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