Re: Instrumentation and RCU

From: Steven Rostedt
Date: Mon Mar 09 2020 - 14:44:32 EST


On Mon, 9 Mar 2020 14:37:40 -0400 (EDT)
Mathieu Desnoyers <mathieu.desnoyers@xxxxxxxxxxxx> wrote:

> So I think we could go back to plain RCU for rcuidle tracepoints if we do
> the cheaper "rcu_is_watching()" check rather than invoking
> rcu_irq_{enter,exit}_irqson() unconditionally.

You mean something like this?

-- Steve

diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 5f4de82ffa0f..1904dbb3a921 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -164,7 +164,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
struct tracepoint_func *it_func_ptr; \
void *it_func; \
void *__data; \
- int __maybe_unused __idx = 0; \
+ int __maybe_unused __idx = -1; \
\
if (!(cond)) \
return; \
@@ -179,8 +179,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
* For rcuidle callers, use srcu since sched-rcu \
* doesn't work from the idle path. \
*/ \
- if (rcuidle) \
- __idx = srcu_read_lock_notrace(&tracepoint_srcu);\
+ if (rcuidle && !rcu_is_watching()) \
+ __idx = srcu_read_lock_notrace(&tracepoint_srcu); \
\
it_func_ptr = rcu_dereference_raw((tp)->funcs); \
\
@@ -199,7 +199,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
} while ((++it_func_ptr)->func); \
} \
\
- if (rcuidle) \
+ if (rcuidle && __idx != -1) \
rcu_irq_exit_irqson(); \
\
preempt_enable_notrace(); \