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