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