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