completion.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "completion.h"
  3. void completion_init(struct completion *p)
  4. {
  5. p->completed = 0;
  6. p->completed_jobs = 0;
  7. fatal_assert(0 == uv_cond_init(&p->cond));
  8. fatal_assert(0 == uv_mutex_init(&p->mutex));
  9. }
  10. void completion_destroy(struct completion *p)
  11. {
  12. uv_cond_destroy(&p->cond);
  13. uv_mutex_destroy(&p->mutex);
  14. }
  15. void completion_wait_for(struct completion *p)
  16. {
  17. uv_mutex_lock(&p->mutex);
  18. while (0 == p->completed) {
  19. uv_cond_wait(&p->cond, &p->mutex);
  20. }
  21. fatal_assert(1 == p->completed);
  22. uv_mutex_unlock(&p->mutex);
  23. }
  24. bool completion_timedwait_for(struct completion *p, uint64_t timeout)
  25. {
  26. timeout *= NSEC_PER_SEC;
  27. uint64_t start_time = uv_hrtime();
  28. bool result = true;
  29. uv_mutex_lock(&p->mutex);
  30. while (!p->completed) {
  31. int rc = uv_cond_timedwait(&p->cond, &p->mutex, timeout);
  32. if (rc == 0) {
  33. result = true;
  34. break;
  35. } else if (rc == UV_ETIMEDOUT) {
  36. result = false;
  37. break;
  38. }
  39. /*
  40. * handle spurious wakeups
  41. */
  42. uint64_t elapsed = uv_hrtime() - start_time;
  43. if (elapsed >= timeout) {
  44. result = false;
  45. break;
  46. }
  47. timeout -= elapsed;
  48. }
  49. uv_mutex_unlock(&p->mutex);
  50. return result;
  51. }
  52. void completion_mark_complete(struct completion *p)
  53. {
  54. uv_mutex_lock(&p->mutex);
  55. p->completed = 1;
  56. uv_cond_broadcast(&p->cond);
  57. uv_mutex_unlock(&p->mutex);
  58. }
  59. unsigned completion_wait_for_a_job(struct completion *p, unsigned completed_jobs)
  60. {
  61. uv_mutex_lock(&p->mutex);
  62. while (0 == p->completed && p->completed_jobs <= completed_jobs) {
  63. uv_cond_wait(&p->cond, &p->mutex);
  64. }
  65. completed_jobs = p->completed_jobs;
  66. uv_mutex_unlock(&p->mutex);
  67. return completed_jobs;
  68. }
  69. void completion_mark_complete_a_job(struct completion *p)
  70. {
  71. uv_mutex_lock(&p->mutex);
  72. p->completed_jobs++;
  73. uv_cond_broadcast(&p->cond);
  74. uv_mutex_unlock(&p->mutex);
  75. }
  76. bool completion_is_done(struct completion *p)
  77. {
  78. bool ret;
  79. uv_mutex_lock(&p->mutex);
  80. ret = p->completed;
  81. uv_mutex_unlock(&p->mutex);
  82. return ret;
  83. }