diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/tracepoint.h | 95 | ||||
| -rw-r--r-- | include/trace/ftrace.h | 14 |
2 files changed, 79 insertions, 30 deletions
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 8d5e4f6d96d0..9a59d1f98cd4 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h | |||
| @@ -20,12 +20,17 @@ | |||
| 20 | struct module; | 20 | struct module; |
| 21 | struct tracepoint; | 21 | struct tracepoint; |
| 22 | 22 | ||
| 23 | struct tracepoint_func { | ||
| 24 | void *func; | ||
| 25 | void *data; | ||
| 26 | }; | ||
| 27 | |||
| 23 | struct tracepoint { | 28 | struct tracepoint { |
| 24 | const char *name; /* Tracepoint name */ | 29 | const char *name; /* Tracepoint name */ |
| 25 | int state; /* State. */ | 30 | int state; /* State. */ |
| 26 | void (*regfunc)(void); | 31 | void (*regfunc)(void); |
| 27 | void (*unregfunc)(void); | 32 | void (*unregfunc)(void); |
| 28 | void **funcs; | 33 | struct tracepoint_func *funcs; |
| 29 | } __attribute__((aligned(32))); /* | 34 | } __attribute__((aligned(32))); /* |
| 30 | * Aligned on 32 bytes because it is | 35 | * Aligned on 32 bytes because it is |
| 31 | * globally visible and gcc happily | 36 | * globally visible and gcc happily |
| @@ -37,16 +42,19 @@ struct tracepoint { | |||
| 37 | * Connect a probe to a tracepoint. | 42 | * Connect a probe to a tracepoint. |
| 38 | * Internal API, should not be used directly. | 43 | * Internal API, should not be used directly. |
| 39 | */ | 44 | */ |
| 40 | extern int tracepoint_probe_register(const char *name, void *probe); | 45 | extern int tracepoint_probe_register(const char *name, void *probe, void *data); |
| 41 | 46 | ||
| 42 | /* | 47 | /* |
| 43 | * Disconnect a probe from a tracepoint. | 48 | * Disconnect a probe from a tracepoint. |
| 44 | * Internal API, should not be used directly. | 49 | * Internal API, should not be used directly. |
| 45 | */ | 50 | */ |
| 46 | extern int tracepoint_probe_unregister(const char *name, void *probe); | 51 | extern int |
| 52 | tracepoint_probe_unregister(const char *name, void *probe, void *data); | ||
| 47 | 53 | ||
| 48 | extern int tracepoint_probe_register_noupdate(const char *name, void *probe); | 54 | extern int tracepoint_probe_register_noupdate(const char *name, void *probe, |
| 49 | extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe); | 55 | void *data); |
| 56 | extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe, | ||
| 57 | void *data); | ||
| 50 | extern void tracepoint_probe_update_all(void); | 58 | extern void tracepoint_probe_update_all(void); |
| 51 | 59 | ||
| 52 | struct tracepoint_iter { | 60 | struct tracepoint_iter { |
| @@ -102,17 +110,27 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
| 102 | /* | 110 | /* |
| 103 | * it_func[0] is never NULL because there is at least one element in the array | 111 | * it_func[0] is never NULL because there is at least one element in the array |
| 104 | * when the array itself is non NULL. | 112 | * when the array itself is non NULL. |
| 113 | * | ||
| 114 | * Note, the proto and args passed in includes "__data" as the first parameter. | ||
| 115 | * The reason for this is to handle the "void" prototype. If a tracepoint | ||
| 116 | * has a "void" prototype, then it is invalid to declare a function | ||
| 117 | * as "(void *, void)". The DECLARE_TRACE_NOARGS() will pass in just | ||
| 118 | * "void *data", where as the DECLARE_TRACE() will pass in "void *data, proto". | ||
| 105 | */ | 119 | */ |
| 106 | #define __DO_TRACE(tp, proto, args) \ | 120 | #define __DO_TRACE(tp, proto, args) \ |
| 107 | do { \ | 121 | do { \ |
| 108 | void **it_func; \ | 122 | struct tracepoint_func *it_func_ptr; \ |
| 123 | void *it_func; \ | ||
| 124 | void *__data; \ | ||
| 109 | \ | 125 | \ |
| 110 | rcu_read_lock_sched_notrace(); \ | 126 | rcu_read_lock_sched_notrace(); \ |
| 111 | it_func = rcu_dereference_sched((tp)->funcs); \ | 127 | it_func_ptr = rcu_dereference_sched((tp)->funcs); \ |
| 112 | if (it_func) { \ | 128 | if (it_func_ptr) { \ |
| 113 | do { \ | 129 | do { \ |
| 114 | ((void(*)(proto))(*it_func))(args); \ | 130 | it_func = (it_func_ptr)->func; \ |
| 115 | } while (*(++it_func)); \ | 131 | __data = (it_func_ptr)->data; \ |
| 132 | ((void(*)(proto))(it_func))(args); \ | ||
| 133 | } while ((++it_func_ptr)->func); \ | ||
| 116 | } \ | 134 | } \ |
| 117 | rcu_read_unlock_sched_notrace(); \ | 135 | rcu_read_unlock_sched_notrace(); \ |
| 118 | } while (0) | 136 | } while (0) |
| @@ -122,23 +140,29 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
| 122 | * not add unwanted padding between the beginning of the section and the | 140 | * not add unwanted padding between the beginning of the section and the |
| 123 | * structure. Force alignment to the same alignment as the section start. | 141 | * structure. Force alignment to the same alignment as the section start. |
| 124 | */ | 142 | */ |
| 125 | #define DECLARE_TRACE(name, proto, args) \ | 143 | #define __DECLARE_TRACE(name, proto, args, data_proto, data_args) \ |
| 126 | extern struct tracepoint __tracepoint_##name; \ | 144 | extern struct tracepoint __tracepoint_##name; \ |
| 127 | static inline void trace_##name(proto) \ | 145 | static inline void trace_##name(proto) \ |
| 128 | { \ | 146 | { \ |
| 129 | if (unlikely(__tracepoint_##name.state)) \ | 147 | if (unlikely(__tracepoint_##name.state)) \ |
| 130 | __DO_TRACE(&__tracepoint_##name, \ | 148 | __DO_TRACE(&__tracepoint_##name, \ |
| 131 | TP_PROTO(proto), TP_ARGS(args)); \ | 149 | TP_PROTO(data_proto), \ |
| 150 | TP_ARGS(data_args)); \ | ||
| 132 | } \ | 151 | } \ |
| 133 | static inline int register_trace_##name(void (*probe)(proto)) \ | 152 | static inline int \ |
| 153 | register_trace_##name(void (*probe)(data_proto), void *data) \ | ||
| 134 | { \ | 154 | { \ |
| 135 | return tracepoint_probe_register(#name, (void *)probe); \ | 155 | return tracepoint_probe_register(#name, (void *)probe, \ |
| 156 | data); \ | ||
| 136 | } \ | 157 | } \ |
| 137 | static inline int unregister_trace_##name(void (*probe)(proto)) \ | 158 | static inline int \ |
| 159 | unregister_trace_##name(void (*probe)(data_proto), void *data) \ | ||
| 138 | { \ | 160 | { \ |
| 139 | return tracepoint_probe_unregister(#name, (void *)probe);\ | 161 | return tracepoint_probe_unregister(#name, (void *)probe, \ |
| 162 | data); \ | ||
| 140 | } \ | 163 | } \ |
| 141 | static inline void check_trace_callback_type_##name(void (*cb)(proto)) \ | 164 | static inline void \ |
| 165 | check_trace_callback_type_##name(void (*cb)(data_proto)) \ | ||
| 142 | { \ | 166 | { \ |
| 143 | } | 167 | } |
| 144 | 168 | ||
| @@ -158,20 +182,22 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
| 158 | EXPORT_SYMBOL(__tracepoint_##name) | 182 | EXPORT_SYMBOL(__tracepoint_##name) |
| 159 | 183 | ||
| 160 | #else /* !CONFIG_TRACEPOINTS */ | 184 | #else /* !CONFIG_TRACEPOINTS */ |
| 161 | #define DECLARE_TRACE(name, proto, args) \ | 185 | #define __DECLARE_TRACE(name, proto, args, data_proto, data_args) \ |
| 162 | static inline void _do_trace_##name(struct tracepoint *tp, proto) \ | ||
| 163 | { } \ | ||
| 164 | static inline void trace_##name(proto) \ | 186 | static inline void trace_##name(proto) \ |
| 165 | { } \ | 187 | { } \ |
| 166 | static inline int register_trace_##name(void (*probe)(proto)) \ | 188 | static inline int \ |
| 189 | register_trace_##name(void (*probe)(data_proto), \ | ||
| 190 | void *data) \ | ||
| 167 | { \ | 191 | { \ |
| 168 | return -ENOSYS; \ | 192 | return -ENOSYS; \ |
| 169 | } \ | 193 | } \ |
| 170 | static inline int unregister_trace_##name(void (*probe)(proto)) \ | 194 | static inline int \ |
| 195 | unregister_trace_##name(void (*probe)(data_proto), \ | ||
| 196 | void *data) \ | ||
| 171 | { \ | 197 | { \ |
| 172 | return -ENOSYS; \ | 198 | return -ENOSYS; \ |
| 173 | } \ | 199 | } \ |
| 174 | static inline void check_trace_callback_type_##name(void (*cb)(proto)) \ | 200 | static inline void check_trace_callback_type_##name(void (*cb)(data_proto)) \ |
| 175 | { \ | 201 | { \ |
| 176 | } | 202 | } |
| 177 | 203 | ||
| @@ -181,6 +207,29 @@ static inline void tracepoint_update_probe_range(struct tracepoint *begin, | |||
| 181 | #define EXPORT_TRACEPOINT_SYMBOL(name) | 207 | #define EXPORT_TRACEPOINT_SYMBOL(name) |
| 182 | 208 | ||
| 183 | #endif /* CONFIG_TRACEPOINTS */ | 209 | #endif /* CONFIG_TRACEPOINTS */ |
| 210 | |||
| 211 | /* | ||
| 212 | * The need for the DECLARE_TRACE_NOARGS() is to handle the prototype | ||
| 213 | * (void). "void" is a special value in a function prototype and can | ||
| 214 | * not be combined with other arguments. Since the DECLARE_TRACE() | ||
| 215 | * macro adds a data element at the beginning of the prototype, | ||
| 216 | * we need a way to differentiate "(void *data, proto)" from | ||
| 217 | * "(void *data, void)". The second prototype is invalid. | ||
| 218 | * | ||
| 219 | * DECLARE_TRACE_NOARGS() passes "void" as the tracepoint prototype | ||
| 220 | * and "void *__data" as the callback prototype. | ||
| 221 | * | ||
| 222 | * DECLARE_TRACE() passes "proto" as the tracepoint protoype and | ||
| 223 | * "void *__data, proto" as the callback prototype. | ||
| 224 | */ | ||
| 225 | #define DECLARE_TRACE_NOARGS(name) \ | ||
| 226 | __DECLARE_TRACE(name, void, , void *__data, __data) | ||
| 227 | |||
| 228 | #define DECLARE_TRACE(name, proto, args) \ | ||
| 229 | __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), \ | ||
| 230 | PARAMS(void *__data, proto), \ | ||
| 231 | PARAMS(__data, args)) | ||
| 232 | |||
| 184 | #endif /* DECLARE_TRACE */ | 233 | #endif /* DECLARE_TRACE */ |
| 185 | 234 | ||
| 186 | #ifndef TRACE_EVENT | 235 | #ifndef TRACE_EVENT |
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 7dcdfd824aab..ba28b644f41b 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h | |||
| @@ -406,18 +406,18 @@ static inline notrace int ftrace_get_offsets_##call( \ | |||
| 406 | #undef DEFINE_EVENT | 406 | #undef DEFINE_EVENT |
| 407 | #define DEFINE_EVENT(template, name, proto, args) \ | 407 | #define DEFINE_EVENT(template, name, proto, args) \ |
| 408 | \ | 408 | \ |
| 409 | static void perf_trace_##name(proto); \ | 409 | static void perf_trace_##name(void *, proto); \ |
| 410 | \ | 410 | \ |
| 411 | static notrace int \ | 411 | static notrace int \ |
| 412 | perf_trace_enable_##name(struct ftrace_event_call *unused) \ | 412 | perf_trace_enable_##name(struct ftrace_event_call *unused) \ |
| 413 | { \ | 413 | { \ |
| 414 | return register_trace_##name(perf_trace_##name); \ | 414 | return register_trace_##name(perf_trace_##name, NULL); \ |
| 415 | } \ | 415 | } \ |
| 416 | \ | 416 | \ |
| 417 | static notrace void \ | 417 | static notrace void \ |
| 418 | perf_trace_disable_##name(struct ftrace_event_call *unused) \ | 418 | perf_trace_disable_##name(struct ftrace_event_call *unused) \ |
| 419 | { \ | 419 | { \ |
| 420 | unregister_trace_##name(perf_trace_##name); \ | 420 | unregister_trace_##name(perf_trace_##name, NULL); \ |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | #undef DEFINE_EVENT_PRINT | 423 | #undef DEFINE_EVENT_PRINT |
| @@ -578,7 +578,7 @@ ftrace_raw_event_id_##call(struct ftrace_event_call *event_call, \ | |||
| 578 | #undef DEFINE_EVENT | 578 | #undef DEFINE_EVENT |
| 579 | #define DEFINE_EVENT(template, call, proto, args) \ | 579 | #define DEFINE_EVENT(template, call, proto, args) \ |
| 580 | \ | 580 | \ |
| 581 | static notrace void ftrace_raw_event_##call(proto) \ | 581 | static notrace void ftrace_raw_event_##call(void *__ignore, proto) \ |
| 582 | { \ | 582 | { \ |
| 583 | ftrace_raw_event_id_##template(&event_##call, args); \ | 583 | ftrace_raw_event_id_##template(&event_##call, args); \ |
| 584 | } \ | 584 | } \ |
| @@ -586,13 +586,13 @@ static notrace void ftrace_raw_event_##call(proto) \ | |||
| 586 | static notrace int \ | 586 | static notrace int \ |
| 587 | ftrace_raw_reg_event_##call(struct ftrace_event_call *unused) \ | 587 | ftrace_raw_reg_event_##call(struct ftrace_event_call *unused) \ |
| 588 | { \ | 588 | { \ |
| 589 | return register_trace_##call(ftrace_raw_event_##call); \ | 589 | return register_trace_##call(ftrace_raw_event_##call, NULL); \ |
| 590 | } \ | 590 | } \ |
| 591 | \ | 591 | \ |
| 592 | static notrace void \ | 592 | static notrace void \ |
| 593 | ftrace_raw_unreg_event_##call(struct ftrace_event_call *unused) \ | 593 | ftrace_raw_unreg_event_##call(struct ftrace_event_call *unused) \ |
| 594 | { \ | 594 | { \ |
| 595 | unregister_trace_##call(ftrace_raw_event_##call); \ | 595 | unregister_trace_##call(ftrace_raw_event_##call, NULL); \ |
| 596 | } \ | 596 | } \ |
| 597 | \ | 597 | \ |
| 598 | static struct trace_event ftrace_event_type_##call = { \ | 598 | static struct trace_event ftrace_event_type_##call = { \ |
| @@ -793,7 +793,7 @@ perf_trace_templ_##call(struct ftrace_event_call *event_call, \ | |||
| 793 | 793 | ||
| 794 | #undef DEFINE_EVENT | 794 | #undef DEFINE_EVENT |
| 795 | #define DEFINE_EVENT(template, call, proto, args) \ | 795 | #define DEFINE_EVENT(template, call, proto, args) \ |
| 796 | static notrace void perf_trace_##call(proto) \ | 796 | static notrace void perf_trace_##call(void *__ignore, proto) \ |
| 797 | { \ | 797 | { \ |
| 798 | struct ftrace_event_call *event_call = &event_##call; \ | 798 | struct ftrace_event_call *event_call = &event_##call; \ |
| 799 | \ | 799 | \ |
