Re: [PATCH v2 1/8] sched: introduce for_each_process_rculock and for_each_thread_rculock
From: "Lorenzo Stoakes (ARM)" <ljs@kernel.org>
Date: 2026-09-07 08:31:00
Also in:
linux-fsdevel, linux-mm, linux-pm, linux-security-module, lkml, rcu
On Mon, Sep 07, 2026 at 04:13:27PM +0800, Ye Liu wrote:
From: Ye Liu <liuye@kylinos.cn> 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 <liuye@kylinos.cn> Acked-by: Michal Hocko <mhocko@suse.com>
Some nits below, with those addressed, LGTM so: Reviewed-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
quoted hunk ↗ jump to hunk
--- 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 ; )
NIT: Can you indent the for loop by a tab? Since the for is in scoped_guard() scope and that's not made clear.
+ +#define for_each_thread_rculock(p, t) \ + scoped_guard(rcu) \ + __for_each_thread((p)->signal, t)
Same comment as above.
+ +/* + * 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)
Yeah this is even worse for clarity :) I know the existing defines do itg this way but it's kinda confusing. I know it's a bit fugly, but it's MUCH clearer as: #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
-- Cheers, Lorenzo