add missing m68k relocation types in elf.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 "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);