summaryrefslogtreecommitdiff
path: root/src/aio
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2018-12-11 16:29:07 -0500
committerRich Felker <dalias@aerifal.cx>2018-12-11 16:29:07 -0500
commit8511511c583cf44ed3aa0bbcaab9168956dce493 (patch)
tree5f080fdce21283e2e9e0c398e035a23f6e51d30f /src/aio
parent1a6d6f131bd60ec2a858b34100049f0c042089f2 (diff)
downloadmusl-8511511c583cf44ed3aa0bbcaab9168956dce493.tar.gz
move aio queue allocation from io thread to submitting thread
since commit c9f415d7ea2dace5bf77f6518b6afc36bb7a5732, it has been possible that the allocator is application-provided code, which cannot necessarily run safely on io thread stacks, and which should not be able to see the existence of io threads, since they are an implementation detail. instead of having the io thread request and possibly allocate its queue (and the map structures leading to it), make the submitting thread responsible for this, and pass the queue pointer into the io thread via its args structure. this eliminates the only early error case in io threads, making it no longer necessary to pass an error status back to the submitting thread via the args structure.
Diffstat (limited to 'src/aio')
-rw-r--r--src/aio/aio.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/src/aio/aio.c b/src/aio/aio.c
index 38943bc0..f7955c44 100644
--- a/src/aio/aio.c
+++ b/src/aio/aio.c
@@ -41,13 +41,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;
@@ -65,6 +58,13 @@ 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;
@@ -196,12 +196,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;
@@ -213,7 +212,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;
@@ -272,9 +270,18 @@ 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 (cb->aio_fildes < 0) errno = EBADF;
+ else errno = EAGAIN;
+ 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;
@@ -291,6 +298,8 @@ 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)) {
+ pthread_mutex_lock(&q->lock);
+ __aio_unref_queue(q);
errno = EAGAIN;
ret = -1;
}
@@ -298,10 +307,6 @@ static int submit(struct aiocb *cb, int op)
if (!ret) {
while (sem_wait(&args.sem));
- if (args.err) {
- errno = args.err;
- ret = -1;
- }
}
return ret;