tracing/rcu: Add trace_##name##__rcuidle() static tracepoint for inside rcu_idle_exit() sections
Added is a new static inline function that lets *any* tracepoint be used inside a rcu_idle_exit() section. And this also solves the problem where the same tracepoint may be used inside a rcu_idle_exit() section as well as outside of one. I added a new tracepoint function with a "_rcuidle" extension. All tracepoints can be used with either the normal "trace_foobar()" function, or the "trace_foobar_rcuidle()" function when inside a rcu_idle_exit() section. All tracepoints defined by TRACE_EVENT() or any of the derivatives will have a "_rcuidle()" function also defined. When a tracepoint is used within an rcu_idle_exit() section, the "_rcuidle()" version must be used. This denotes that the tracepoint is within rcu_idle_exit() and it allows the rcu read locks within the tracepoint to still be valid, as this version takes us out of rcu_idle_exit(). Another nice aspect about this patch is that "static inline"s are not compiled into text when not used. So only the tracepoints that actually use the _rcuidle() version will have them defined in the actual text that is booted. Link: http://lkml.kernel.org/r/1328563113.2200.39.camel@gandalf.stny.rr.com> Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Josh Triplett <josh@joshtriplett.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
f069686e4b
commit
2fbb90db1b
|
@ -114,7 +114,7 @@ static inline void tracepoint_synchronize_unregister(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) \
|
#define __DO_TRACE(tp, proto, args, cond, prercu, postrcu) \
|
||||||
do { \
|
do { \
|
||||||
struct tracepoint_func *it_func_ptr; \
|
struct tracepoint_func *it_func_ptr; \
|
||||||
void *it_func; \
|
void *it_func; \
|
||||||
|
@ -122,6 +122,7 @@ static inline void tracepoint_synchronize_unregister(void)
|
||||||
\
|
\
|
||||||
if (!(cond)) \
|
if (!(cond)) \
|
||||||
return; \
|
return; \
|
||||||
|
prercu; \
|
||||||
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) { \
|
||||||
|
@ -132,6 +133,7 @@ static inline void tracepoint_synchronize_unregister(void)
|
||||||
} while ((++it_func_ptr)->func); \
|
} while ((++it_func_ptr)->func); \
|
||||||
} \
|
} \
|
||||||
rcu_read_unlock_sched_notrace(); \
|
rcu_read_unlock_sched_notrace(); \
|
||||||
|
postrcu; \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -139,7 +141,7 @@ static inline void tracepoint_synchronize_unregister(void)
|
||||||
* not add unwanted padding between the beginning of the section and the
|
* not add unwanted padding between the beginning of the section and the
|
||||||
* structure. Force alignment to the same alignment as the section start.
|
* structure. Force alignment to the same alignment as the section start.
|
||||||
*/
|
*/
|
||||||
#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
|
#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
|
||||||
extern struct tracepoint __tracepoint_##name; \
|
extern struct tracepoint __tracepoint_##name; \
|
||||||
static inline void trace_##name(proto) \
|
static inline void trace_##name(proto) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -147,7 +149,17 @@ static inline void tracepoint_synchronize_unregister(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),,); \
|
||||||
|
} \
|
||||||
|
static inline void trace_##name##_rcuidle(proto) \
|
||||||
|
{ \
|
||||||
|
if (static_branch(&__tracepoint_##name.key)) \
|
||||||
|
__DO_TRACE(&__tracepoint_##name, \
|
||||||
|
TP_PROTO(data_proto), \
|
||||||
|
TP_ARGS(data_args), \
|
||||||
|
TP_CONDITION(cond), \
|
||||||
|
rcu_idle_exit(), \
|
||||||
|
rcu_idle_enter()); \
|
||||||
} \
|
} \
|
||||||
static inline int \
|
static inline int \
|
||||||
register_trace_##name(void (*probe)(data_proto), void *data) \
|
register_trace_##name(void (*probe)(data_proto), void *data) \
|
||||||
|
@ -190,9 +202,11 @@ static inline void tracepoint_synchronize_unregister(void)
|
||||||
EXPORT_SYMBOL(__tracepoint_##name)
|
EXPORT_SYMBOL(__tracepoint_##name)
|
||||||
|
|
||||||
#else /* !CONFIG_TRACEPOINTS */
|
#else /* !CONFIG_TRACEPOINTS */
|
||||||
#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
|
#define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \
|
||||||
static inline void trace_##name(proto) \
|
static inline void trace_##name(proto) \
|
||||||
{ } \
|
{ } \
|
||||||
|
static inline void trace_##name##_rcuidle(proto) \
|
||||||
|
{ } \
|
||||||
static inline int \
|
static inline int \
|
||||||
register_trace_##name(void (*probe)(data_proto), \
|
register_trace_##name(void (*probe)(data_proto), \
|
||||||
void *data) \
|
void *data) \
|
||||||
|
|
Loading…
Reference in New Issue