diff options
Diffstat (limited to 'src/aio')
-rw-r--r-- | src/aio/aio.c | 64 | ||||
-rw-r--r-- | src/aio/aio_suspend.c | 7 | ||||
-rw-r--r-- | src/aio/lio_listio.c | 2 |
3 files changed, 50 insertions, 23 deletions
diff --git a/src/aio/aio.c b/src/aio/aio.c index 6d34fa86..d7e063bf 100644 --- a/src/aio/aio.c +++ b/src/aio/aio.c @@ -9,6 +9,12 @@ #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 @@ -70,8 +76,14 @@ 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) { + sigset_t allmask, origmask; + int masked = 0; if (fd < 0) { errno = EBADF; return 0; @@ -83,7 +95,14 @@ static struct aio_queue *__aio_get_queue(int fd, int need) 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; + sigfillset(&allmask); + masked = 1; + pthread_sigmask(SIG_BLOCK, &allmask, &origmask); 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); @@ -105,6 +124,7 @@ static struct aio_queue *__aio_get_queue(int fd, int need) if (q) pthread_mutex_lock(&q->lock); out: pthread_rwlock_unlock(&maplock); + if (masked) pthread_sigmask(SIG_SETMASK, &origmask, 0); return q; } @@ -259,15 +279,6 @@ static void *io_thread_func(void *ctx) return 0; } -static size_t io_thread_stack_size = MINSIGSTKSZ+2048; -static pthread_once_t init_stack_size_once; - -static void init_stack_size() -{ - unsigned long val = __getauxval(AT_MINSIGSTKSZ); - if (val > MINSIGSTKSZ) io_thread_stack_size = val + 512; -} - static int submit(struct aiocb *cb, int op) { int ret = 0; @@ -293,7 +304,6 @@ static int submit(struct aiocb *cb, int op) else pthread_attr_init(&a); } else { - pthread_once(&init_stack_size_once, init_stack_size); pthread_attr_init(&a); pthread_attr_setstacksize(&a, io_thread_stack_size); pthread_attr_setguardsize(&a, 0); @@ -392,9 +402,31 @@ int __aio_close(int fd) return fd; } -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); +void __aio_atfork(int who) +{ + if (who<0) { + pthread_rwlock_rdlock(&maplock); + return; + } else if (!who) { + pthread_rwlock_unlock(&maplock); + return; + } + aio_fd_cnt = 0; + if (pthread_rwlock_tryrdlock(&maplock)) { + /* Obtaining lock may fail if _Fork was called nor via + * fork. In this case, no further aio is possible from + * child and we can just null out map so __aio_close + * does not attempt to do anything. */ + map = 0; + return; + } + if (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; + /* Re-initialize the rwlock rather than unlocking since there + * may have been more than one reference on it in the parent. + * We are not a lock holder anyway; the thread in the parent was. */ + pthread_rwlock_init(&maplock, 0); +} diff --git a/src/aio/aio_suspend.c b/src/aio/aio_suspend.c index 34b66f87..1f0c9aaa 100644 --- a/src/aio/aio_suspend.c +++ b/src/aio/aio_suspend.c @@ -3,12 +3,13 @@ #include <time.h> #include "atomic.h" #include "pthread_impl.h" +#include "aio_impl.h" int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec *ts) { int i, tid = 0, ret, expect = 0; struct timespec at; - volatile int dummy_fut, *pfut; + volatile int dummy_fut = 0, *pfut; int nzcnt = 0; const struct aiocb *cb = 0; @@ -72,7 +73,3 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec } } } - -#if !_REDIR_TIME64 -weak_alias(aio_suspend, aio_suspend64); -#endif diff --git a/src/aio/lio_listio.c b/src/aio/lio_listio.c index 0799c15d..a672812f 100644 --- a/src/aio/lio_listio.c +++ b/src/aio/lio_listio.c @@ -139,5 +139,3 @@ int lio_listio(int mode, struct aiocb *restrict const *restrict cbs, int cnt, st return 0; } - -weak_alias(lio_listio, lio_listio64); |