swait.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * <linux/swait.h> (simple wait queues ) implementation:
  4. */
  5. #include "sched.h"
  6. void __init_swait_queue_head(struct swait_queue_head *q, const char *name,
  7. struct lock_class_key *key)
  8. {
  9. raw_spin_lock_init(&q->lock);
  10. lockdep_set_class_and_name(&q->lock, key, name);
  11. INIT_LIST_HEAD(&q->task_list);
  12. }
  13. EXPORT_SYMBOL(__init_swait_queue_head);
  14. /*
  15. * The thing about the wake_up_state() return value; I think we can ignore it.
  16. *
  17. * If for some reason it would return 0, that means the previously waiting
  18. * task is already running, so it will observe condition true (or has already).
  19. */
  20. void swake_up_locked(struct swait_queue_head *q)
  21. {
  22. struct swait_queue *curr;
  23. if (list_empty(&q->task_list))
  24. return;
  25. curr = list_first_entry(&q->task_list, typeof(*curr), task_list);
  26. wake_up_process(curr->task);
  27. list_del_init(&curr->task_list);
  28. }
  29. EXPORT_SYMBOL(swake_up_locked);
  30. /*
  31. * Wake up all waiters. This is an interface which is solely exposed for
  32. * completions and not for general usage.
  33. *
  34. * It is intentionally different from swake_up_all() to allow usage from
  35. * hard interrupt context and interrupt disabled regions.
  36. */
  37. void swake_up_all_locked(struct swait_queue_head *q)
  38. {
  39. while (!list_empty(&q->task_list))
  40. swake_up_locked(q);
  41. }
  42. void swake_up_one(struct swait_queue_head *q)
  43. {
  44. unsigned long flags;
  45. raw_spin_lock_irqsave(&q->lock, flags);
  46. swake_up_locked(q);
  47. raw_spin_unlock_irqrestore(&q->lock, flags);
  48. }
  49. EXPORT_SYMBOL(swake_up_one);
  50. /*
  51. * Does not allow usage from IRQ disabled, since we must be able to
  52. * release IRQs to guarantee bounded hold time.
  53. */
  54. void swake_up_all(struct swait_queue_head *q)
  55. {
  56. struct swait_queue *curr;
  57. LIST_HEAD(tmp);
  58. raw_spin_lock_irq(&q->lock);
  59. list_splice_init(&q->task_list, &tmp);
  60. while (!list_empty(&tmp)) {
  61. curr = list_first_entry(&tmp, typeof(*curr), task_list);
  62. wake_up_state(curr->task, TASK_NORMAL);
  63. list_del_init(&curr->task_list);
  64. if (list_empty(&tmp))
  65. break;
  66. raw_spin_unlock_irq(&q->lock);
  67. raw_spin_lock_irq(&q->lock);
  68. }
  69. raw_spin_unlock_irq(&q->lock);
  70. }
  71. EXPORT_SYMBOL(swake_up_all);
  72. void __prepare_to_swait(struct swait_queue_head *q, struct swait_queue *wait)
  73. {
  74. wait->task = current;
  75. if (list_empty(&wait->task_list))
  76. list_add_tail(&wait->task_list, &q->task_list);
  77. }
  78. void prepare_to_swait_exclusive(struct swait_queue_head *q, struct swait_queue *wait, int state)
  79. {
  80. unsigned long flags;
  81. raw_spin_lock_irqsave(&q->lock, flags);
  82. __prepare_to_swait(q, wait);
  83. set_current_state(state);
  84. raw_spin_unlock_irqrestore(&q->lock, flags);
  85. }
  86. EXPORT_SYMBOL(prepare_to_swait_exclusive);
  87. long prepare_to_swait_event(struct swait_queue_head *q, struct swait_queue *wait, int state)
  88. {
  89. unsigned long flags;
  90. long ret = 0;
  91. raw_spin_lock_irqsave(&q->lock, flags);
  92. if (signal_pending_state(state, current)) {
  93. /*
  94. * See prepare_to_wait_event(). TL;DR, subsequent swake_up_one()
  95. * must not see us.
  96. */
  97. list_del_init(&wait->task_list);
  98. ret = -ERESTARTSYS;
  99. } else {
  100. __prepare_to_swait(q, wait);
  101. set_current_state(state);
  102. }
  103. raw_spin_unlock_irqrestore(&q->lock, flags);
  104. return ret;
  105. }
  106. EXPORT_SYMBOL(prepare_to_swait_event);
  107. void __finish_swait(struct swait_queue_head *q, struct swait_queue *wait)
  108. {
  109. __set_current_state(TASK_RUNNING);
  110. if (!list_empty(&wait->task_list))
  111. list_del_init(&wait->task_list);
  112. }
  113. void finish_swait(struct swait_queue_head *q, struct swait_queue *wait)
  114. {
  115. unsigned long flags;
  116. __set_current_state(TASK_RUNNING);
  117. if (!list_empty_careful(&wait->task_list)) {
  118. raw_spin_lock_irqsave(&q->lock, flags);
  119. list_del_init(&wait->task_list);
  120. raw_spin_unlock_irqrestore(&q->lock, flags);
  121. }
  122. }
  123. EXPORT_SYMBOL(finish_swait);