From: Ye Liu <[email protected]> Introduce for_each_process_rculock(), for_each_thread_rculock() and for_each_process_thread_rculock() macros that acquire the RCU read lock before the iteration starts and release it when the loop is left, so that the RCU read-side critical section is scoped to the loop body instead of an externally managed rcu_read_lock()/rcu_read_unlock() pair.
Signed-off-by: Ye Liu <[email protected]> Acked-by: Michal Hocko <[email protected]> --- Changes in v2: - Rename macros from *_rcu to *_rculock (Steven Rostedt, Thomas Gleixner) - Improve comment on for_each_process_thread_rculock() double loop - Change prefix from mm: to sched: (Michal Hocko) include/linux/sched/signal.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 584ae88b435e..110ea9f131f3 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -2,6 +2,7 @@ #ifndef _LINUX_SCHED_SIGNAL_H #define _LINUX_SCHED_SIGNAL_H +#include <linux/cleanup.h> #include <linux/rculist.h> #include <linux/signal.h> #include <linux/sched.h> @@ -663,6 +664,30 @@ extern bool current_is_single_threaded(void); #define for_each_process_thread(p, t) \ for_each_process(p) for_each_thread(p, t) +/* + * Variants of for_each_process(), for_each_thread() and + * for_each_process_thread() that automatically acquire and release the + * RCU read lock via scoped_guard(rcu). The lock is held for the + * duration of the loop and released on exit, including via break, + * goto, or return. + */ +#define for_each_process_rculock(p) \ + scoped_guard(rcu) \ + for (p = &init_task ; (p = next_task(p)) != &init_task ; ) + +#define for_each_thread_rculock(p, t) \ + scoped_guard(rcu) \ + __for_each_thread((p)->signal, t) + +/* + * Double loop: 'break' only exits the inner for_each_thread() loop. + * Use 'goto' to exit both loops; the RCU read lock is released + * automatically when the scoped_guard scope is left. + */ +#define for_each_process_thread_rculock(p, t) \ + scoped_guard(rcu) \ + for_each_process(p) for_each_thread(p, t) + typedef int (*proc_visitor)(struct task_struct *p, void *data); void walk_process_tree(struct task_struct *top, proc_visitor, void *); -- 2.25.1
