Greg Kroah-Hartman | b244131 | 2017-11-01 15:07:57 +0100 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
Ingo Molnar | 84f001e | 2017-02-01 16:36:40 +0100 | [diff] [blame] | 2 | #ifndef _LINUX_SCHED_WAKE_Q_H |
| 3 | #define _LINUX_SCHED_WAKE_Q_H |
| 4 | |
Ingo Molnar | eb61baf | 2017-02-01 17:09:06 +0100 | [diff] [blame] | 5 | /* |
| 6 | * Wake-queues are lists of tasks with a pending wakeup, whose |
| 7 | * callers have already marked the task as woken internally, |
| 8 | * and can thus carry on. A common use case is being able to |
| 9 | * do the wakeups once the corresponding user lock as been |
| 10 | * released. |
| 11 | * |
| 12 | * We hold reference to each task in the list across the wakeup, |
| 13 | * thus guaranteeing that the memory is still valid by the time |
| 14 | * the actual wakeups are performed in wake_up_q(). |
| 15 | * |
| 16 | * One per task suffices, because there's never a need for a task to be |
| 17 | * in two wake queues simultaneously; it is forbidden to abandon a task |
| 18 | * in a wake queue (a call to wake_up_q() _must_ follow), so if a task is |
| 19 | * already in a wake queue, the wakeup will happen soon and the second |
| 20 | * waker can just skip it. |
| 21 | * |
| 22 | * The DEFINE_WAKE_Q macro declares and initializes the list head. |
| 23 | * wake_up_q() does NOT reinitialize the list; it's expected to be |
| 24 | * called near the end of a function. Otherwise, the list can be |
| 25 | * re-initialized for later re-use by wake_q_init(). |
| 26 | * |
Peter Zijlstra | e6018c0 | 2018-12-17 10:14:53 +0100 | [diff] [blame] | 27 | * NOTE that this can cause spurious wakeups. schedule() callers |
Ingo Molnar | eb61baf | 2017-02-01 17:09:06 +0100 | [diff] [blame] | 28 | * must ensure the call is done inside a loop, confirming that the |
| 29 | * wakeup condition has in fact occurred. |
Peter Zijlstra | e6018c0 | 2018-12-17 10:14:53 +0100 | [diff] [blame] | 30 | * |
| 31 | * NOTE that there is no guarantee the wakeup will happen any later than the |
| 32 | * wake_q_add() location. Therefore task must be ready to be woken at the |
| 33 | * location of the wake_q_add(). |
Ingo Molnar | eb61baf | 2017-02-01 17:09:06 +0100 | [diff] [blame] | 34 | */ |
| 35 | |
Ingo Molnar | 84f001e | 2017-02-01 16:36:40 +0100 | [diff] [blame] | 36 | #include <linux/sched.h> |
| 37 | |
Ingo Molnar | eb61baf | 2017-02-01 17:09:06 +0100 | [diff] [blame] | 38 | struct wake_q_head { |
| 39 | struct wake_q_node *first; |
| 40 | struct wake_q_node **lastp; |
| 41 | }; |
| 42 | |
| 43 | #define WAKE_Q_TAIL ((struct wake_q_node *) 0x01) |
| 44 | |
| 45 | #define DEFINE_WAKE_Q(name) \ |
| 46 | struct wake_q_head name = { WAKE_Q_TAIL, &name.first } |
| 47 | |
| 48 | static inline void wake_q_init(struct wake_q_head *head) |
| 49 | { |
| 50 | head->first = WAKE_Q_TAIL; |
| 51 | head->lastp = &head->first; |
| 52 | } |
| 53 | |
Davidlohr Bueso | 07879c6 | 2018-12-18 11:53:52 -0800 | [diff] [blame] | 54 | extern void wake_q_add(struct wake_q_head *head, struct task_struct *task); |
| 55 | extern void wake_q_add_safe(struct wake_q_head *head, struct task_struct *task); |
Ingo Molnar | eb61baf | 2017-02-01 17:09:06 +0100 | [diff] [blame] | 56 | extern void wake_up_q(struct wake_q_head *head); |
| 57 | |
Ingo Molnar | 84f001e | 2017-02-01 16:36:40 +0100 | [diff] [blame] | 58 | #endif /* _LINUX_SCHED_WAKE_Q_H */ |