[RFC v4 1/4] tracepoint: Add API to not do lockdep checks during RCU ops

2018-04-16 Thread Joel Fernandes
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 

[RFC v4 1/4] tracepoint: Add API to not do lockdep checks during RCU ops

2018-04-16 Thread Joel Fernandes
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