| .. | .. | 
|---|
| 11 | 11 | #include <linux/atomic.h> | 
|---|
| 12 | 12 | #include <linux/static_key.h> | 
|---|
| 13 | 13 |  | 
|---|
|  | 14 | +struct static_call_key; | 
|---|
|  | 15 | + | 
|---|
| 14 | 16 | struct trace_print_flags { | 
|---|
| 15 | 17 | unsigned long		mask; | 
|---|
| 16 | 18 | const char		*name; | 
|---|
| .. | .. | 
|---|
| 30 | 32 | struct tracepoint { | 
|---|
| 31 | 33 | const char *name;		/* Tracepoint name */ | 
|---|
| 32 | 34 | struct static_key key; | 
|---|
|  | 35 | +	struct static_call_key *static_call_key; | 
|---|
|  | 36 | +	void *static_call_tramp; | 
|---|
|  | 37 | +	void *iterator; | 
|---|
| 33 | 38 | int (*regfunc)(void); | 
|---|
| 34 | 39 | void (*unregfunc)(void); | 
|---|
| 35 | 40 | struct tracepoint_func __rcu *funcs; | 
|---|
| .. | .. | 
|---|
| 45 | 50 | struct tracepoint	*tp; | 
|---|
| 46 | 51 | void			*bpf_func; | 
|---|
| 47 | 52 | u32			num_args; | 
|---|
|  | 53 | +	u32			writable_size; | 
|---|
| 48 | 54 | } __aligned(32); | 
|---|
| 49 | 55 |  | 
|---|
|  | 56 | +/* | 
|---|
|  | 57 | + * If a tracepoint needs to be called from a header file, it is not | 
|---|
|  | 58 | + * recommended to call it directly, as tracepoints in header files | 
|---|
|  | 59 | + * may cause side-effects and bloat the kernel. Instead, use | 
|---|
|  | 60 | + * tracepoint_enabled() to test if the tracepoint is enabled, then if | 
|---|
|  | 61 | + * it is, call a wrapper function defined in a C file that will then | 
|---|
|  | 62 | + * call the tracepoint. | 
|---|
|  | 63 | + * | 
|---|
|  | 64 | + * For "trace_foo_bar()", you would need to create a wrapper function | 
|---|
|  | 65 | + * in a C file to call trace_foo_bar(): | 
|---|
|  | 66 | + *   void do_trace_foo_bar(args) { trace_foo_bar(args); } | 
|---|
|  | 67 | + * Then in the header file, declare the tracepoint: | 
|---|
|  | 68 | + *   DECLARE_TRACEPOINT(foo_bar); | 
|---|
|  | 69 | + * And call your wrapper: | 
|---|
|  | 70 | + *   static inline void some_inlined_function() { | 
|---|
|  | 71 | + *            [..] | 
|---|
|  | 72 | + *            if (tracepoint_enabled(foo_bar)) | 
|---|
|  | 73 | + *                    do_trace_foo_bar(args); | 
|---|
|  | 74 | + *            [..] | 
|---|
|  | 75 | + *   } | 
|---|
|  | 76 | + * | 
|---|
|  | 77 | + * Note: tracepoint_enabled(foo_bar) is equivalent to trace_foo_bar_enabled() | 
|---|
|  | 78 | + *   but is safe to have in headers, where trace_foo_bar_enabled() is not. | 
|---|
|  | 79 | + */ | 
|---|
|  | 80 | +#define DECLARE_TRACEPOINT(tp) \ | 
|---|
|  | 81 | +	extern struct tracepoint __tracepoint_##tp | 
|---|
|  | 82 | + | 
|---|
|  | 83 | +#ifdef CONFIG_TRACEPOINTS | 
|---|
|  | 84 | +# define tracepoint_enabled(tp) \ | 
|---|
|  | 85 | +	static_key_false(&(__tracepoint_##tp).key) | 
|---|
|  | 86 | +#else | 
|---|
|  | 87 | +# define tracepoint_enabled(tracepoint) false | 
|---|
|  | 88 | +#endif | 
|---|
|  | 89 | + | 
|---|
| 50 | 90 | #endif | 
|---|