From: "Paul E. McKenney" <paulmck@kernel.org>
To: rcu@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, kernel-team@meta.com,
rostedt@goodmis.org, "Paul E. McKenney" <paulmck@kernel.org>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Subject: [PATCH RFC 4/4] tracing: Guard __DECLARE_TRACE() use of __DO_TRACE_CALL() with SRCU-fast
Date: Wed, 16 Jul 2025 15:54:18 -0700 [thread overview]
Message-ID: <20250716225418.3014815-4-paulmck@kernel.org> (raw)
In-Reply-To: <bb20a575-235b-499e-aa1d-70fe9e2c7617@paulmck-laptop>
The current use of guard(preempt_notrace)() within __DECLARE_TRACE()
to protect invocation of __DO_TRACE_CALL() means that BPF programs
attached to tracepoints are non-preemptible. This is unhelpful in
real-time systems, whose users apparently wish to use BPF while also
achieving low latencies. (Who knew?)
One option would be to use preemptible RCU, but this introduces
many opportunities for infinite recursion, which many consider to
be counterproductive, especially given the relatively small stacks
provided by the Linux kernel. These opportunities could be shut down
by sufficiently energetic duplication of code, but this sort of thing
is considered impolite in some circles.
Therefore, use the shiny new SRCU-fast API, which provides somewhat faster
readers than those of preemptible RCU, at least on my laptop, where
task_struct access is more expensive than access to per-CPU variables.
And SRCU fast provides way faster readers than does SRCU, courtesy of
being able to avoid the read-side use of smp_mb(). Also, it is quite
straightforward to create srcu_read_{,un}lock_fast_notrace() functions.
Link: https://lore.kernel.org/all/20250613152218.1924093-1-bigeasy@linutronix.de/
Signed-off-by: Paul E. McKenney <paulmck@kernel.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
include/linux/tracepoint.h | 6 +++--
kernel/tracepoint.c | 54 +++++++++++++++++++++++++++++++++++++-
2 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 826ce3f8e1f85..a22c1ab88560b 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -33,6 +33,8 @@ struct trace_eval_map {
#define TRACEPOINT_DEFAULT_PRIO 10
+extern struct srcu_struct tracepoint_srcu;
+
extern int
tracepoint_probe_register(struct tracepoint *tp, void *probe, void *data);
extern int
@@ -115,7 +117,7 @@ void for_each_tracepoint_in_module(struct module *mod,
static inline void tracepoint_synchronize_unregister(void)
{
synchronize_rcu_tasks_trace();
- synchronize_rcu();
+ synchronize_srcu(&tracepoint_srcu);
}
static inline bool tracepoint_is_faultable(struct tracepoint *tp)
{
@@ -271,7 +273,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
static inline void __do_trace_##name(proto) \
{ \
if (cond) { \
- guard(preempt_notrace)(); \
+ guard(srcu_fast_notrace)(&tracepoint_srcu); \
__DO_TRACE_CALL(name, TP_ARGS(args)); \
} \
} \
diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c
index 62719d2941c90..d96ea84804c64 100644
--- a/kernel/tracepoint.c
+++ b/kernel/tracepoint.c
@@ -25,6 +25,9 @@ enum tp_func_state {
extern tracepoint_ptr_t __start___tracepoints_ptrs[];
extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
+DEFINE_SRCU(tracepoint_srcu);
+EXPORT_SYMBOL_GPL(tracepoint_srcu);
+
enum tp_transition_sync {
TP_TRANSITION_SYNC_1_0_1,
TP_TRANSITION_SYNC_N_2_1,
@@ -34,6 +37,7 @@ enum tp_transition_sync {
struct tp_transition_snapshot {
unsigned long rcu;
+ unsigned long srcu_gp;
bool ongoing;
};
@@ -46,6 +50,7 @@ static void tp_rcu_get_state(enum tp_transition_sync sync)
/* Keep the latest get_state snapshot. */
snapshot->rcu = get_state_synchronize_rcu();
+ snapshot->srcu_gp = start_poll_synchronize_srcu(&tracepoint_srcu);
snapshot->ongoing = true;
}
@@ -56,6 +61,8 @@ static void tp_rcu_cond_sync(enum tp_transition_sync sync)
if (!snapshot->ongoing)
return;
cond_synchronize_rcu(snapshot->rcu);
+ if (!poll_state_synchronize_srcu(&tracepoint_srcu, snapshot->srcu_gp))
+ synchronize_srcu(&tracepoint_srcu);
snapshot->ongoing = false;
}
@@ -78,6 +85,9 @@ static LIST_HEAD(tracepoint_module_list);
*/
static DEFINE_MUTEX(tracepoints_mutex);
+static struct rcu_head *early_probes;
+static bool ok_to_free_tracepoints;
+
/*
* Note about RCU :
* It is used to delay the free of multiple probes array until a quiescent
@@ -101,17 +111,59 @@ static inline void *allocate_probes(int count)
return p == NULL ? NULL : p->probes;
}
-static void rcu_free_old_probes(struct rcu_head *head)
+static void srcu_free_old_probes(struct rcu_head *head)
{
kfree(container_of(head, struct tp_probes, rcu));
}
+static __init int release_early_probes(void)
+{
+ struct rcu_head *tmp;
+
+ ok_to_free_tracepoints = true;
+
+ while (early_probes) {
+ tmp = early_probes;
+ early_probes = tmp->next;
+ call_srcu(&tracepoint_srcu, tmp, srcu_free_old_probes);
+ }
+
+ return 0;
+}
+
+static void rcu_free_old_probes(struct rcu_head *head)
+{
+ /*
+ * We can't free probes if SRCU is not initialized yet.
+ * Postpone the wait for SRCU until after it has initialized.
+ */
+ if (unlikely(!ok_to_free_tracepoints)) {
+ struct tp_probes *tp_probes = container_of(head, struct tp_probes, rcu);
+
+ tp_probes->rcu.next = early_probes;
+ early_probes = &tp_probes->rcu;
+ return;
+ }
+
+ call_srcu(&tracepoint_srcu, head, srcu_free_old_probes);
+}
+
+/* SRCU is initialized at core_initcall */
+postcore_initcall(release_early_probes);
+
static inline void release_probes(struct tracepoint *tp, struct tracepoint_func *old)
{
if (old) {
struct tp_probes *tp_probes = container_of(old,
struct tp_probes, probes[0]);
+ /*
+ * Tracepoint probes are protected by either RCU or
+ * Tasks Trace RCU and also by SRCU. By calling the SRCU
+ * callback in the [Tasks Trace] RCU callback we cover
+ * both cases. So let us chain the SRCU and [Tasks Trace]
+ * RCU callbacks to wait for both grace periods.
+ */
if (tracepoint_is_faultable(tp))
call_rcu_tasks_trace(&tp_probes->rcu, rcu_free_old_probes);
else
--
2.40.1
next prev parent reply other threads:[~2025-07-16 22:54 UTC|newest]
Thread overview: 63+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-13 15:22 [RFC PATCH 0/2] Switch tracing from sched-RCU to preempt-RCU Sebastian Andrzej Siewior
2025-06-13 15:22 ` [RFC PATCH 1/2] rcu: Add rcu_read_lock_notrace() Sebastian Andrzej Siewior
2025-06-18 17:21 ` Boqun Feng
2025-06-20 8:43 ` Sebastian Andrzej Siewior
2025-06-20 11:23 ` Paul E. McKenney
2025-06-23 10:49 ` Sebastian Andrzej Siewior
2025-06-23 18:13 ` Paul E. McKenney
2025-07-07 21:56 ` Paul E. McKenney
2025-07-08 19:40 ` Mathieu Desnoyers
2025-07-08 20:49 ` Paul E. McKenney
2025-07-09 14:31 ` Mathieu Desnoyers
2025-07-09 18:33 ` Paul E. McKenney
2025-07-11 13:46 ` Mathieu Desnoyers
2025-07-11 17:05 ` Paul E. McKenney
2025-07-14 16:34 ` Paul E. McKenney
2025-07-15 19:56 ` Mathieu Desnoyers
2025-07-15 23:23 ` Paul E. McKenney
2025-07-15 19:54 ` Mathieu Desnoyers
2025-07-15 23:18 ` Paul E. McKenney
2025-07-16 0:42 ` Paul E. McKenney
2025-07-16 4:41 ` Paul E. McKenney
2025-07-16 15:09 ` Steven Rostedt
2025-07-16 20:35 ` Paul E. McKenney
2025-07-16 22:54 ` Paul E. McKenney
2025-07-16 22:54 ` [PATCH RFC 1/4] srcu: Move rcu_is_watching() checks to srcu_read_{,un}lock_fast() Paul E. McKenney
2025-07-16 22:54 ` [PATCH RFC 2/4] srcu: Add srcu_read_lock_fast_notrace() and srcu_read_unlock_fast_notrace() Paul E. McKenney
2025-07-16 22:54 ` [PATCH RFC 3/4] srcu: Add guards for notrace variants of SRCU-fast readers Paul E. McKenney
2025-07-16 22:54 ` Paul E. McKenney [this message]
2025-07-17 13:14 ` [RFC PATCH 1/2] rcu: Add rcu_read_lock_notrace() Mathieu Desnoyers
2025-07-17 14:46 ` Mathieu Desnoyers
2025-07-17 15:18 ` Paul E. McKenney
2025-07-17 19:36 ` Mathieu Desnoyers
2025-07-17 21:27 ` Paul E. McKenney
2026-01-07 1:26 ` Joel Fernandes
2026-01-06 15:08 ` Mathieu Desnoyers
2026-01-06 18:30 ` Paul E. McKenney
2026-01-06 18:43 ` Mathieu Desnoyers
2025-07-17 14:57 ` Alexei Starovoitov
2025-07-17 15:12 ` Steven Rostedt
2025-07-17 15:27 ` Alexei Starovoitov
2025-07-17 15:40 ` Steven Rostedt
2025-07-17 15:55 ` Steven Rostedt
2025-07-17 16:02 ` Alexei Starovoitov
2025-07-17 16:19 ` Steven Rostedt
2025-07-17 17:38 ` Mathieu Desnoyers
2025-07-17 16:04 ` Paul E. McKenney
2025-07-17 15:44 ` Paul E. McKenney
2025-07-17 15:30 ` Paul E. McKenney
2025-07-17 15:07 ` Paul E. McKenney
2025-07-17 19:04 ` [PATCH RFC 6/4] srcu: Add guards for SRCU-fast readers Paul E. McKenney
2025-07-17 19:19 ` Steven Rostedt
2025-07-17 19:51 ` Paul E. McKenney
2025-07-17 19:56 ` Steven Rostedt
2025-07-17 20:38 ` Paul E. McKenney
2025-07-19 0:28 ` [RFC PATCH 1/2] rcu: Add rcu_read_lock_notrace() Paul E. McKenney
2025-07-19 0:28 ` [PATCH v2 1/4] srcu: Move rcu_is_watching() checks to srcu_read_{,un}lock_fast() Paul E. McKenney
2025-07-21 14:53 ` Steven Rostedt
2025-07-21 16:25 ` Paul E. McKenney
2025-07-19 0:28 ` [PATCH v2 2/4] srcu: Add srcu_read_lock_fast_notrace() and srcu_read_unlock_fast_notrace() Paul E. McKenney
2025-07-19 0:28 ` [PATCH v2 3/4] srcu: Add guards for notrace variants of SRCU-fast readers Paul E. McKenney
2025-07-19 0:28 ` [PATCH v2 4/4] tracing: Guard __DECLARE_TRACE() use of __DO_TRACE_CALL() with SRCU-fast Paul E. McKenney
2025-06-13 15:22 ` [RFC PATCH 2/2] trace: Use rcu_read_lock() instead preempt_disable() Sebastian Andrzej Siewior
2025-06-13 15:38 ` [RFC PATCH 0/2] Switch tracing from sched-RCU to preempt-RCU Mathieu Desnoyers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250716225418.3014815-4-paulmck@kernel.org \
--to=paulmck@kernel.org \
--cc=bigeasy@linutronix.de \
--cc=kernel-team@meta.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=rcu@vger.kernel.org \
--cc=rostedt@goodmis.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.