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