sleepq.h 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright (c) 2017-2018 Richard Braun.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. *
  18. * Generic sleep queues.
  19. *
  20. * Sleep queues are used to build sleeping synchronization primitives
  21. * such as mutexes and condition variables.
  22. *
  23. * Although the sleep queues are mostly generic, this implementation
  24. * relies on knowing whether a synchronization object is a condition
  25. * variable or not, because waiting on a condition variable unlocks
  26. * the associated mutex, at which point two sleep queues are locked.
  27. * Handling condition variable sleep queues slightly differently
  28. * allows preventing deadlocks while keeping overall complexity low.
  29. */
  30. #ifndef KERN_SLEEPQ_H
  31. #define KERN_SLEEPQ_H
  32. #include <stdbool.h>
  33. #include <stdint.h>
  34. #include <kern/init.h>
  35. struct sleepq;
  36. /*
  37. * Create/destroy a sleep queue.
  38. */
  39. struct sleepq * sleepq_create(void);
  40. void sleepq_destroy(struct sleepq *sleepq);
  41. /*
  42. * Acquire/release a sleep queue.
  43. *
  44. * Acquiring a sleep queue serializes all access and disables preemption.
  45. *
  46. * The condition argument must be true if the synchronization object
  47. * is a condition variable.
  48. *
  49. * If no sleep queue has been lent for the synchronization object, NULL
  50. * is returned. Note that, in the case of the non-blocking variant,
  51. * the call may also return NULL if internal state shared by unrelated
  52. * synchronization objects is locked.
  53. */
  54. struct sleepq * sleepq_acquire(const void *sync_obj, bool condition);
  55. struct sleepq * sleepq_tryacquire(const void *sync_obj, bool condition);
  56. void sleepq_release(struct sleepq *sleepq);
  57. /*
  58. * Versions of the sleep queue acquisition functions that also disable
  59. * interrupts.
  60. */
  61. struct sleepq * sleepq_acquire_intr_save(const void *sync_obj,
  62. bool condition,
  63. unsigned long *flags);
  64. struct sleepq * sleepq_tryacquire_intr_save(const void *sync_obj,
  65. bool condition,
  66. unsigned long *flags);
  67. void sleepq_release_intr_restore(struct sleepq *sleepq,
  68. unsigned long flags);
  69. /*
  70. * Lend/return a sleep queue.
  71. *
  72. * Most often, a thread lends its private sleep queue to the sleepq
  73. * module in order to prepare its sleep. The sleep queue obtained
  74. * on lending is either the thread's queue, or an already existing
  75. * queue for this synchronization object if another thread is waiting.
  76. *
  77. * When multiple threads lend their sleep queue for the same synchronization
  78. * object, the extra queues lent are kept in an internal free list, used
  79. * when threads are awoken to return a queue to them. As a result, the
  80. * sleep queue returned may not be the one lent.
  81. *
  82. * The sleep queue obtained when lending is automatically acquired.
  83. *
  84. * The condition argument must be true if the synchronization object
  85. * is a condition variable.
  86. */
  87. struct sleepq * sleepq_lend(const void *sync_obj, bool condition);
  88. void sleepq_return(struct sleepq *sleepq);
  89. /*
  90. * Versions of the sleep queue lending functions that also disable
  91. * interrupts.
  92. */
  93. struct sleepq * sleepq_lend_intr_save(const void *sync_obj, bool condition,
  94. unsigned long *flags);
  95. void sleepq_return_intr_restore(struct sleepq *sleepq, unsigned long flags);
  96. /*
  97. * Return true if the given sleep queue has no waiters.
  98. *
  99. * The sleep queue must be acquired when calling this function.
  100. */
  101. bool sleepq_empty(const struct sleepq *sleepq);
  102. /*
  103. * Wait for a wake-up on the given sleep queue.
  104. *
  105. * The sleep queue must be lent when calling this function. It is
  106. * released and later reacquired before returning from this function.
  107. *
  108. * The calling thread is considered a waiter as long as it didn't
  109. * reacquire the sleep queue. This means that signalling a sleep queue
  110. * has no visible effect on the number of waiters until the queue is
  111. * released, e.g. if a single thread is waiting and another signals
  112. * the queue, the queue is not immediately considered empty.
  113. *
  114. * When bounding the duration of the wait, the caller must pass an absolute
  115. * time in ticks, and ETIMEDOUT is returned if that time is reached before
  116. * the sleep queue is signalled.
  117. */
  118. void sleepq_wait(struct sleepq *sleepq, const char *wchan);
  119. int sleepq_timedwait(struct sleepq *sleepq, const char *wchan, uint64_t ticks);
  120. /*
  121. * Wake up a thread waiting on the given sleep queue, if any.
  122. *
  123. * The sleep queue must be acquired when calling this function.
  124. * A sleep queue may be signalled from interrupt context.
  125. *
  126. * Since a sleep queue must be lent (and in turn is automatically
  127. * acquired) when waiting, and acquired in order to signal it,
  128. * wake-ups are serialized and cannot be missed.
  129. *
  130. * At least one thread is awoken if any threads are waiting on the sleep
  131. * queue.
  132. *
  133. * Broadcasting a sleep queue wakes up all waiting threads.
  134. */
  135. void sleepq_signal(struct sleepq *sleepq);
  136. void sleepq_broadcast(struct sleepq *sleepq);
  137. /*
  138. * This init operation provides :
  139. * - sleepq creation
  140. * - module fully initialized
  141. */
  142. INIT_OP_DECLARE(sleepq_setup);
  143. #endif /* KERN_SLEEPQ_H */