X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=src%2Faio%2Faio_suspend.c;h=1c1060e340a13cedcbd458c98578ec88c483f4e4;hb=f9827fc7da55c7b03ea5f36598ce8782c03e9d6e;hp=cb2539e9f73cbaa5779311ead215741ae792f085;hpb=b4de6f93aed733b8fc8d103e5ced69ebe7d659e6;p=musl diff --git a/src/aio/aio_suspend.c b/src/aio/aio_suspend.c index cb2539e9..1c1060e3 100644 --- a/src/aio/aio_suspend.c +++ b/src/aio/aio_suspend.c @@ -1,57 +1,79 @@ #include #include +#include +#include "atomic.h" #include "pthread_impl.h" +#include "aio_impl.h" -/* Due to the requirement that aio_suspend be async-signal-safe, we cannot - * use any locks, wait queues, etc. that would make it more efficient. The - * only obviously-correct algorithm is to generate a wakeup every time any - * aio operation finishes and have aio_suspend re-evaluate the completion - * status of each aiocb it was waiting on. */ - -static volatile int seq; - -void __aio_wake(void) -{ - a_inc(&seq); - __wake(&seq, -1, 1); -} - -int aio_suspend(struct aiocb *const cbs[], int cnt, const struct timespec *ts) +int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec *ts) { - int i, last, first=1, ret=0; + int i, tid = 0, ret, expect = 0; struct timespec at; + volatile int dummy_fut, *pfut; + int nzcnt = 0; + const struct aiocb *cb = 0; + + pthread_testcancel(); if (cnt<0) { errno = EINVAL; return -1; } - for (;;) { - last = seq; + for (i=0; i__err != EINPROGRESS) - return 0; + if (ts) { + clock_gettime(CLOCK_MONOTONIC, &at); + at.tv_sec += ts->tv_sec; + if ((at.tv_nsec += ts->tv_nsec) >= 1000000000) { + at.tv_nsec -= 1000000000; + at.tv_sec++; } + } - if (first && ts) { - clock_gettime(CLOCK_MONOTONIC, &at); - at.tv_sec += ts->tv_sec; - if ((at.tv_nsec += ts->tv_nsec) >= 1000000000) { - at.tv_nsec -= 1000000000; - at.tv_sec++; - } - first = 0; - } + for (;;) { + for (i=0; i__err; + expect = EINPROGRESS | 0x80000000; + a_cas(pfut, EINPROGRESS, expect); + break; + default: + pfut = &__aio_fut; + if (!tid) tid = __pthread_self()->tid; + expect = a_cas(pfut, 0, tid); + if (!expect) expect = tid; + /* Need to recheck the predicate before waiting. */ + for (i=0; i