Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tracing: Add trace_<tracepoint>_enabled() function

There are some code paths in the kernel that need to do some preparations
before it calls a tracepoint. As that code is worthless overhead when
the tracepoint is not enabled, it would be prudent to have that code
only run when the tracepoint is active. To accomplish this, all tracepoints
now get a static inline function called "trace_<tracepoint-name>_enabled()"
which returns true when the tracepoint is enabled and false otherwise.

As an added bonus, that function uses the static_key of the tracepoint
such that no branch is needed.

if (trace_mytracepoint_enabled()) {
arg = process_tp_arg();
trace_mytracepoint(arg);
}

Will keep the "process_tp_arg()" (which may be expensive to run) from
being executed when the tracepoint isn't enabled.

It's best to encapsulate the tracepoint itself in the if statement
just to keep races. For example, if you had:

if (trace_mytracepoint_enabled())
arg = process_tp_arg();
trace_mytracepoint(arg);

There's a chance that the tracepoint could be enabled just after the
if statement, and arg will be undefined when calling the tracepoint.

Link: http://lkml.kernel.org/r/20140506094407.507b6435@gandalf.local.home

Acked-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>

+34
+24
Documentation/trace/tracepoints.txt
··· 115 115 EXPORT_TRACEPOINT_SYMBOL_GPL() or EXPORT_TRACEPOINT_SYMBOL() can be 116 116 used to export the defined tracepoints. 117 117 118 + If you need to do a bit of work for a tracepoint parameter, and 119 + that work is only used for the tracepoint, that work can be encapsulated 120 + within an if statement with the following: 121 + 122 + if (trace_foo_bar_enabled()) { 123 + int i; 124 + int tot = 0; 125 + 126 + for (i = 0; i < count; i++) 127 + tot += calculate_nuggets(); 128 + 129 + trace_foo_bar(tot); 130 + } 131 + 132 + All trace_<tracepoint>() calls have a matching trace_<tracepoint>_enabled() 133 + function defined that returns true if the tracepoint is enabled and 134 + false otherwise. The trace_<tracepoint>() should always be within the 135 + block of the if (trace_<tracepoint>_enabled()) to prevent races between 136 + the tracepoint being enabled and the check being seen. 137 + 138 + The advantage of using the trace_<tracepoint>_enabled() is that it uses 139 + the static_key of the tracepoint to allow the if statement to be implemented 140 + with jump labels and avoid conditional branches. 141 + 118 142 Note: The convenience macro TRACE_EVENT provides an alternative way to 119 143 define tracepoints. Check http://lwn.net/Articles/379903, 120 144 http://lwn.net/Articles/381064 and http://lwn.net/Articles/383362
+10
include/linux/tracepoint.h
··· 185 185 static inline void \ 186 186 check_trace_callback_type_##name(void (*cb)(data_proto)) \ 187 187 { \ 188 + } \ 189 + static inline bool \ 190 + trace_##name##_enabled(void) \ 191 + { \ 192 + return static_key_false(&__tracepoint_##name.key); \ 188 193 } 189 194 190 195 /* ··· 235 230 } \ 236 231 static inline void check_trace_callback_type_##name(void (*cb)(data_proto)) \ 237 232 { \ 233 + } \ 234 + static inline bool \ 235 + trace_##name##_enabled(void) \ 236 + { \ 237 + return false; \ 238 238 } 239 239 240 240 #define DEFINE_TRACE_FN(name, reg, unreg)