• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <aio.h>
2 #include <errno.h>
3 #include <time.h>
4 #include "atomic.h"
5 #include "pthread_impl.h"
6 
aio_suspend(const struct aiocb * const cbs[],int cnt,const struct timespec * ts)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 #if !_REDIR_TIME64
77 weak_alias(aio_suspend, aio_suspend64);
78 #endif
79