aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/linux/tracepoint.h95
-rw-r--r--include/trace/ftrace.h14
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 @@
20struct module; 20struct module;
21struct tracepoint; 21struct tracepoint;
22 22
23struct tracepoint_func {
24 void *func;
25 void *data;
26};
27
23struct tracepoint { 28struct 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 */
40extern int tracepoint_probe_register(const char *name, void *probe); 45extern 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 */
46extern int tracepoint_probe_unregister(const char *name, void *probe); 51extern int
52tracepoint_probe_unregister(const char *name, void *probe, void *data);
47 53
48extern int tracepoint_probe_register_noupdate(const char *name, void *probe); 54extern int tracepoint_probe_register_noupdate(const char *name, void *probe,
49extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe); 55 void *data);
56extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe,
57 void *data);
50extern void tracepoint_probe_update_all(void); 58extern void tracepoint_probe_update_all(void);
51 59
52struct tracepoint_iter { 60struct 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 \
409static void perf_trace_##name(proto); \ 409static void perf_trace_##name(void *, proto); \
410 \ 410 \
411static notrace int \ 411static notrace int \
412perf_trace_enable_##name(struct ftrace_event_call *unused) \ 412perf_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 \
417static notrace void \ 417static notrace void \
418perf_trace_disable_##name(struct ftrace_event_call *unused) \ 418perf_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 \
581static notrace void ftrace_raw_event_##call(proto) \ 581static 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) \
586static notrace int \ 586static notrace int \
587ftrace_raw_reg_event_##call(struct ftrace_event_call *unused) \ 587ftrace_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 \
592static notrace void \ 592static notrace void \
593ftrace_raw_unreg_event_##call(struct ftrace_event_call *unused) \ 593ftrace_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 \
598static struct trace_event ftrace_event_type_##call = { \ 598static 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) \
796static notrace void perf_trace_##call(proto) \ 796static 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 \