aio_suspend.c 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  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. 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 = 0, *pfut;
  12. int nzcnt = 0;
  13. const struct aiocb *cb = 0;
  14. pthread_testcancel();
  15. if (cnt<0) {
  16. errno = EINVAL;
  17. return -1;
  18. }
  19. for (i=0; i<cnt; i++) if (cbs[i]) {
  20. if (aio_error(cbs[i]) != EINPROGRESS) return 0;
  21. nzcnt++;
  22. cb = cbs[i];
  23. }
  24. if (ts) {
  25. clock_gettime(CLOCK_MONOTONIC, &at);
  26. at.tv_sec += ts->tv_sec;
  27. if ((at.tv_nsec += ts->tv_nsec) >= 1000000000) {
  28. at.tv_nsec -= 1000000000;
  29. at.tv_sec++;
  30. }
  31. }
  32. for (;;) {
  33. for (i=0; i<cnt; i++)
  34. if (cbs[i] && aio_error(cbs[i]) != EINPROGRESS)
  35. return 0;
  36. switch (nzcnt) {
  37. case 0:
  38. pfut = &dummy_fut;
  39. break;
  40. case 1:
  41. pfut = (void *)&cb->__err;
  42. expect = EINPROGRESS | 0x80000000;
  43. a_cas(pfut, EINPROGRESS, expect);
  44. break;
  45. default:
  46. pfut = &__aio_fut;
  47. if (!tid) tid = __pthread_self()->tid;
  48. expect = a_cas(pfut, 0, tid);
  49. if (!expect) expect = tid;
  50. /* Need to recheck the predicate before waiting. */
  51. for (i=0; i<cnt; i++)
  52. if (cbs[i] && aio_error(cbs[i]) != EINPROGRESS)
  53. return 0;
  54. break;
  55. }
  56. ret = __timedwait_cp(pfut, expect, CLOCK_MONOTONIC, ts?&at:0, 1);
  57. switch (ret) {
  58. case ETIMEDOUT:
  59. ret = EAGAIN;
  60. case ECANCELED:
  61. case EINTR:
  62. errno = ret;
  63. return -1;
  64. }
  65. }
  66. }