Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */ 2 : : #ifndef _LINUX_RCUWAIT_H_ 3 : : #define _LINUX_RCUWAIT_H_ 4 : : 5 : : #include <linux/rcupdate.h> 6 : : 7 : : /* 8 : : * rcuwait provides a way of blocking and waking up a single 9 : : * task in an rcu-safe manner. 10 : : * 11 : : * The only time @task is non-nil is when a user is blocked (or 12 : : * checking if it needs to) on a condition, and reset as soon as we 13 : : * know that the condition has succeeded and are awoken. 14 : : */ 15 : : struct rcuwait { 16 : : struct task_struct __rcu *task; 17 : : }; 18 : : 19 : : #define __RCUWAIT_INITIALIZER(name) \ 20 : : { .task = NULL, } 21 : : 22 : : static inline void rcuwait_init(struct rcuwait *w) 23 : : { 24 : 54136 : w->task = NULL; 25 : : } 26 : : 27 : : extern void rcuwait_wake_up(struct rcuwait *w); 28 : : 29 : : /* 30 : : * The caller is responsible for locking around rcuwait_wait_event(), 31 : : * such that writes to @task are properly serialized. 32 : : */ 33 : : #define rcuwait_wait_event(w, condition) \ 34 : : ({ \ 35 : : rcu_assign_pointer((w)->task, current); \ 36 : : for (;;) { \ 37 : : /* \ 38 : : * Implicit barrier (A) pairs with (B) in \ 39 : : * rcuwait_wake_up(). \ 40 : : */ \ 41 : : set_current_state(TASK_UNINTERRUPTIBLE); \ 42 : : if (condition) \ 43 : : break; \ 44 : : \ 45 : : schedule(); \ 46 : : } \ 47 : : \ 48 : : WRITE_ONCE((w)->task, NULL); \ 49 : : __set_current_state(TASK_RUNNING); \ 50 : : }) 51 : : 52 : : #endif /* _LINUX_RCUWAIT_H_ */