github.com/afumu/libc@v0.0.6/musl/src/aio/aio_suspend.c (about)

     1  #include <aio.h>
     2  #include <errno.h>
     3  #include <time.h>
     4  #include "atomic.h"
     5  #include "pthread_impl.h"
     6  
     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