blob: 08fb5ddcf1a7b1450fb7446d9e8be202eaa1f42a [file] [log] [blame]
Rich Felkerb4de6f92011-09-09 01:07:38 -04001#include <aio.h>
2#include <errno.h>
Rich Felker4e8a3562015-02-13 00:27:45 -05003#include <time.h>
4#include "atomic.h"
Szabolcs Nagy36c30c42014-09-04 22:01:36 +02005#include "libc.h"
Rich Felker4e8a3562015-02-13 00:27:45 -05006#include "pthread_impl.h"
Rich Felkerb4de6f92011-09-09 01:07:38 -04007
Rich Felker4e8a3562015-02-13 00:27:45 -05008extern volatile int __aio_fut;
Rich Felkerb4de6f92011-09-09 01:07:38 -04009
Rich Felker13cd9692011-09-13 21:09:35 -040010int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec *ts)
Rich Felkerb4de6f92011-09-09 01:07:38 -040011{
Rich Felker4e8a3562015-02-13 00:27:45 -050012 int i, tid = 0, ret, expect = 0;
Rich Felkerb4de6f92011-09-09 01:07:38 -040013 struct timespec at;
Rich Felker4e8a3562015-02-13 00:27:45 -050014 volatile int dummy_fut, *pfut;
15 int nzcnt = 0;
16 const struct aiocb *cb = 0;
Rich Felkerb4de6f92011-09-09 01:07:38 -040017
Rich Felker5451d952015-03-02 18:11:28 -050018 pthread_testcancel();
19
Rich Felkerb4de6f92011-09-09 01:07:38 -040020 if (cnt<0) {
21 errno = EINVAL;
22 return -1;
23 }
24
Rich Felker4e8a3562015-02-13 00:27:45 -050025 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
Rich Felkerb4de6f92011-09-09 01:07:38 -040040 for (;;) {
Rich Felker4e8a3562015-02-13 00:27:45 -050041 for (i=0; i<cnt; i++)
42 if (cbs[i] && aio_error(cbs[i]) != EINPROGRESS)
Rich Felkerb4de6f92011-09-09 01:07:38 -040043 return 0;
Rich Felker4e8a3562015-02-13 00:27:45 -050044
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;
Rich Felkerb4de6f92011-09-09 01:07:38 -040064 }
65
Rich Felker5451d952015-03-02 18:11:28 -050066 ret = __timedwait_cp(pfut, expect, CLOCK_MONOTONIC, ts?&at:0, 1);
Rich Felkerb4de6f92011-09-09 01:07:38 -040067
Rich Felker5451d952015-03-02 18:11:28 -050068 switch (ret) {
69 case ETIMEDOUT:
70 ret = EAGAIN;
71 case ECANCELED:
72 case EINTR:
73 errno = ret;
Rich Felkerb4de6f92011-09-09 01:07:38 -040074 return -1;
75 }
76 }
77}
Szabolcs Nagy36c30c42014-09-04 22:01:36 +020078
79LFS64(aio_suspend);