summaryrefslogtreecommitdiffstats
path: root/include/linux/wait.h
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2015-10-23 08:32:34 -0400
committerIngo Molnar <mingo@kernel.org>2015-11-23 03:37:52 -0500
commit69e51e92a394088fc3266ed5136903074b44f3c4 (patch)
treeaa82af638e05ee38ad4a3c0b8c5c36ae2f8365a5 /include/linux/wait.h
parent38c6ade2dd4dcc3bca06c981e2a1b91289046177 (diff)
sched/wait: Document waitqueue_active()
Kosuku reports that there were a fair number of buggy waitqueue_active() users and this function deserves a big comment in order to avoid growing more. Reported-by: Kosuke Tatsukawa <tatsu@ab.jp.nec.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'include/linux/wait.h')
-rw-r--r--include/linux/wait.h30
1 files changed, 30 insertions, 0 deletions
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 1e1bf9f963a9..f3bac30587f7 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -102,6 +102,36 @@ init_waitqueue_func_entry(wait_queue_t *q, wait_queue_func_t func)
102 q->func = func; 102 q->func = func;
103} 103}
104 104
105/**
106 * waitqueue_active -- locklessly test for waiters on the queue
107 * @q: the waitqueue to test for waiters
108 *
109 * returns true if the wait list is not empty
110 *
111 * NOTE: this function is lockless and requires care, incorrect usage _will_
112 * lead to sporadic and non-obvious failure.
113 *
114 * Use either while holding wait_queue_head_t::lock or when used for wakeups
115 * with an extra smp_mb() like:
116 *
117 * CPU0 - waker CPU1 - waiter
118 *
119 * for (;;) {
120 * @cond = true; prepare_to_wait(&wq, &wait, state);
121 * smp_mb(); // smp_mb() from set_current_state()
122 * if (waitqueue_active(wq)) if (@cond)
123 * wake_up(wq); break;
124 * schedule();
125 * }
126 * finish_wait(&wq, &wait);
127 *
128 * Because without the explicit smp_mb() it's possible for the
129 * waitqueue_active() load to get hoisted over the @cond store such that we'll
130 * observe an empty wait list while the waiter might not observe @cond.
131 *
132 * Also note that this 'optimization' trades a spin_lock() for an smp_mb(),
133 * which (when the lock is uncontended) are of roughly equal cost.
134 */
105static inline int waitqueue_active(wait_queue_head_t *q) 135static inline int waitqueue_active(wait_queue_head_t *q)
106{ 136{
107 return !list_empty(&q->task_list); 137 return !list_empty(&q->task_list);