On Mon, Sep 07, 2026 at 04:13:27PM +0800, Ye Liu wrote: > 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]>
Some nits below, with those addressed, LGTM so: Reviewed-by: Lorenzo Stoakes (ARM) <[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 ; ) 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
