Thread (49 messages) flat view 49 messages, 10 authors, 12d ago

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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help