github.com/afumu/libc@v0.0.6/musl/src/aio/aio_suspend.c (about) 1 #include <aio.h> 2 #include <errno.h> 3 #include <time.h> 4 #include "atomic.h" 5 #include "pthread_impl.h" 6 7 int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec *ts) 8 { 9 int i, tid = 0, ret, expect = 0; 10 struct timespec at; 11 volatile int dummy_fut, *pfut; 12 int nzcnt = 0; 13 const struct aiocb *cb = 0; 14 15 pthread_testcancel(); 16 17 if (cnt<0) { 18 errno = EINVAL; 19 return -1; 20 } 21 22 for (i=0; i<cnt; i++) if (cbs[i]) { 23 if (aio_error(cbs[i]) != EINPROGRESS) return 0; 24 nzcnt++; 25 cb = cbs[i]; 26 } 27 28 if (ts) { 29 clock_gettime(CLOCK_MONOTONIC, &at); 30 at.tv_sec += ts->tv_sec; 31 if ((at.tv_nsec += ts->tv_nsec) >= 1000000000) { 32 at.tv_nsec -= 1000000000; 33 at.tv_sec++; 34 } 35 } 36 37 for (;;) { 38 for (i=0; i<cnt; i++) 39 if (cbs[i] && aio_error(cbs[i]) != EINPROGRESS) 40 return 0; 41 42 switch (nzcnt) { 43 case 0: 44 pfut = &dummy_fut; 45 break; 46 case 1: 47 pfut = (void *)&cb->__err; 48 expect = EINPROGRESS | 0x80000000; 49 a_cas(pfut, EINPROGRESS, expect); 50 break; 51 default: 52 pfut = &__aio_fut; 53 if (!tid) tid = __pthread_self()->tid; 54 expect = a_cas(pfut, 0, tid); 55 if (!expect) expect = tid; 56 /* Need to recheck the predicate before waiting. */ 57 for (i=0; i<cnt; i++) 58 if (cbs[i] && aio_error(cbs[i]) != EINPROGRESS) 59 return 0; 60 break; 61 } 62 63 ret = __timedwait_cp(pfut, expect, CLOCK_MONOTONIC, ts?&at:0, 1); 64 65 switch (ret) { 66 case ETIMEDOUT: 67 ret = EAGAIN; 68 case ECANCELED: 69 case EINTR: 70 errno = ret; 71 return -1; 72 } 73 } 74 } 75 76 #if !_REDIR_TIME64 77 weak_alias(aio_suspend, aio_suspend64); 78 #endif