[PATCH v2 1/8] sched: introduce for_each_process_rculock and for_each_thread_rculock
From: Ye Liu
Date: Mon Sep 07 2026 - 04:25:10 EST
From: Ye Liu <liuye@xxxxxxxxxx>
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@xxxxxxxxxx>
Acked-by: Michal Hocko <mhocko@xxxxxxxx>
---
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