OLD | NEW |
(Empty) | |
| 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 |
| 8 extern volatile int __aio_fut; |
| 9 |
| 10 int 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 |
| 79 LFS64(aio_suspend); |
OLD | NEW |