This series makes lockdeps use the trace irqs on/off tracepoints. Lets
introduce an API where lockdep checks are not done so that we don't get
false lockdep splats. This API introduction will not affect any of the
existing users of the tracepoint API and the new call will only be used
by the IRQs on/off tracepoints.
Cc: Steven Rostedt
Cc: Peter Zilstra
Cc: Ingo Molnar
Cc: Mathieu Desnoyers
Cc: Tom Zanussi
Cc: Namhyung Kim
Cc: Thomas Glexiner
Cc: Boqun Feng
Cc: Paul McKenney
Cc: Frederic Weisbecker
Cc: Randy Dunlap
Cc: Masami Hiramatsu
Cc: Fenguang Wu
Cc: Baohong Liu
Cc: Vedang Patel
Signed-off-by: Joel Fernandes
---
include/linux/tracepoint.h | 32 +---
1 file changed, 29 insertions(+), 3 deletions(-)
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index c94f466d57ef..0b6d7d1a16e2 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -119,6 +119,14 @@ extern void syscall_unregfunc(void);
#ifdef TRACEPOINTS_ENABLED
+#define LOCKDEP_CHECKS_ON(lockdep) \
+ if (IS_ENABLED(CONFIG_LOCKDEP) && !lockdep) \
+ lockdep_on();
+
+#define LOCKDEP_CHECKS_OFF(lockdep)\
+ if (IS_ENABLED(CONFIG_LOCKDEP) && !lockdep) \
+ lockdep_off();
+
/*
* it_func[0] is never NULL because there is at least one element in the array
* when the array itself is non NULL.
@@ -129,7 +137,7 @@ extern void syscall_unregfunc(void);
* as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just
* "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto".
*/
-#define __DO_TRACE(tp, proto, args, cond, rcucheck)\
+#define __DO_TRACE(tp, proto, args, cond, rcucheck, lockdep) \
do {\
struct tracepoint_func *it_func_ptr;\
void *it_func; \
@@ -137,10 +145,14 @@ extern void syscall_unregfunc(void);
\
if (!(cond))\
return; \
+ \
+ LOCKDEP_CHECKS_OFF(lockdep) \
if (rcucheck) \
rcu_irq_enter_irqson(); \
rcu_read_lock_sched_notrace(); \
it_func_ptr = rcu_dereference_sched((tp)->funcs); \
+ LOCKDEP_CHECKS_ON(lockdep) \
+ \
if (it_func_ptr) { \
do {\
it_func = (it_func_ptr)->func; \
@@ -148,9 +160,12 @@ extern void syscall_unregfunc(void);
((void(*)(proto))(it_func))(args); \
} while ((++it_func_ptr)->func);\
} \
+ \
+ LOCKDEP_CHECKS_OFF(lockdep) \
rcu_read_unlock_sched_notrace();\
if (rcucheck) \
rcu_irq_exit_irqson(); \
+ LOCKDEP_CHECKS_ON(lockdep) \
} while (0)
#ifndef MODULE
@@ -161,7 +176,16 @@ extern void syscall_unregfunc(void);
__DO_TRACE(&__tracepoint_##name,\
TP_PROTO(data_proto), \
TP_ARGS(data_args), \
- TP_CONDITION(cond), 1); \
+ TP_CONDITION(cond), 1, 1); \
+ } \
+ \
+ static inline void trace_##name##_rcuidle_nolockdep(proto) \
+ { \
+ if (static_key_false(&__tracepoint_##name.key)) \
+ __DO_TRACE(&__tracepoint_##name,\
+ TP_PROTO(data_proto), \
+ TP_ARGS(data_args), \
+ TP_CONDITION(cond), 1, 0); \
}
#else