Thread (53 messages) 53 messages, 7 authors, 2026-01-07
STALE164d

[RFC PATCH 1/2] rcu: Add rcu_read_lock_notrace()

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Date: 2025-06-13 15:22:25
Also in: linux-rt-devel, rcu
Subsystem: read-copy update (rcu), the rest · Maintainers: "Paul E. McKenney", Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Boqun Feng, Uladzislau Rezki, Linus Torvalds

rcu_read_lock_notrace() follows preempt_disable_notrace(). The idea is
provide a rcu_read_lock() version so that the preempt_disable_notrace()
user (which use RCU-sched under the hood) can migrate to preemptible
RCU.
The first user should be tracing (tracepoint) which is using the
_notrace variant.

rcu_read_lock_notrace() is a slim version of rcu_read_lock(). It simply
increments/ decrements the counter. It does not emit any warnings if
RCU_NEST_PMAX is exceeded or patricipates in STRICT_GRACE_PERIOD. It
also does not participate in rcu_read_unlock_special() as it would if
invoke from NMI.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
 include/linux/rcupdate.h | 41 ++++++++++++++++++++++++++++++++++++++++
 kernel/rcu/tree_plugin.h | 14 ++++++++++++++
 2 files changed, 55 insertions(+)
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 120536f4c6eb1..0de7e68a2411a 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -71,6 +71,8 @@ static inline bool same_state_synchronize_rcu(unsigned long oldstate1, unsigned
 
 void __rcu_read_lock(void);
 void __rcu_read_unlock(void);
+void __rcu_read_lock_notrace(void);
+void __rcu_read_unlock_notrace(void);
 
 /*
  * Defined as a macro as it is a very low level header included from
@@ -93,6 +95,11 @@ static inline void __rcu_read_lock(void)
 	preempt_disable();
 }
 
+static inline void __rcu_read_lock_notrace(void)
+{
+	preempt_disable_notrace();
+}
+
 static inline void __rcu_read_unlock(void)
 {
 	if (IS_ENABLED(CONFIG_RCU_STRICT_GRACE_PERIOD))
@@ -100,6 +107,11 @@ static inline void __rcu_read_unlock(void)
 	preempt_enable();
 }
 
+static inline void __rcu_read_unlock_notrace(void)
+{
+	preempt_enable_notrace();
+}
+
 static inline int rcu_preempt_depth(void)
 {
 	return 0;
@@ -843,6 +855,16 @@ static __always_inline void rcu_read_lock(void)
 			 "rcu_read_lock() used illegally while idle");
 }
 
+/*
+ * Used by tracing: cannot be traced, NMI safe, usable from the scheduler,
+ * usable to trace the RCU implementation.
+ */
+static __always_inline void rcu_read_lock_notrace(void)
+{
+	__rcu_read_lock_notrace();
+	__acquire(RCU);
+}
+
 /*
  * So where is rcu_write_lock()?  It does not exist, as there is no
  * way for writers to lock out RCU readers.  This is a feature, not
@@ -873,6 +895,11 @@ static inline void rcu_read_unlock(void)
 	__rcu_read_unlock();
 }
 
+static __always_inline void rcu_read_unlock_notrace(void)
+{
+	__release(RCU);
+	__rcu_read_unlock_notrace();
+}
 /**
  * rcu_read_lock_bh() - mark the beginning of an RCU-bh critical section
  *
@@ -1166,4 +1193,18 @@ DEFINE_LOCK_GUARD_0(rcu,
 	} while (0),
 	rcu_read_unlock())
 
+DEFINE_LOCK_GUARD_0(rcu_notrace,
+	do {
+		rcu_read_lock_notrace();
+		/*
+		 * sparse doesn't call the cleanup function,
+		 * so just release immediately and don't track
+		 * the context. We don't need to anyway, since
+		 * the whole point of the guard is to not need
+		 * the explicit unlock.
+		 */
+		__release(RCU);
+	} while (0),
+	rcu_read_unlock_notrace())
+
 #endif /* __LINUX_RCUPDATE_H */
diff --git a/kernel/rcu/tree_plugin.h b/kernel/rcu/tree_plugin.h
index 0b0f56f6abc85..02cccca917a22 100644
--- a/kernel/rcu/tree_plugin.h
+++ b/kernel/rcu/tree_plugin.h
@@ -420,6 +420,13 @@ void __rcu_read_lock(void)
 }
 EXPORT_SYMBOL_GPL(__rcu_read_lock);
 
+notrace void __rcu_read_lock_notrace(void)
+{
+	rcu_preempt_read_enter();
+	barrier();  /* critical section after entry code. */
+}
+EXPORT_SYMBOL_GPL(__rcu_read_lock_notrace);
+
 /*
  * Preemptible RCU implementation for rcu_read_unlock().
  * Decrement ->rcu_read_lock_nesting.  If the result is zero (outermost
@@ -445,6 +452,13 @@ void __rcu_read_unlock(void)
 }
 EXPORT_SYMBOL_GPL(__rcu_read_unlock);
 
+notrace void __rcu_read_unlock_notrace(void)
+{
+	barrier();  // critical section before exit code.
+	rcu_preempt_read_exit();
+}
+EXPORT_SYMBOL_GPL(__rcu_read_unlock_notrace);
+
 /*
  * Advance a ->blkd_tasks-list pointer to the next entry, instead
  * returning NULL if at the end of the list.
-- 
2.49.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help