X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Faio%2Faio.c;h=a1a3e7914b02e138fa5aedd3eb8c7e6aa0d19f1f;hb=122002f0ddf267977282f05066a0794e31661501;hp=a5f6443299d4a5c1298bda57fc4fc8f21c414aaa;hpb=5ce3737931bb411a8d167356d4d0287b53b0cbdc;p=musl diff --git a/src/aio/aio.c b/src/aio/aio.c index a5f64432..a1a3e791 100644 --- a/src/aio/aio.c +++ b/src/aio/aio.c @@ -5,9 +5,16 @@ #include #include #include +#include #include "syscall.h" #include "atomic.h" #include "pthread_impl.h" +#include "aio_impl.h" + +#define malloc __libc_malloc +#define calloc __libc_calloc +#define realloc __libc_realloc +#define free __libc_free /* The following is a threads-based implementation of AIO with minimal * dependence on implementation details. Most synchronization is @@ -40,13 +47,6 @@ * blocked permanently. */ -struct aio_args { - struct aiocb *cb; - int op; - int err; - sem_t sem; -}; - struct aio_thread { pthread_t td; struct aiocb *cb; @@ -64,21 +64,40 @@ struct aio_queue { struct aio_thread *head; }; +struct aio_args { + struct aiocb *cb; + struct aio_queue *q; + int op; + sem_t sem; +}; + static pthread_rwlock_t maplock = PTHREAD_RWLOCK_INITIALIZER; static struct aio_queue *****map; static volatile int aio_fd_cnt; volatile int __aio_fut; +static size_t io_thread_stack_size; + +#define MAX(a,b) ((a)>(b) ? (a) : (b)) + static struct aio_queue *__aio_get_queue(int fd, int need) { - if (fd < 0) return 0; + if (fd < 0) { + errno = EBADF; + return 0; + } int a=fd>>24; unsigned char b=fd>>16, c=fd>>8, d=fd; struct aio_queue *q = 0; pthread_rwlock_rdlock(&maplock); if ((!map || !map[a] || !map[a][b] || !map[a][b][c] || !(q=map[a][b][c][d])) && need) { pthread_rwlock_unlock(&maplock); + if (fcntl(fd, F_GETFD) < 0) return 0; pthread_rwlock_wrlock(&maplock); + if (!io_thread_stack_size) { + unsigned long val = __getauxval(AT_MINSIGSTKSZ); + io_thread_stack_size = MAX(MINSIGSTKSZ+2048, val+512); + } if (!map) map = calloc(sizeof *map, (-1U/2+1)>>24); if (!map) goto out; if (!map[a]) map[a] = calloc(sizeof **map, 256); @@ -195,12 +214,11 @@ static void *io_thread_func(void *ctx) size_t len = cb->aio_nbytes; off_t off = cb->aio_offset; - struct aio_queue *q = __aio_get_queue(fd, 1); + struct aio_queue *q = args->q; ssize_t ret; - args->err = q ? 0 : EAGAIN; + pthread_mutex_lock(&q->lock); sem_post(&args->sem); - if (!q) return 0; at.op = op; at.running = 1; @@ -212,7 +230,6 @@ static void *io_thread_func(void *ctx) at.prev = 0; if ((at.next = q->head)) at.next->prev = &at; q->head = &at; - q->ref++; if (!q->init) { int seekable = lseek(fd, 0, SEEK_CUR) >= 0; @@ -262,9 +279,19 @@ static int submit(struct aiocb *cb, int op) pthread_attr_t a; sigset_t allmask, origmask; pthread_t td; - struct aio_args args = { .cb = cb, .op = op }; + struct aio_queue *q = __aio_get_queue(cb->aio_fildes, 1); + struct aio_args args = { .cb = cb, .op = op, .q = q }; sem_init(&args.sem, 0, 0); + if (!q) { + if (errno != EBADF) errno = EAGAIN; + cb->__ret = -1; + cb->__err = errno; + return -1; + } + q->ref++; + pthread_mutex_unlock(&q->lock); + if (cb->aio_sigevent.sigev_notify == SIGEV_THREAD) { if (cb->aio_sigevent.sigev_notify_attributes) a = *cb->aio_sigevent.sigev_notify_attributes; @@ -272,7 +299,7 @@ static int submit(struct aiocb *cb, int op) pthread_attr_init(&a); } else { pthread_attr_init(&a); - pthread_attr_setstacksize(&a, PTHREAD_STACK_MIN); + pthread_attr_setstacksize(&a, io_thread_stack_size); pthread_attr_setguardsize(&a, 0); } pthread_attr_setdetachstate(&a, PTHREAD_CREATE_DETACHED); @@ -280,17 +307,15 @@ static int submit(struct aiocb *cb, int op) pthread_sigmask(SIG_BLOCK, &allmask, &origmask); cb->__err = EINPROGRESS; if (pthread_create(&td, &a, io_thread_func, &args)) { - errno = EAGAIN; - ret = -1; + pthread_mutex_lock(&q->lock); + __aio_unref_queue(q); + cb->__err = errno = EAGAIN; + cb->__ret = ret = -1; } pthread_sigmask(SIG_SETMASK, &origmask, 0); if (!ret) { while (sem_wait(&args.sem)); - if (args.err) { - errno = args.err; - ret = -1; - } } return ret; @@ -342,8 +367,9 @@ int aio_cancel(int fd, struct aiocb *cb) sigfillset(&allmask); pthread_sigmask(SIG_BLOCK, &allmask, &origmask); + errno = ENOENT; if (!(q = __aio_get_queue(fd, 0))) { - if (fcntl(fd, F_GETFD) < 0) ret = -1; + if (errno == EBADF) ret = -1; goto done; } @@ -370,9 +396,23 @@ int __aio_close(int fd) return fd; } -LFS64(aio_cancel); -LFS64(aio_error); -LFS64(aio_fsync); -LFS64(aio_read); -LFS64(aio_write); -LFS64(aio_return); +void __aio_atfork(int who) +{ + if (who<0) { + pthread_rwlock_rdlock(&maplock); + return; + } + if (who>0 && map) for (int a=0; a<(-1U/2+1)>>24; a++) + if (map[a]) for (int b=0; b<256; b++) + if (map[a][b]) for (int c=0; c<256; c++) + if (map[a][b][c]) for (int d=0; d<256; d++) + map[a][b][c][d] = 0; + pthread_rwlock_unlock(&maplock); +} + +weak_alias(aio_cancel, aio_cancel64); +weak_alias(aio_error, aio_error64); +weak_alias(aio_fsync, aio_fsync64); +weak_alias(aio_read, aio_read64); +weak_alias(aio_write, aio_write64); +weak_alias(aio_return, aio_return64);