1 From 5dd7edbd6980c6139624515d75bc93f89dff142a Mon Sep 17 00:00:00 2001
2 From: Thomas Gleixner <tglx@linutronix.de>
3 Date: Mon, 12 Dec 2011 12:29:04 +0100
4 Subject: [PATCH 140/366] wait-simple: Simple waitqueue implementation
6 wait_queue is a swiss army knife and in most of the cases the
7 complexity is not needed. For RT waitqueues are a constant source of
8 trouble as we can't convert the head lock to a raw spinlock due to
9 fancy and long lasting callbacks.
11 Provide a slim version, which allows RT to replace wait queues. This
12 should go mainline as well, as it lowers memory consumption and
15 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
17 smp_mb() added by Steven Rostedt to fix a race condition with swait
18 wakeups vs adding items to the list.
20 include/linux/wait-simple.h | 207 ++++++++++++++++++++++++++++++++++++++++++++
21 kernel/sched/Makefile | 2 +-
22 kernel/sched/wait-simple.c | 115 ++++++++++++++++++++++++
23 3 files changed, 323 insertions(+), 1 deletion(-)
24 create mode 100644 include/linux/wait-simple.h
25 create mode 100644 kernel/sched/wait-simple.c
27 diff --git a/include/linux/wait-simple.h b/include/linux/wait-simple.h
29 index 0000000..f86bca2
31 +++ b/include/linux/wait-simple.h
33 +#ifndef _LINUX_WAIT_SIMPLE_H
34 +#define _LINUX_WAIT_SIMPLE_H
36 +#include <linux/spinlock.h>
37 +#include <linux/list.h>
39 +#include <asm/current.h>
42 + struct task_struct *task;
43 + struct list_head node;
46 +#define DEFINE_SWAITER(name) \
47 + struct swaiter name = { \
49 + .node = LIST_HEAD_INIT((name).node), \
53 + raw_spinlock_t lock;
54 + struct list_head list;
57 +#define SWAIT_HEAD_INITIALIZER(name) { \
58 + .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \
59 + .list = LIST_HEAD_INIT((name).list), \
62 +#define DEFINE_SWAIT_HEAD(name) \
63 + struct swait_head name = SWAIT_HEAD_INITIALIZER(name)
65 +extern void __init_swait_head(struct swait_head *h, struct lock_class_key *key);
67 +#define init_swait_head(swh) \
69 + static struct lock_class_key __key; \
71 + __init_swait_head((swh), &__key); \
77 +extern void swait_prepare_locked(struct swait_head *head, struct swaiter *w);
78 +extern void swait_prepare(struct swait_head *head, struct swaiter *w, int state);
79 +extern void swait_finish_locked(struct swait_head *head, struct swaiter *w);
80 +extern void swait_finish(struct swait_head *head, struct swaiter *w);
82 +/* Check whether a head has waiters enqueued */
83 +static inline bool swaitqueue_active(struct swait_head *h)
85 + /* Make sure the condition is visible before checking list_empty() */
87 + return !list_empty(&h->list);
93 +extern unsigned int __swait_wake(struct swait_head *head, unsigned int state, unsigned int num);
94 +extern unsigned int __swait_wake_locked(struct swait_head *head, unsigned int state, unsigned int num);
96 +#define swait_wake(head) __swait_wake(head, TASK_NORMAL, 1)
97 +#define swait_wake_interruptible(head) __swait_wake(head, TASK_INTERRUPTIBLE, 1)
98 +#define swait_wake_all(head) __swait_wake(head, TASK_NORMAL, 0)
99 +#define swait_wake_all_interruptible(head) __swait_wake(head, TASK_INTERRUPTIBLE, 0)
104 +#define __swait_event(wq, condition) \
106 + DEFINE_SWAITER(__wait); \
109 + swait_prepare(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
114 + swait_finish(&wq, &__wait); \
118 + * swait_event - sleep until a condition gets true
119 + * @wq: the waitqueue to wait on
120 + * @condition: a C expression for the event to wait for
122 + * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
123 + * @condition evaluates to true. The @condition is checked each time
124 + * the waitqueue @wq is woken up.
126 + * wake_up() has to be called after changing any variable that could
127 + * change the result of the wait condition.
129 +#define swait_event(wq, condition) \
133 + __swait_event(wq, condition); \
136 +#define __swait_event_interruptible(wq, condition, ret) \
138 + DEFINE_SWAITER(__wait); \
141 + swait_prepare(&wq, &__wait, TASK_INTERRUPTIBLE); \
144 + if (signal_pending(current)) { \
145 + ret = -ERESTARTSYS; \
150 + swait_finish(&wq, &__wait); \
153 +#define __swait_event_interruptible_timeout(wq, condition, ret) \
155 + DEFINE_SWAITER(__wait); \
158 + swait_prepare(&wq, &__wait, TASK_INTERRUPTIBLE); \
161 + if (signal_pending(current)) { \
162 + ret = -ERESTARTSYS; \
165 + ret = schedule_timeout(ret); \
169 + swait_finish(&wq, &__wait); \
173 + * swait_event_interruptible - sleep until a condition gets true
174 + * @wq: the waitqueue to wait on
175 + * @condition: a C expression for the event to wait for
177 + * The process is put to sleep (TASK_INTERRUPTIBLE) until the
178 + * @condition evaluates to true. The @condition is checked each time
179 + * the waitqueue @wq is woken up.
181 + * wake_up() has to be called after changing any variable that could
182 + * change the result of the wait condition.
184 +#define swait_event_interruptible(wq, condition) \
187 + if (!(condition)) \
188 + __swait_event_interruptible(wq, condition, __ret); \
192 +#define swait_event_interruptible_timeout(wq, condition, timeout) \
194 + int __ret = timeout; \
195 + if (!(condition)) \
196 + __swait_event_interruptible_timeout(wq, condition, __ret); \
200 +#define __swait_event_timeout(wq, condition, ret) \
202 + DEFINE_SWAITER(__wait); \
205 + swait_prepare(&wq, &__wait, TASK_UNINTERRUPTIBLE); \
208 + ret = schedule_timeout(ret); \
212 + swait_finish(&wq, &__wait); \
216 + * swait_event_timeout - sleep until a condition gets true or a timeout elapses
217 + * @wq: the waitqueue to wait on
218 + * @condition: a C expression for the event to wait for
219 + * @timeout: timeout, in jiffies
221 + * The process is put to sleep (TASK_UNINTERRUPTIBLE) until the
222 + * @condition evaluates to true. The @condition is checked each time
223 + * the waitqueue @wq is woken up.
225 + * wake_up() has to be called after changing any variable that could
226 + * change the result of the wait condition.
228 + * The function returns 0 if the @timeout elapsed, and the remaining
229 + * jiffies if the condition evaluated to true before the timeout elapsed.
231 +#define swait_event_timeout(wq, condition, timeout) \
233 + long __ret = timeout; \
234 + if (!(condition)) \
235 + __swait_event_timeout(wq, condition, __ret); \
240 diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile
241 index 43fb319c..26505c1 100644
242 --- a/kernel/sched/Makefile
243 +++ b/kernel/sched/Makefile
244 @@ -15,7 +15,7 @@ endif
246 obj-y += core.o loadavg.o clock.o cputime.o
247 obj-y += idle_task.o fair.o rt.o deadline.o stop_task.o
248 -obj-y += wait.o completion.o idle.o
249 +obj-y += wait.o wait-simple.o completion.o idle.o
250 obj-$(CONFIG_SMP) += cpupri.o cpudeadline.o
251 obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o
252 obj-$(CONFIG_SCHEDSTATS) += stats.o
253 diff --git a/kernel/sched/wait-simple.c b/kernel/sched/wait-simple.c
255 index 0000000..7dfa86d
257 +++ b/kernel/sched/wait-simple.c
260 + * Simple waitqueues without fancy flags and callbacks
262 + * (C) 2011 Thomas Gleixner <tglx@linutronix.de>
264 + * Based on kernel/wait.c
266 + * For licencing details see kernel-base/COPYING
268 +#include <linux/init.h>
269 +#include <linux/export.h>
270 +#include <linux/sched.h>
271 +#include <linux/wait-simple.h>
273 +/* Adds w to head->list. Must be called with head->lock locked. */
274 +static inline void __swait_enqueue(struct swait_head *head, struct swaiter *w)
276 + list_add(&w->node, &head->list);
277 + /* We can't let the condition leak before the setting of head */
281 +/* Removes w from head->list. Must be called with head->lock locked. */
282 +static inline void __swait_dequeue(struct swaiter *w)
284 + list_del_init(&w->node);
287 +void __init_swait_head(struct swait_head *head, struct lock_class_key *key)
289 + raw_spin_lock_init(&head->lock);
290 + lockdep_set_class(&head->lock, key);
291 + INIT_LIST_HEAD(&head->list);
293 +EXPORT_SYMBOL(__init_swait_head);
295 +void swait_prepare_locked(struct swait_head *head, struct swaiter *w)
298 + if (list_empty(&w->node))
299 + __swait_enqueue(head, w);
302 +void swait_prepare(struct swait_head *head, struct swaiter *w, int state)
304 + unsigned long flags;
306 + raw_spin_lock_irqsave(&head->lock, flags);
307 + swait_prepare_locked(head, w);
308 + __set_current_state(state);
309 + raw_spin_unlock_irqrestore(&head->lock, flags);
311 +EXPORT_SYMBOL(swait_prepare);
313 +void swait_finish_locked(struct swait_head *head, struct swaiter *w)
315 + __set_current_state(TASK_RUNNING);
317 + __swait_dequeue(w);
320 +void swait_finish(struct swait_head *head, struct swaiter *w)
322 + unsigned long flags;
324 + __set_current_state(TASK_RUNNING);
326 + raw_spin_lock_irqsave(&head->lock, flags);
327 + __swait_dequeue(w);
328 + raw_spin_unlock_irqrestore(&head->lock, flags);
331 +EXPORT_SYMBOL(swait_finish);
334 +__swait_wake_locked(struct swait_head *head, unsigned int state, unsigned int num)
336 + struct swaiter *curr, *next;
339 + list_for_each_entry_safe(curr, next, &head->list, node) {
340 + if (wake_up_state(curr->task, state)) {
341 + __swait_dequeue(curr);
343 + * The waiting task can free the waiter as
344 + * soon as curr->task = NULL is written,
345 + * without taking any locks. A memory barrier
346 + * is required here to prevent the following
347 + * store to curr->task from getting ahead of
348 + * the dequeue operation.
352 + if (++woken == num)
360 +__swait_wake(struct swait_head *head, unsigned int state, unsigned int num)
362 + unsigned long flags;
365 + if (!swaitqueue_active(head))
368 + raw_spin_lock_irqsave(&head->lock, flags);
369 + woken = __swait_wake_locked(head, state, num);
370 + raw_spin_unlock_irqrestore(&head->lock, flags);
373 +EXPORT_SYMBOL(__swait_wake);