mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-05 05:42:36 +00:00
tracing: Make sure rcu_irq_enter() can work for trace_*_rcuidle() trace events
Stack tracing discovered that there's a small location inside the RCU infrastructure where calling rcu_irq_enter() does not work. As trace events use rcu_irq_enter() it must make sure that it is functionable. A check against rcu_irq_enter_disabled() is added with a WARN_ON_ONCE() as no trace event should ever be used in that part of RCU. If the warning is triggered, then the trace event is ignored. Restructure the __DO_TRACE() a bit to get rid of the prercu and postrcu, and just have an rcucheck that does the work from within the _DO_TRACE() macro. gcc optimization will compile out the rcucheck=0 case. Link: http://lkml.kernel.org/r/20170405093207.404f8deb@gandalf.local.home Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
parent
03ecd3f48e
commit
d54b6eeb55
1 changed files with 11 additions and 8 deletions
|
@ -128,7 +128,7 @@ extern void syscall_unregfunc(void);
|
||||||
* as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just
|
* as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just
|
||||||
* "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto".
|
* "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto".
|
||||||
*/
|
*/
|
||||||
#define __DO_TRACE(tp, proto, args, cond, prercu, postrcu) \
|
#define __DO_TRACE(tp, proto, args, cond, rcucheck) \
|
||||||
do { \
|
do { \
|
||||||
struct tracepoint_func *it_func_ptr; \
|
struct tracepoint_func *it_func_ptr; \
|
||||||
void *it_func; \
|
void *it_func; \
|
||||||
|
@ -136,7 +136,11 @@ extern void syscall_unregfunc(void);
|
||||||
\
|
\
|
||||||
if (!(cond)) \
|
if (!(cond)) \
|
||||||
return; \
|
return; \
|
||||||
prercu; \
|
if (rcucheck) { \
|
||||||
|
if (WARN_ON_ONCE(rcu_irq_enter_disabled())) \
|
||||||
|
return; \
|
||||||
|
rcu_irq_enter_irqson(); \
|
||||||
|
} \
|
||||||
rcu_read_lock_sched_notrace(); \
|
rcu_read_lock_sched_notrace(); \
|
||||||
it_func_ptr = rcu_dereference_sched((tp)->funcs); \
|
it_func_ptr = rcu_dereference_sched((tp)->funcs); \
|
||||||
if (it_func_ptr) { \
|
if (it_func_ptr) { \
|
||||||
|
@ -147,7 +151,8 @@ extern void syscall_unregfunc(void);
|
||||||
} while ((++it_func_ptr)->func); \
|
} while ((++it_func_ptr)->func); \
|
||||||
} \
|
} \
|
||||||
rcu_read_unlock_sched_notrace(); \
|
rcu_read_unlock_sched_notrace(); \
|
||||||
postrcu; \
|
if (rcucheck) \
|
||||||
|
rcu_irq_exit_irqson(); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
|
@ -158,9 +163,7 @@ extern void syscall_unregfunc(void);
|
||||||
__DO_TRACE(&__tracepoint_##name, \
|
__DO_TRACE(&__tracepoint_##name, \
|
||||||
TP_PROTO(data_proto), \
|
TP_PROTO(data_proto), \
|
||||||
TP_ARGS(data_args), \
|
TP_ARGS(data_args), \
|
||||||
TP_CONDITION(cond), \
|
TP_CONDITION(cond), 1); \
|
||||||
rcu_irq_enter_irqson(), \
|
|
||||||
rcu_irq_exit_irqson()); \
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
#define __DECLARE_TRACE_RCU(name, proto, args, cond, data_proto, data_args)
|
#define __DECLARE_TRACE_RCU(name, proto, args, cond, data_proto, data_args)
|
||||||
|
@ -186,7 +189,7 @@ extern void syscall_unregfunc(void);
|
||||||
__DO_TRACE(&__tracepoint_##name, \
|
__DO_TRACE(&__tracepoint_##name, \
|
||||||
TP_PROTO(data_proto), \
|
TP_PROTO(data_proto), \
|
||||||
TP_ARGS(data_args), \
|
TP_ARGS(data_args), \
|
||||||
TP_CONDITION(cond),,); \
|
TP_CONDITION(cond), 0); \
|
||||||
if (IS_ENABLED(CONFIG_LOCKDEP) && (cond)) { \
|
if (IS_ENABLED(CONFIG_LOCKDEP) && (cond)) { \
|
||||||
rcu_read_lock_sched_notrace(); \
|
rcu_read_lock_sched_notrace(); \
|
||||||
rcu_dereference_sched(__tracepoint_##name.funcs);\
|
rcu_dereference_sched(__tracepoint_##name.funcs);\
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue