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