aio_suspend.c raw

   1  #include <aio.h>
   2  #include <errno.h>
   3  #include <time.h>
   4  #include "atomic.h"
   5  #include "pthread_impl.h"
   6  #include "aio_impl.h"
   7  
   8  int 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  
  77  #if !_REDIR_TIME64
  78  weak_alias(aio_suspend, aio_suspend64);
  79  #endif
  80