diff options
author | Steven Rostedt <srostedt@redhat.com> | 2012-02-07 09:32:43 -0500 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2012-02-13 08:23:21 -0500 |
commit | 2fbb90db1b8fcc78f43830f1a009f3af243c5f42 (patch) | |
tree | a190e127ab6bd352d95a4a0964f0f1e8858cb2f4 /include | |
parent | f069686e4bdc60a637d210ea3eea25fcdb82df88 (diff) |
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>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/tracepoint.h | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index df0a779c1bbd..fc36da97ff7e 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h | |||
@@ -114,7 +114,7 @@ static inline void tracepoint_synchronize_unregister(void) | |||
114 | * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just | 114 | * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just |
115 | * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto". | 115 | * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto". |
116 | */ | 116 | */ |
117 | #define __DO_TRACE(tp, proto, args, cond) \ | 117 | #define __DO_TRACE(tp, proto, args, cond, prercu, postrcu) \ |
118 | do { \ | 118 | do { \ |
119 | struct tracepoint_func *it_func_ptr; \ | 119 | struct tracepoint_func *it_func_ptr; \ |
120 | void *it_func; \ | 120 | void *it_func; \ |
@@ -122,6 +122,7 @@ static inline void tracepoint_synchronize_unregister(void) | |||
122 | \ | 122 | \ |
123 | if (!(cond)) \ | 123 | if (!(cond)) \ |
124 | return; \ | 124 | return; \ |
125 | prercu; \ | ||
125 | rcu_read_lock_sched_notrace(); \ | 126 | rcu_read_lock_sched_notrace(); \ |
126 | it_func_ptr = rcu_dereference_sched((tp)->funcs); \ | 127 | it_func_ptr = rcu_dereference_sched((tp)->funcs); \ |
127 | if (it_func_ptr) { \ | 128 | if (it_func_ptr) { \ |
@@ -132,6 +133,7 @@ static inline void tracepoint_synchronize_unregister(void) | |||
132 | } while ((++it_func_ptr)->func); \ | 133 | } while ((++it_func_ptr)->func); \ |
133 | } \ | 134 | } \ |
134 | rcu_read_unlock_sched_notrace(); \ | 135 | rcu_read_unlock_sched_notrace(); \ |
136 | postrcu; \ | ||
135 | } while (0) | 137 | } while (0) |
136 | 138 | ||
137 | /* | 139 | /* |
@@ -139,7 +141,7 @@ static inline void tracepoint_synchronize_unregister(void) | |||
139 | * not add unwanted padding between the beginning of the section and the | 141 | * not add unwanted padding between the beginning of the section and the |
140 | * structure. Force alignment to the same alignment as the section start. | 142 | * structure. Force alignment to the same alignment as the section start. |
141 | */ | 143 | */ |
142 | #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \ | 144 | #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \ |
143 | extern struct tracepoint __tracepoint_##name; \ | 145 | extern struct tracepoint __tracepoint_##name; \ |
144 | static inline void trace_##name(proto) \ | 146 | static inline void trace_##name(proto) \ |
145 | { \ | 147 | { \ |
@@ -147,7 +149,17 @@ static inline void tracepoint_synchronize_unregister(void) | |||
147 | __DO_TRACE(&__tracepoint_##name, \ | 149 | __DO_TRACE(&__tracepoint_##name, \ |
148 | TP_PROTO(data_proto), \ | 150 | TP_PROTO(data_proto), \ |
149 | TP_ARGS(data_args), \ | 151 | TP_ARGS(data_args), \ |
150 | TP_CONDITION(cond)); \ | 152 | TP_CONDITION(cond),,); \ |
153 | } \ | ||
154 | static inline void trace_##name##_rcuidle(proto) \ | ||
155 | { \ | ||
156 | if (static_branch(&__tracepoint_##name.key)) \ | ||
157 | __DO_TRACE(&__tracepoint_##name, \ | ||
158 | TP_PROTO(data_proto), \ | ||
159 | TP_ARGS(data_args), \ | ||
160 | TP_CONDITION(cond), \ | ||
161 | rcu_idle_exit(), \ | ||
162 | rcu_idle_enter()); \ | ||
151 | } \ | 163 | } \ |
152 | static inline int \ | 164 | static inline int \ |
153 | register_trace_##name(void (*probe)(data_proto), void *data) \ | 165 | register_trace_##name(void (*probe)(data_proto), void *data) \ |
@@ -190,9 +202,11 @@ static inline void tracepoint_synchronize_unregister(void) | |||
190 | EXPORT_SYMBOL(__tracepoint_##name) | 202 | EXPORT_SYMBOL(__tracepoint_##name) |
191 | 203 | ||
192 | #else /* !CONFIG_TRACEPOINTS */ | 204 | #else /* !CONFIG_TRACEPOINTS */ |
193 | #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \ | 205 | #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \ |
194 | static inline void trace_##name(proto) \ | 206 | static inline void trace_##name(proto) \ |
195 | { } \ | 207 | { } \ |
208 | static inline void trace_##name##_rcuidle(proto) \ | ||
209 | { } \ | ||
196 | static inline int \ | 210 | static inline int \ |
197 | register_trace_##name(void (*probe)(data_proto), \ | 211 | register_trace_##name(void (*probe)(data_proto), \ |
198 | void *data) \ | 212 | void *data) \ |