aio_suspend.c 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. #include <aio.h>
  2. #include <errno.h>
  3. #include "pthread_impl.h"
  4. /* Due to the requirement that aio_suspend be async-signal-safe, we cannot
  5. * use any locks, wait queues, etc. that would make it more efficient. The
  6. * only obviously-correct algorithm is to generate a wakeup every time any
  7. * aio operation finishes and have aio_suspend re-evaluate the completion
  8. * status of each aiocb it was waiting on. */
  9. static volatile int seq;
  10. void __aio_wake(void)
  11. {
  12. a_inc(&seq);
  13. __wake(&seq, -1, 1);
  14. }
  15. int aio_suspend(struct aiocb *const cbs[], int cnt, const struct timespec *ts)
  16. {
  17. int i, last, first=1, ret=0;
  18. struct timespec at;
  19. if (cnt<0) {
  20. errno = EINVAL;
  21. return -1;
  22. }
  23. for (;;) {
  24. last = seq;
  25. for (i=0; i<cnt; i++) {
  26. if (cbs[i] && cbs[i]->__err != EINPROGRESS)
  27. return 0;
  28. }
  29. if (first && 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. first = 0;
  37. }
  38. ret = __timedwait(&seq, last, CLOCK_MONOTONIC,
  39. ts ? &at : 0, 0, 0, 1);
  40. if (ret == ETIMEDOUT) ret = EAGAIN;
  41. if (ret) {
  42. errno = ret;
  43. return -1;
  44. }
  45. }
  46. }