1919#include <linux/cpumask.h>
2020#include <linux/rcupdate.h>
2121#include <linux/tracepoint-defs.h>
22+ #include <linux/static_call.h>
2223
2324struct module ;
2425struct tracepoint ;
@@ -92,7 +93,9 @@ extern int syscall_regfunc(void);
9293extern void syscall_unregfunc (void );
9394#endif /* CONFIG_HAVE_SYSCALL_TRACEPOINTS */
9495
96+ #ifndef PARAMS
9597#define PARAMS (args ...) args
98+ #endif
9699
97100#define TRACE_DEFINE_ENUM (x )
98101#define TRACE_DEFINE_SIZEOF (x )
@@ -148,6 +151,12 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
148151
149152#ifdef TRACEPOINTS_ENABLED
150153
154+ #ifdef CONFIG_HAVE_STATIC_CALL
155+ #define __DO_TRACE_CALL (name ) static_call(tp_func_##name)
156+ #else
157+ #define __DO_TRACE_CALL (name ) __tracepoint_iter_##name
158+ #endif /* CONFIG_HAVE_STATIC_CALL */
159+
151160/*
152161 * it_func[0] is never NULL because there is at least one element in the array
153162 * when the array itself is non NULL.
@@ -157,12 +166,11 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
157166 * has a "void" prototype, then it is invalid to declare a function
158167 * as "(void *, void)".
159168 */
160- #define __DO_TRACE (tp , proto , args , cond , rcuidle ) \
169+ #define __DO_TRACE (name , proto , args , cond , rcuidle ) \
161170 do { \
162171 struct tracepoint_func *it_func_ptr; \
163- void *it_func; \
164- void *__data; \
165172 int __maybe_unused __idx = 0; \
173+ void *__data; \
166174 \
167175 if (!(cond)) \
168176 return; \
@@ -182,14 +190,11 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
182190 rcu_irq_enter_irqson (); \
183191 } \
184192 \
185- it_func_ptr = rcu_dereference_raw (( tp ) -> funcs ); \
186- \
193+ it_func_ptr = \
194+ rcu_dereference_raw (( & __tracepoint_ # #name )->funcs); \
187195 if (it_func_ptr) { \
188- do { \
189- it_func = (it_func_ptr )-> func ; \
190- __data = (it_func_ptr )-> data ; \
191- ((void (* )(proto ))(it_func ))(args ); \
192- } while ((++ it_func_ptr )-> func ); \
196+ __data = (it_func_ptr)->data; \
197+ __DO_TRACE_CALL(name)(args); \
193198 } \
194199 \
195200 if (rcuidle) { \
@@ -205,7 +210,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
205210 static inline void trace_##name##_rcuidle(proto) \
206211 { \
207212 if (static_key_false(&__tracepoint_##name.key)) \
208- __DO_TRACE(&__tracepoint_## name, \
213+ __DO_TRACE(name, \
209214 TP_PROTO(data_proto), \
210215 TP_ARGS(data_args), \
211216 TP_CONDITION(cond), 1); \
@@ -227,11 +232,13 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
227232 * poking RCU a bit.
228233 */
229234#define __DECLARE_TRACE (name , proto , args , cond , data_proto , data_args ) \
235+ extern int __tracepoint_iter_##name(data_proto); \
236+ DECLARE_STATIC_CALL(tp_func_##name, __tracepoint_iter_##name); \
230237 extern struct tracepoint __tracepoint_##name; \
231238 static inline void trace_##name(proto) \
232239 { \
233240 if (static_key_false(&__tracepoint_##name.key)) \
234- __DO_TRACE(&__tracepoint_## name, \
241+ __DO_TRACE(name, \
235242 TP_PROTO(data_proto), \
236243 TP_ARGS(data_args), \
237244 TP_CONDITION(cond), 0); \
@@ -277,21 +284,50 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
277284 * structures, so we create an array of pointers that will be used for iteration
278285 * on the tracepoints.
279286 */
280- #define DEFINE_TRACE_FN (name , reg , unreg ) \
281- static const char __tpstrtab_##name[] \
282- __section(__tracepoints_strings) = #name; \
283- struct tracepoint __tracepoint_##name __used \
284- __section(__tracepoints) = \
285- { __tpstrtab_##name, STATIC_KEY_INIT_FALSE, reg, unreg, NULL };\
286- __TRACEPOINT_ENTRY(name);
287+ #define DEFINE_TRACE_FN (_name , _reg , _unreg , proto , args ) \
288+ static const char __tpstrtab_##_name[] \
289+ __section(__tracepoints_strings) = #_name; \
290+ extern struct static_call_key STATIC_CALL_KEY(tp_func_##_name); \
291+ int __tracepoint_iter_##_name(void *__data, proto); \
292+ struct tracepoint __tracepoint_##_name __used \
293+ __section(__tracepoints) = { \
294+ .name = __tpstrtab_##_name, \
295+ .key = STATIC_KEY_INIT_FALSE, \
296+ .static_call_key = &STATIC_CALL_KEY(tp_func_##_name), \
297+ .static_call_tramp = STATIC_CALL_TRAMP_ADDR(tp_func_##_name), \
298+ .iterator = &__tracepoint_iter_##_name, \
299+ .regfunc = _reg, \
300+ .unregfunc = _unreg, \
301+ .funcs = NULL }; \
302+ __TRACEPOINT_ENTRY(_name); \
303+ int __tracepoint_iter_##_name(void *__data, proto) \
304+ { \
305+ struct tracepoint_func *it_func_ptr; \
306+ void *it_func; \
307+ \
308+ it_func_ptr = \
309+ rcu_dereference_raw((&__tracepoint_##_name)->funcs); \
310+ do { \
311+ it_func = (it_func_ptr)->func; \
312+ __data = (it_func_ptr)->data; \
313+ ((void(*)(void *, proto))(it_func))(__data, args); \
314+ } while ((++it_func_ptr)->func); \
315+ return 0; \
316+ } \
317+ DEFINE_STATIC_CALL(tp_func_##_name, __tracepoint_iter_##_name);
287318
288- #define DEFINE_TRACE (name ) \
289- DEFINE_TRACE_FN(name, NULL, NULL);
319+ #define DEFINE_TRACE (name , proto , args ) \
320+ DEFINE_TRACE_FN(name, NULL, NULL, PARAMS(proto), PARAMS(args) );
290321
291322#define EXPORT_TRACEPOINT_SYMBOL_GPL (name ) \
292- EXPORT_SYMBOL_GPL(__tracepoint_##name)
323+ EXPORT_SYMBOL_GPL(__tracepoint_##name); \
324+ EXPORT_SYMBOL_GPL(__tracepoint_iter_##name); \
325+ EXPORT_STATIC_CALL_GPL(tp_func_##name)
293326#define EXPORT_TRACEPOINT_SYMBOL (name ) \
294- EXPORT_SYMBOL(__tracepoint_##name)
327+ EXPORT_SYMBOL(__tracepoint_##name); \
328+ EXPORT_SYMBOL(__tracepoint_iter_##name); \
329+ EXPORT_STATIC_CALL(tp_func_##name)
330+
295331
296332#else /* !TRACEPOINTS_ENABLED */
297333#define __DECLARE_TRACE (name , proto , args , cond , data_proto , data_args ) \
@@ -320,8 +356,8 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
320356 return false; \
321357 }
322358
323- #define DEFINE_TRACE_FN (name , reg , unreg )
324- #define DEFINE_TRACE (name )
359+ #define DEFINE_TRACE_FN (name , reg , unreg , proto , args )
360+ #define DEFINE_TRACE (name , proto , args )
325361#define EXPORT_TRACEPOINT_SYMBOL_GPL (name )
326362#define EXPORT_TRACEPOINT_SYMBOL (name )
327363
0 commit comments