• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <aio.h>
2 #include <errno.h>
3 #include <time.h>
4 #include <unsupported_api.h>
5 #include "atomic.h"
6 #include "pthread_impl.h"
7 #include "aio_impl.h"
8 
aio_suspend(const struct aiocb * const cbs[],int cnt,const struct timespec * ts)9 int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec *ts)
10 {
11 	int i, tid = 0, ret, expect = 0;
12 	struct timespec at;
13 	volatile int dummy_fut = 0, *pfut;
14 	int nzcnt = 0;
15 	const struct aiocb *cb = 0;
16 
17 	UNSUPPORTED_API_VOID(LITEOS_A);
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 #if !_REDIR_TIME64
80 weak_alias(aio_suspend, aio_suspend64);
81 #endif
82