aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/tracepoint.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/tracepoint.h')
-rw-r--r--include/linux/tracepoint.h197
1 files changed, 128 insertions, 69 deletions
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 78b4bd3be496..103d1b61aacb 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -14,18 +14,24 @@
14 * See the file COPYING for more details. 14 * See the file COPYING for more details.
15 */ 15 */
16 16
17#include <linux/errno.h>
17#include <linux/types.h> 18#include <linux/types.h>
18#include <linux/rcupdate.h> 19#include <linux/rcupdate.h>
19 20
20struct module; 21struct module;
21struct tracepoint; 22struct tracepoint;
22 23
24struct tracepoint_func {
25 void *func;
26 void *data;
27};
28
23struct tracepoint { 29struct tracepoint {
24 const char *name; /* Tracepoint name */ 30 const char *name; /* Tracepoint name */
25 int state; /* State. */ 31 int state; /* State. */
26 void (*regfunc)(void); 32 void (*regfunc)(void);
27 void (*unregfunc)(void); 33 void (*unregfunc)(void);
28 void **funcs; 34 struct tracepoint_func *funcs;
29} __attribute__((aligned(32))); /* 35} __attribute__((aligned(32))); /*
30 * Aligned on 32 bytes because it is 36 * Aligned on 32 bytes because it is
31 * globally visible and gcc happily 37 * globally visible and gcc happily
@@ -33,6 +39,68 @@ struct tracepoint {
33 * Keep in sync with vmlinux.lds.h. 39 * Keep in sync with vmlinux.lds.h.
34 */ 40 */
35 41
42/*
43 * Connect a probe to a tracepoint.
44 * Internal API, should not be used directly.
45 */
46extern int tracepoint_probe_register(const char *name, void *probe, void *data);
47
48/*
49 * Disconnect a probe from a tracepoint.
50 * Internal API, should not be used directly.
51 */
52extern int
53tracepoint_probe_unregister(const char *name, void *probe, void *data);
54
55extern int tracepoint_probe_register_noupdate(const char *name, void *probe,
56 void *data);
57extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe,
58 void *data);
59extern void tracepoint_probe_update_all(void);
60
61struct tracepoint_iter {
62 struct module *module;
63 struct tracepoint *tracepoint;
64};
65
66extern void tracepoint_iter_start(struct tracepoint_iter *iter);
67extern void tracepoint_iter_next(struct tracepoint_iter *iter);
68extern void tracepoint_iter_stop(struct tracepoint_iter *iter);
69extern void tracepoint_iter_reset(struct tracepoint_iter *iter);
70extern int tracepoint_get_iter_range(struct tracepoint **tracepoint,
71 struct tracepoint *begin, struct tracepoint *end);
72
73/*
74 * tracepoint_synchronize_unregister must be called between the last tracepoint
75 * probe unregistration and the end of module exit to make sure there is no
76 * caller executing a probe when it is freed.
77 */
78static inline void tracepoint_synchronize_unregister(void)
79{
80 synchronize_sched();
81}
82
83#define PARAMS(args...) args
84
85#ifdef CONFIG_TRACEPOINTS
86extern void tracepoint_update_probe_range(struct tracepoint *begin,
87 struct tracepoint *end);
88#else
89static inline void tracepoint_update_probe_range(struct tracepoint *begin,
90 struct tracepoint *end)
91{ }
92#endif /* CONFIG_TRACEPOINTS */
93
94#endif /* _LINUX_TRACEPOINT_H */
95
96/*
97 * Note: we keep the TRACE_EVENT and DECLARE_TRACE outside the include
98 * file ifdef protection.
99 * This is due to the way trace events work. If a file includes two
100 * trace event headers under one "CREATE_TRACE_POINTS" the first include
101 * will override the TRACE_EVENT and break the second include.
102 */
103
36#ifndef DECLARE_TRACE 104#ifndef DECLARE_TRACE
37 105
38#define TP_PROTO(args...) args 106#define TP_PROTO(args...) args
@@ -43,17 +111,27 @@ struct tracepoint {
43/* 111/*
44 * it_func[0] is never NULL because there is at least one element in the array 112 * it_func[0] is never NULL because there is at least one element in the array
45 * when the array itself is non NULL. 113 * when the array itself is non NULL.
114 *
115 * Note, the proto and args passed in includes "__data" as the first parameter.
116 * The reason for this is to handle the "void" prototype. If a tracepoint
117 * has a "void" prototype, then it is invalid to declare a function
118 * 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".
46 */ 120 */
47#define __DO_TRACE(tp, proto, args) \ 121#define __DO_TRACE(tp, proto, args) \
48 do { \ 122 do { \
49 void **it_func; \ 123 struct tracepoint_func *it_func_ptr; \
124 void *it_func; \
125 void *__data; \
50 \ 126 \
51 rcu_read_lock_sched_notrace(); \ 127 rcu_read_lock_sched_notrace(); \
52 it_func = rcu_dereference_sched((tp)->funcs); \ 128 it_func_ptr = rcu_dereference_sched((tp)->funcs); \
53 if (it_func) { \ 129 if (it_func_ptr) { \
54 do { \ 130 do { \
55 ((void(*)(proto))(*it_func))(args); \ 131 it_func = (it_func_ptr)->func; \
56 } while (*(++it_func)); \ 132 __data = (it_func_ptr)->data; \
133 ((void(*)(proto))(it_func))(args); \
134 } while ((++it_func_ptr)->func); \
57 } \ 135 } \
58 rcu_read_unlock_sched_notrace(); \ 136 rcu_read_unlock_sched_notrace(); \
59 } while (0) 137 } while (0)
@@ -63,24 +141,32 @@ struct tracepoint {
63 * 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
64 * structure. Force alignment to the same alignment as the section start. 142 * structure. Force alignment to the same alignment as the section start.
65 */ 143 */
66#define DECLARE_TRACE(name, proto, args) \ 144#define __DECLARE_TRACE(name, proto, args, data_proto, data_args) \
67 extern struct tracepoint __tracepoint_##name; \ 145 extern struct tracepoint __tracepoint_##name; \
68 static inline void trace_##name(proto) \ 146 static inline void trace_##name(proto) \
69 { \ 147 { \
70 if (unlikely(__tracepoint_##name.state)) \ 148 if (unlikely(__tracepoint_##name.state)) \
71 __DO_TRACE(&__tracepoint_##name, \ 149 __DO_TRACE(&__tracepoint_##name, \
72 TP_PROTO(proto), TP_ARGS(args)); \ 150 TP_PROTO(data_proto), \
151 TP_ARGS(data_args)); \
73 } \ 152 } \
74 static inline int register_trace_##name(void (*probe)(proto)) \ 153 static inline int \
154 register_trace_##name(void (*probe)(data_proto), void *data) \
75 { \ 155 { \
76 return tracepoint_probe_register(#name, (void *)probe); \ 156 return tracepoint_probe_register(#name, (void *)probe, \
157 data); \
77 } \ 158 } \
78 static inline int unregister_trace_##name(void (*probe)(proto)) \ 159 static inline int \
160 unregister_trace_##name(void (*probe)(data_proto), void *data) \
161 { \
162 return tracepoint_probe_unregister(#name, (void *)probe, \
163 data); \
164 } \
165 static inline void \
166 check_trace_callback_type_##name(void (*cb)(data_proto)) \
79 { \ 167 { \
80 return tracepoint_probe_unregister(#name, (void *)probe);\
81 } 168 }
82 169
83
84#define DEFINE_TRACE_FN(name, reg, unreg) \ 170#define DEFINE_TRACE_FN(name, reg, unreg) \
85 static const char __tpstrtab_##name[] \ 171 static const char __tpstrtab_##name[] \
86 __attribute__((section("__tracepoints_strings"))) = #name; \ 172 __attribute__((section("__tracepoints_strings"))) = #name; \
@@ -96,22 +182,24 @@ struct tracepoint {
96#define EXPORT_TRACEPOINT_SYMBOL(name) \ 182#define EXPORT_TRACEPOINT_SYMBOL(name) \
97 EXPORT_SYMBOL(__tracepoint_##name) 183 EXPORT_SYMBOL(__tracepoint_##name)
98 184
99extern void tracepoint_update_probe_range(struct tracepoint *begin,
100 struct tracepoint *end);
101
102#else /* !CONFIG_TRACEPOINTS */ 185#else /* !CONFIG_TRACEPOINTS */
103#define DECLARE_TRACE(name, proto, args) \ 186#define __DECLARE_TRACE(name, proto, args, data_proto, data_args) \
104 static inline void _do_trace_##name(struct tracepoint *tp, proto) \
105 { } \
106 static inline void trace_##name(proto) \ 187 static inline void trace_##name(proto) \
107 { } \ 188 { } \
108 static inline int register_trace_##name(void (*probe)(proto)) \ 189 static inline int \
190 register_trace_##name(void (*probe)(data_proto), \
191 void *data) \
109 { \ 192 { \
110 return -ENOSYS; \ 193 return -ENOSYS; \
111 } \ 194 } \
112 static inline int unregister_trace_##name(void (*probe)(proto)) \ 195 static inline int \
196 unregister_trace_##name(void (*probe)(data_proto), \
197 void *data) \
113 { \ 198 { \
114 return -ENOSYS; \ 199 return -ENOSYS; \
200 } \
201 static inline void check_trace_callback_type_##name(void (*cb)(data_proto)) \
202 { \
115 } 203 }
116 204
117#define DEFINE_TRACE_FN(name, reg, unreg) 205#define DEFINE_TRACE_FN(name, reg, unreg)
@@ -119,60 +207,31 @@ extern void tracepoint_update_probe_range(struct tracepoint *begin,
119#define EXPORT_TRACEPOINT_SYMBOL_GPL(name) 207#define EXPORT_TRACEPOINT_SYMBOL_GPL(name)
120#define EXPORT_TRACEPOINT_SYMBOL(name) 208#define EXPORT_TRACEPOINT_SYMBOL(name)
121 209
122static inline void tracepoint_update_probe_range(struct tracepoint *begin,
123 struct tracepoint *end)
124{ }
125#endif /* CONFIG_TRACEPOINTS */ 210#endif /* CONFIG_TRACEPOINTS */
126#endif /* DECLARE_TRACE */
127
128/*
129 * Connect a probe to a tracepoint.
130 * Internal API, should not be used directly.
131 */
132extern int tracepoint_probe_register(const char *name, void *probe);
133
134/*
135 * Disconnect a probe from a tracepoint.
136 * Internal API, should not be used directly.
137 */
138extern int tracepoint_probe_unregister(const char *name, void *probe);
139
140extern int tracepoint_probe_register_noupdate(const char *name, void *probe);
141extern int tracepoint_probe_unregister_noupdate(const char *name, void *probe);
142extern void tracepoint_probe_update_all(void);
143
144struct tracepoint_iter {
145 struct module *module;
146 struct tracepoint *tracepoint;
147};
148
149extern void tracepoint_iter_start(struct tracepoint_iter *iter);
150extern void tracepoint_iter_next(struct tracepoint_iter *iter);
151extern void tracepoint_iter_stop(struct tracepoint_iter *iter);
152extern void tracepoint_iter_reset(struct tracepoint_iter *iter);
153extern int tracepoint_get_iter_range(struct tracepoint **tracepoint,
154 struct tracepoint *begin, struct tracepoint *end);
155 211
156/* 212/*
157 * tracepoint_synchronize_unregister must be called between the last tracepoint 213 * The need for the DECLARE_TRACE_NOARGS() is to handle the prototype
158 * probe unregistration and the end of module exit to make sure there is no 214 * (void). "void" is a special value in a function prototype and can
159 * caller executing a probe when it is freed. 215 * not be combined with other arguments. Since the DECLARE_TRACE()
216 * macro adds a data element at the beginning of the prototype,
217 * we need a way to differentiate "(void *data, proto)" from
218 * "(void *data, void)". The second prototype is invalid.
219 *
220 * DECLARE_TRACE_NOARGS() passes "void" as the tracepoint prototype
221 * and "void *__data" as the callback prototype.
222 *
223 * DECLARE_TRACE() passes "proto" as the tracepoint protoype and
224 * "void *__data, proto" as the callback prototype.
160 */ 225 */
161static inline void tracepoint_synchronize_unregister(void) 226#define DECLARE_TRACE_NOARGS(name) \
162{ 227 __DECLARE_TRACE(name, void, , void *__data, __data)
163 synchronize_sched();
164}
165 228
166#define PARAMS(args...) args 229#define DECLARE_TRACE(name, proto, args) \
167 230 __DECLARE_TRACE(name, PARAMS(proto), PARAMS(args), \
168#endif /* _LINUX_TRACEPOINT_H */ 231 PARAMS(void *__data, proto), \
232 PARAMS(__data, args))
169 233
170/* 234#endif /* DECLARE_TRACE */
171 * Note: we keep the TRACE_EVENT outside the include file ifdef protection.
172 * This is due to the way trace events work. If a file includes two
173 * trace event headers under one "CREATE_TRACE_POINTS" the first include
174 * will override the TRACE_EVENT and break the second include.
175 */
176 235
177#ifndef TRACE_EVENT 236#ifndef TRACE_EVENT
178/* 237/*