]> git.proxmox.com Git - wasi-libc.git/blame - libc-top-half/musl/src/aio/aio_suspend.c
Update to musl 1.2.2.
[wasi-libc.git] / libc-top-half / musl / src / aio / aio_suspend.c
CommitLineData
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
8int 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 78weak_alias(aio_suspend, aio_suspend64);
575e1579 79#endif