wait-queue.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * Copyright 2023 Red Hat
  4. */
  5. #ifndef VDO_WAIT_QUEUE_H
  6. #define VDO_WAIT_QUEUE_H
  7. #include <linux/compiler.h>
  8. #include <linux/types.h>
  9. /**
  10. * A vdo_wait_queue is a circular singly linked list of entries waiting to be notified
  11. * of a change in a condition. Keeping a circular list allows the vdo_wait_queue
  12. * structure to simply be a pointer to the tail (newest) entry, supporting
  13. * constant-time enqueue and dequeue operations. A null pointer is an empty waitq.
  14. *
  15. * An empty waitq:
  16. * waitq0.last_waiter -> NULL
  17. *
  18. * A singleton waitq:
  19. * waitq1.last_waiter -> entry1 -> entry1 -> [...]
  20. *
  21. * A three-element waitq:
  22. * waitq2.last_waiter -> entry3 -> entry1 -> entry2 -> entry3 -> [...]
  23. *
  24. * linux/wait.h's wait_queue_head is _not_ used because vdo_wait_queue's
  25. * interface is much less complex (doesn't need locking, priorities or timers).
  26. * Made possible by vdo's thread-based resource allocation and locking; and
  27. * the polling nature of vdo_wait_queue consumers.
  28. *
  29. * FIXME: could be made to use a linux/list.h's list_head but its extra barriers
  30. * really aren't needed. Nor is a doubly linked list, but vdo_wait_queue could
  31. * make use of __list_del_clearprev() -- but that would compromise the ability
  32. * to make full use of linux's list interface.
  33. */
  34. struct vdo_waiter;
  35. struct vdo_wait_queue {
  36. /* The tail of the queue, the last (most recently added) entry */
  37. struct vdo_waiter *last_waiter;
  38. /* The number of waiters currently in the queue */
  39. size_t length;
  40. };
  41. /**
  42. * vdo_waiter_callback_fn - Callback type that will be called to resume processing
  43. * of a waiter after it has been removed from its wait queue.
  44. */
  45. typedef void (*vdo_waiter_callback_fn)(struct vdo_waiter *waiter, void *context);
  46. /**
  47. * vdo_waiter_match_fn - Method type for waiter matching methods.
  48. *
  49. * Returns false if the waiter does not match.
  50. */
  51. typedef bool (*vdo_waiter_match_fn)(struct vdo_waiter *waiter, void *context);
  52. /* The structure for entries in a vdo_wait_queue. */
  53. struct vdo_waiter {
  54. /*
  55. * The next waiter in the waitq. If this entry is the last waiter, then this
  56. * is actually a pointer back to the head of the waitq.
  57. */
  58. struct vdo_waiter *next_waiter;
  59. /* Optional waiter-specific callback to invoke when dequeuing this waiter. */
  60. vdo_waiter_callback_fn callback;
  61. };
  62. /**
  63. * vdo_waiter_is_waiting() - Check whether a waiter is waiting.
  64. * @waiter: The waiter to check.
  65. *
  66. * Return: true if the waiter is on some vdo_wait_queue.
  67. */
  68. static inline bool vdo_waiter_is_waiting(struct vdo_waiter *waiter)
  69. {
  70. return (waiter->next_waiter != NULL);
  71. }
  72. /**
  73. * vdo_waitq_init() - Initialize a vdo_wait_queue.
  74. * @waitq: The vdo_wait_queue to initialize.
  75. */
  76. static inline void vdo_waitq_init(struct vdo_wait_queue *waitq)
  77. {
  78. *waitq = (struct vdo_wait_queue) {
  79. .last_waiter = NULL,
  80. .length = 0,
  81. };
  82. }
  83. /**
  84. * vdo_waitq_has_waiters() - Check whether a vdo_wait_queue has any entries waiting.
  85. * @waitq: The vdo_wait_queue to query.
  86. *
  87. * Return: true if there are any waiters in the waitq.
  88. */
  89. static inline bool __must_check vdo_waitq_has_waiters(const struct vdo_wait_queue *waitq)
  90. {
  91. return (waitq->last_waiter != NULL);
  92. }
  93. void vdo_waitq_enqueue_waiter(struct vdo_wait_queue *waitq,
  94. struct vdo_waiter *waiter);
  95. struct vdo_waiter *vdo_waitq_dequeue_waiter(struct vdo_wait_queue *waitq);
  96. void vdo_waitq_notify_all_waiters(struct vdo_wait_queue *waitq,
  97. vdo_waiter_callback_fn callback, void *context);
  98. bool vdo_waitq_notify_next_waiter(struct vdo_wait_queue *waitq,
  99. vdo_waiter_callback_fn callback, void *context);
  100. void vdo_waitq_transfer_all_waiters(struct vdo_wait_queue *from_waitq,
  101. struct vdo_wait_queue *to_waitq);
  102. struct vdo_waiter *vdo_waitq_get_first_waiter(const struct vdo_wait_queue *waitq);
  103. void vdo_waitq_dequeue_matching_waiters(struct vdo_wait_queue *waitq,
  104. vdo_waiter_match_fn waiter_match,
  105. void *match_context,
  106. struct vdo_wait_queue *matched_waitq);
  107. /**
  108. * vdo_waitq_num_waiters() - Return the number of waiters in a vdo_wait_queue.
  109. * @waitq: The vdo_wait_queue to query.
  110. *
  111. * Return: The number of waiters in the waitq.
  112. */
  113. static inline size_t __must_check vdo_waitq_num_waiters(const struct vdo_wait_queue *waitq)
  114. {
  115. return waitq->length;
  116. }
  117. #endif /* VDO_WAIT_QUEUE_H */