diff options
Diffstat (limited to 'include/linux/tracepoint.h')
-rw-r--r-- | include/linux/tracepoint.h | 85 |
1 files changed, 56 insertions, 29 deletions
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 103d1b61aacb..d530a4460a0b 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/rcupdate.h> | 19 | #include <linux/rcupdate.h> |
20 | #include <linux/jump_label.h> | ||
20 | 21 | ||
21 | struct module; | 22 | struct module; |
22 | struct tracepoint; | 23 | struct tracepoint; |
@@ -28,16 +29,11 @@ struct tracepoint_func { | |||
28 | 29 | ||
29 | struct tracepoint { | 30 | struct tracepoint { |
30 | const char *name; /* Tracepoint name */ | 31 | const char *name; /* Tracepoint name */ |
31 | int state; /* State. */ | 32 | struct jump_label_key key; |
32 | void (*regfunc)(void); | 33 | void (*regfunc)(void); |
33 | void (*unregfunc)(void); | 34 | void (*unregfunc)(void); |
34 | struct tracepoint_func *funcs; | 35 | struct tracepoint_func __rcu *funcs; |
35 | } __attribute__((aligned(32))); /* | 36 | }; |
36 | * Aligned on 32 bytes because it is | ||
37 | * globally visible and gcc happily | ||
38 | * align these on the structure size. | ||
39 | * Keep in sync with vmlinux.lds.h. | ||
40 | */ | ||
41 | 37 | ||
42 | /* | 38 | /* |
43 | * Connect a probe to a tracepoint. | 39 | * Connect a probe to a tracepoint. |
@@ -60,15 +56,15 @@ extern void tracepoint_probe_update_all(void); | |||
60 | 56 | ||
61 | struct tracepoint_iter { | 57 | struct tracepoint_iter { |
62 | struct module *module; | 58 | struct module *module; |
63 | struct tracepoint *tracepoint; | 59 | struct tracepoint * const *tracepoint; |
64 | }; | 60 | }; |
65 | 61 | ||
66 | extern void tracepoint_iter_start(struct tracepoint_iter *iter); | 62 | extern void tracepoint_iter_start(struct tracepoint_iter *iter); |
67 | extern void tracepoint_iter_next(struct tracepoint_iter *iter); | 63 | extern void tracepoint_iter_next(struct tracepoint_iter *iter); |
68 | extern void tracepoint_iter_stop(struct tracepoint_iter *iter); | 64 | extern void tracepoint_iter_stop(struct tracepoint_iter *iter); |
69 | extern void tracepoint_iter_reset(struct tracepoint_iter *iter); | 65 | extern void tracepoint_iter_reset(struct tracepoint_iter *iter); |
70 | extern int tracepoint_get_iter_range(struct tracepoint **tracepoint, | 66 | extern int tracepoint_get_iter_range(struct tracepoint * const **tracepoint, |
71 | struct tracepoint *begin, struct tracepoint *end); | 67 | struct tracepoint * const *begin, struct tracepoint * const *end); |
72 | 68 | ||
73 | /* | 69 | /* |
74 | * tracepoint_synchronize_unregister must be called between the last tracepoint | 70 | * tracepoint_synchronize_unregister must be called between the last tracepoint |
@@ -83,11 +79,13 @@ static inline void tracepoint_synchronize_unregister(void) | |||
83 | #define PARAMS(args...) args | 79 | #define PARAMS(args...) args |
84 | 80 | ||
85 | #ifdef CONFIG_TRACEPOINTS | 81 | #ifdef CONFIG_TRACEPOINTS |
86 | extern void tracepoint_update_probe_range(struct tracepoint *begin, | 82 | extern |
87 | struct tracepoint *end); | 83 | void tracepoint_update_probe_range(struct tracepoint * const *begin, |
84 | struct tracepoint * const *end); | ||
88 | #else | 85 | #else |
89 | static inline void tracepoint_update_probe_range(struct tracepoint *begin, | 86 | static inline |
90 | struct tracepoint *end) | 87 | void tracepoint_update_probe_range(struct tracepoint * const *begin, |
88 | struct tracepoint * const *end) | ||
91 | { } | 89 | { } |
92 | #endif /* CONFIG_TRACEPOINTS */ | 90 | #endif /* CONFIG_TRACEPOINTS */ |
93 | 91 | ||
@@ -105,6 +103,7 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
105 | 103 | ||
106 | #define TP_PROTO(args...) args | 104 | #define TP_PROTO(args...) args |
107 | #define TP_ARGS(args...) args | 105 | #define TP_ARGS(args...) args |
106 | #define TP_CONDITION(args...) args | ||
108 | 107 | ||
109 | #ifdef CONFIG_TRACEPOINTS | 108 | #ifdef CONFIG_TRACEPOINTS |
110 | 109 | ||
@@ -118,12 +117,14 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
118 | * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just | 117 | * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just |
119 | * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto". | 118 | * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto". |
120 | */ | 119 | */ |
121 | #define __DO_TRACE(tp, proto, args) \ | 120 | #define __DO_TRACE(tp, proto, args, cond) \ |
122 | do { \ | 121 | do { \ |
123 | struct tracepoint_func *it_func_ptr; \ | 122 | struct tracepoint_func *it_func_ptr; \ |
124 | void *it_func; \ | 123 | void *it_func; \ |
125 | void *__data; \ | 124 | void *__data; \ |
126 | \ | 125 | \ |
126 | if (!(cond)) \ | ||
127 | return; \ | ||
127 | rcu_read_lock_sched_notrace(); \ | 128 | rcu_read_lock_sched_notrace(); \ |
128 | it_func_ptr = rcu_dereference_sched((tp)->funcs); \ | 129 | it_func_ptr = rcu_dereference_sched((tp)->funcs); \ |
129 | if (it_func_ptr) { \ | 130 | if (it_func_ptr) { \ |
@@ -141,14 +142,15 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
141 | * not add unwanted padding between the beginning of the section and the | 142 | * not add unwanted padding between the beginning of the section and the |
142 | * structure. Force alignment to the same alignment as the section start. | 143 | * structure. Force alignment to the same alignment as the section start. |
143 | */ | 144 | */ |
144 | #define __DECLARE_TRACE(name, proto, args, data_proto, data_args) \ | 145 | #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \ |
145 | extern struct tracepoint __tracepoint_##name; \ | 146 | extern struct tracepoint __tracepoint_##name; \ |
146 | static inline void trace_##name(proto) \ | 147 | static inline void trace_##name(proto) \ |
147 | { \ | 148 | { \ |
148 | if (unlikely(__tracepoint_##name.state)) \ | 149 | if (static_branch(&__tracepoint_##name.key)) \ |
149 | __DO_TRACE(&__tracepoint_##name, \ | 150 | __DO_TRACE(&__tracepoint_##name, \ |
150 | TP_PROTO(data_proto), \ | 151 | TP_PROTO(data_proto), \ |
151 | TP_ARGS(data_args)); \ | 152 | TP_ARGS(data_args), \ |
153 | TP_CONDITION(cond)); \ | ||
152 | } \ | 154 | } \ |
153 | static inline int \ | 155 | static inline int \ |
154 | register_trace_##name(void (*probe)(data_proto), void *data) \ | 156 | register_trace_##name(void (*probe)(data_proto), void *data) \ |
@@ -167,12 +169,20 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
167 | { \ | 169 | { \ |
168 | } | 170 | } |
169 | 171 | ||
170 | #define DEFINE_TRACE_FN(name, reg, unreg) \ | 172 | /* |
171 | static const char __tpstrtab_##name[] \ | 173 | * We have no guarantee that gcc and the linker won't up-align the tracepoint |
172 | __attribute__((section("__tracepoints_strings"))) = #name; \ | 174 | * structures, so we create an array of pointers that will be used for iteration |
173 | struct tracepoint __tracepoint_##name \ | 175 | * on the tracepoints. |
174 | __attribute__((section("__tracepoints"), aligned(32))) = \ | 176 | */ |
175 | { __tpstrtab_##name, 0, reg, unreg, NULL } | 177 | #define DEFINE_TRACE_FN(name, reg, unreg) \ |
178 | static const char __tpstrtab_##name[] \ | ||
179 | __attribute__((section("__tracepoints_strings"))) = #name; \ | ||
180 | struct tracepoint __tracepoint_##name \ | ||
181 | __attribute__((section("__tracepoints"))) = \ | ||
182 | { __tpstrtab_##name, JUMP_LABEL_INIT, reg, unreg, NULL };\ | ||
183 | static struct tracepoint * const __tracepoint_ptr_##name __used \ | ||
184 | __attribute__((section("__tracepoints_ptrs"))) = \ | ||
185 | &__tracepoint_##name; | ||
176 | 186 | ||
177 | #define DEFINE_TRACE(name) \ | 187 | #define DEFINE_TRACE(name) \ |
178 | DEFINE_TRACE_FN(name, NULL, NULL); | 188 | DEFINE_TRACE_FN(name, NULL, NULL); |
@@ -183,7 +193,7 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
183 | EXPORT_SYMBOL(__tracepoint_##name) | 193 | EXPORT_SYMBOL(__tracepoint_##name) |
184 | 194 | ||
185 | #else /* !CONFIG_TRACEPOINTS */ | 195 | #else /* !CONFIG_TRACEPOINTS */ |
186 | #define __DECLARE_TRACE(name, proto, args, data_proto, data_args) \ | 196 | #define __DECLARE_TRACE(name, proto, args, cond, data_proto, data_args) \ |
187 | static inline void trace_##name(proto) \ | 197 | static inline void trace_##name(proto) \ |
188 | { } \ | 198 | { } \ |
189 | static inline int \ | 199 | static inline int \ |
@@ -224,13 +234,20 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
224 | * "void *__data, proto" as the callback prototype. | 234 | * "void *__data, proto" as the callback prototype. |
225 | */ | 235 | */ |
226 | #define DECLARE_TRACE_NOARGS(name) \ | 236 | #define DECLARE_TRACE_NOARGS(name) \ |
227 | __DECLARE_TRACE(name, void, , void *__data, __data) | 237 | __DECLARE_TRACE(name, void, , 1, void *__data, __data) |
228 | 238 | ||
229 | #define DECLARE_TRACE(name, proto, args) \ | 239 | #define DECLARE_TRACE(name, proto, args) \ |
230 | __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), \ | 240 | __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), 1, \ |
231 | PARAMS(void *__data, proto), \ | 241 | PARAMS(void *__data, proto), \ |
232 | PARAMS(__data, args)) | 242 | PARAMS(__data, args)) |
233 | 243 | ||
244 | #define DECLARE_TRACE_CONDITION(name, proto, args, cond) \ | ||
245 | __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), PARAMS(cond), \ | ||
246 | PARAMS(void *__data, proto), \ | ||
247 | PARAMS(__data, args)) | ||
248 | |||
249 | #define TRACE_EVENT_FLAGS(event, flag) | ||
250 | |||
234 | #endif /* DECLARE_TRACE */ | 251 | #endif /* DECLARE_TRACE */ |
235 | 252 | ||
236 | #ifndef TRACE_EVENT | 253 | #ifndef TRACE_EVENT |
@@ -312,7 +329,7 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
312 | * memcpy(__entry->prev_comm, prev->comm, TASK_COMM_LEN); | 329 | * memcpy(__entry->prev_comm, prev->comm, TASK_COMM_LEN); |
313 | * __entry->next_pid = next->pid; | 330 | * __entry->next_pid = next->pid; |
314 | * __entry->next_prio = next->prio; | 331 | * __entry->next_prio = next->prio; |
315 | * ) | 332 | * ), |
316 | * | 333 | * |
317 | * * | 334 | * * |
318 | * * Formatted output of a trace record via TP_printk(). | 335 | * * Formatted output of a trace record via TP_printk(). |
@@ -344,11 +361,21 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
344 | DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) | 361 | DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) |
345 | #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ | 362 | #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ |
346 | DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) | 363 | DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) |
364 | #define DEFINE_EVENT_CONDITION(template, name, proto, \ | ||
365 | args, cond) \ | ||
366 | DECLARE_TRACE_CONDITION(name, PARAMS(proto), \ | ||
367 | PARAMS(args), PARAMS(cond)) | ||
347 | 368 | ||
348 | #define TRACE_EVENT(name, proto, args, struct, assign, print) \ | 369 | #define TRACE_EVENT(name, proto, args, struct, assign, print) \ |
349 | DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) | 370 | DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) |
350 | #define TRACE_EVENT_FN(name, proto, args, struct, \ | 371 | #define TRACE_EVENT_FN(name, proto, args, struct, \ |
351 | assign, print, reg, unreg) \ | 372 | assign, print, reg, unreg) \ |
352 | DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) | 373 | DECLARE_TRACE(name, PARAMS(proto), PARAMS(args)) |
374 | #define TRACE_EVENT_CONDITION(name, proto, args, cond, \ | ||
375 | struct, assign, print) \ | ||
376 | DECLARE_TRACE_CONDITION(name, PARAMS(proto), \ | ||
377 | PARAMS(args), PARAMS(cond)) | ||
378 | |||
379 | #define TRACE_EVENT_FLAGS(event, flag) | ||
353 | 380 | ||
354 | #endif /* ifdef TRACE_EVENT (see note above) */ | 381 | #endif /* ifdef TRACE_EVENT (see note above) */ |