diff options
author | Davidlohr Bueso <dave@stgolabs.net> | 2017-09-13 16:08:18 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-09-15 10:57:10 -0400 |
commit | 8cd641e3c7cbf86c7cbd2a17a160dd137d86c860 (patch) | |
tree | 23ff1da546c321e16956cbc2456fc55fe7931008 | |
parent | 3a8b0677fc6180a467e26cc32ce6b0c09a32f9bb (diff) |
sched/wait: Add swq_has_sleeper()
Which is the equivalent of what we have in regular waitqueues.
I'm not crazy about the name, but this also helps us get both
apis closer -- which iirc comes originally from the -net folks.
We also duplicate the comments for the lockless swait_active(),
from wait.h. Future users will make use of this interface.
Signed-off-by: Davidlohr Bueso <dbueso@suse.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | include/linux/swait.h | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/include/linux/swait.h b/include/linux/swait.h index 4a4e180d0a35..73e97a08d3d0 100644 --- a/include/linux/swait.h +++ b/include/linux/swait.h | |||
@@ -79,9 +79,63 @@ extern void __init_swait_queue_head(struct swait_queue_head *q, const char *name | |||
79 | DECLARE_SWAIT_QUEUE_HEAD(name) | 79 | DECLARE_SWAIT_QUEUE_HEAD(name) |
80 | #endif | 80 | #endif |
81 | 81 | ||
82 | static inline int swait_active(struct swait_queue_head *q) | 82 | /** |
83 | * swait_active -- locklessly test for waiters on the queue | ||
84 | * @wq: the waitqueue to test for waiters | ||
85 | * | ||
86 | * returns true if the wait list is not empty | ||
87 | * | ||
88 | * NOTE: this function is lockless and requires care, incorrect usage _will_ | ||
89 | * lead to sporadic and non-obvious failure. | ||
90 | * | ||
91 | * NOTE2: this function has the same above implications as regular waitqueues. | ||
92 | * | ||
93 | * Use either while holding swait_queue_head::lock or when used for wakeups | ||
94 | * with an extra smp_mb() like: | ||
95 | * | ||
96 | * CPU0 - waker CPU1 - waiter | ||
97 | * | ||
98 | * for (;;) { | ||
99 | * @cond = true; prepare_to_swait(&wq_head, &wait, state); | ||
100 | * smp_mb(); // smp_mb() from set_current_state() | ||
101 | * if (swait_active(wq_head)) if (@cond) | ||
102 | * wake_up(wq_head); break; | ||
103 | * schedule(); | ||
104 | * } | ||
105 | * finish_swait(&wq_head, &wait); | ||
106 | * | ||
107 | * Because without the explicit smp_mb() it's possible for the | ||
108 | * swait_active() load to get hoisted over the @cond store such that we'll | ||
109 | * observe an empty wait list while the waiter might not observe @cond. | ||
110 | * This, in turn, can trigger missing wakeups. | ||
111 | * | ||
112 | * Also note that this 'optimization' trades a spin_lock() for an smp_mb(), | ||
113 | * which (when the lock is uncontended) are of roughly equal cost. | ||
114 | */ | ||
115 | static inline int swait_active(struct swait_queue_head *wq) | ||
116 | { | ||
117 | return !list_empty(&wq->task_list); | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * swq_has_sleeper - check if there are any waiting processes | ||
122 | * @wq: the waitqueue to test for waiters | ||
123 | * | ||
124 | * Returns true if @wq has waiting processes | ||
125 | * | ||
126 | * Please refer to the comment for swait_active. | ||
127 | */ | ||
128 | static inline bool swq_has_sleeper(struct swait_queue_head *wq) | ||
83 | { | 129 | { |
84 | return !list_empty(&q->task_list); | 130 | /* |
131 | * We need to be sure we are in sync with the list_add() | ||
132 | * modifications to the wait queue (task_list). | ||
133 | * | ||
134 | * This memory barrier should be paired with one on the | ||
135 | * waiting side. | ||
136 | */ | ||
137 | smp_mb(); | ||
138 | return swait_active(wq); | ||
85 | } | 139 | } |
86 | 140 | ||
87 | extern void swake_up(struct swait_queue_head *q); | 141 | extern void swake_up(struct swait_queue_head *q); |