Skip to content

Commit 3a73333

Browse files
committed
tracing: Add TRACE_CUSTOM_EVENT() macro
To make it really easy to add custom events from modules, add a TRACE_CUSTOM_EVENT() macro that acts just like the TRACE_EVENT() macro, but creates a custom event to an already existing tracepoint. The trace_custom_sched.[ch] has been updated to use this new macro to show how simple it is. Link: https://lkml.kernel.org/r/20220303220625.738622494@goodmis.org Cc: Ingo Molnar <mingo@kernel.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Joel Fernandes <joel@joelfernandes.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Tom Zanussi <zanussi@kernel.org> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
1 parent af6b966 commit 3a73333

6 files changed

Lines changed: 441 additions & 237 deletions

File tree

include/linux/trace_events.h

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ enum {
315315
TRACE_EVENT_FL_KPROBE_BIT,
316316
TRACE_EVENT_FL_UPROBE_BIT,
317317
TRACE_EVENT_FL_EPROBE_BIT,
318+
TRACE_EVENT_FL_CUSTOM_BIT,
318319
};
319320

320321
/*
@@ -328,6 +329,9 @@ enum {
328329
* KPROBE - Event is a kprobe
329330
* UPROBE - Event is a uprobe
330331
* EPROBE - Event is an event probe
332+
* CUSTOM - Event is a custom event (to be attached to an exsiting tracepoint)
333+
* This is set when the custom event has not been attached
334+
* to a tracepoint yet, then it is cleared when it is.
331335
*/
332336
enum {
333337
TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT),
@@ -339,6 +343,7 @@ enum {
339343
TRACE_EVENT_FL_KPROBE = (1 << TRACE_EVENT_FL_KPROBE_BIT),
340344
TRACE_EVENT_FL_UPROBE = (1 << TRACE_EVENT_FL_UPROBE_BIT),
341345
TRACE_EVENT_FL_EPROBE = (1 << TRACE_EVENT_FL_EPROBE_BIT),
346+
TRACE_EVENT_FL_CUSTOM = (1 << TRACE_EVENT_FL_CUSTOM_BIT),
342347
};
343348

344349
#define TRACE_EVENT_FL_UKPROBE (TRACE_EVENT_FL_KPROBE | TRACE_EVENT_FL_UPROBE)
@@ -440,7 +445,9 @@ static inline bool bpf_prog_array_valid(struct trace_event_call *call)
440445
static inline const char *
441446
trace_event_name(struct trace_event_call *call)
442447
{
443-
if (call->flags & TRACE_EVENT_FL_TRACEPOINT)
448+
if (call->flags & TRACE_EVENT_FL_CUSTOM)
449+
return call->name;
450+
else if (call->flags & TRACE_EVENT_FL_TRACEPOINT)
444451
return call->tp ? call->tp->name : NULL;
445452
else
446453
return call->name;
@@ -901,3 +908,18 @@ perf_trace_buf_submit(void *raw_data, int size, int rctx, u16 type,
901908
#endif
902909

903910
#endif /* _LINUX_TRACE_EVENT_H */
911+
912+
/*
913+
* Note: we keep the TRACE_CUSTOM_EVENT outside the include file ifdef protection.
914+
* This is due to the way trace custom events work. If a file includes two
915+
* trace event headers under one "CREATE_CUSTOM_TRACE_EVENTS" the first include
916+
* will override the TRACE_CUSTOM_EVENT and break the second include.
917+
*/
918+
919+
#ifndef TRACE_CUSTOM_EVENT
920+
921+
#define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print)
922+
#define DEFINE_CUSTOM_EVENT(template, name, proto, args)
923+
#define TRACE_CUSTOM_EVENT(name, proto, args, struct, assign, print)
924+
925+
#endif /* ifdef TRACE_CUSTOM_EVENT (see note above) */
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* Trace files that want to automate creation of all tracepoints defined
4+
* in their file should include this file. The following are macros that the
5+
* trace file may define:
6+
*
7+
* TRACE_SYSTEM defines the system the tracepoint is for
8+
*
9+
* TRACE_INCLUDE_FILE if the file name is something other than TRACE_SYSTEM.h
10+
* This macro may be defined to tell define_trace.h what file to include.
11+
* Note, leave off the ".h".
12+
*
13+
* TRACE_INCLUDE_PATH if the path is something other than core kernel include/trace
14+
* then this macro can define the path to use. Note, the path is relative to
15+
* define_trace.h, not the file including it. Full path names for out of tree
16+
* modules must be used.
17+
*/
18+
19+
#ifdef CREATE_CUSTOM_TRACE_EVENTS
20+
21+
/* Prevent recursion */
22+
#undef CREATE_CUSTOM_TRACE_EVENTS
23+
24+
#include <linux/stringify.h>
25+
26+
#undef TRACE_CUSTOM_EVENT
27+
#define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print)
28+
29+
#undef DEFINE_CUSTOM_EVENT
30+
#define DEFINE_CUSTOM_EVENT(template, name, proto, args)
31+
32+
#undef TRACE_INCLUDE
33+
#undef __TRACE_INCLUDE
34+
35+
#ifndef TRACE_INCLUDE_FILE
36+
# define TRACE_INCLUDE_FILE TRACE_SYSTEM
37+
# define UNDEF_TRACE_INCLUDE_FILE
38+
#endif
39+
40+
#ifndef TRACE_INCLUDE_PATH
41+
# define __TRACE_INCLUDE(system) <trace/events/system.h>
42+
# define UNDEF_TRACE_INCLUDE_PATH
43+
#else
44+
# define __TRACE_INCLUDE(system) __stringify(TRACE_INCLUDE_PATH/system.h)
45+
#endif
46+
47+
# define TRACE_INCLUDE(system) __TRACE_INCLUDE(system)
48+
49+
/* Let the trace headers be reread */
50+
#define TRACE_CUSTOM_MULTI_READ
51+
52+
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
53+
54+
#ifdef TRACEPOINTS_ENABLED
55+
#include <trace/trace_custom_events.h>
56+
#endif
57+
58+
#undef TRACE_CUSTOM_EVENT
59+
#undef DECLARE_CUSTOM_EVENT_CLASS
60+
#undef DEFINE_CUSTOM_EVENT
61+
#undef TRACE_CUSTOM_MULTI_READ
62+
63+
/* Only undef what we defined in this file */
64+
#ifdef UNDEF_TRACE_INCLUDE_FILE
65+
# undef TRACE_INCLUDE_FILE
66+
# undef UNDEF_TRACE_INCLUDE_FILE
67+
#endif
68+
69+
#ifdef UNDEF_TRACE_INCLUDE_PATH
70+
# undef TRACE_INCLUDE_PATH
71+
# undef UNDEF_TRACE_INCLUDE_PATH
72+
#endif
73+
74+
/* We may be processing more files */
75+
#define CREATE_CUSTOM_TRACE_POINTS
76+
77+
#endif /* CREATE_CUSTOM_TRACE_POINTS */
Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/*
3+
* This is similar to the trace_events.h file, but is to only
4+
* create custom trace events to be attached to existing tracepoints.
5+
* Where as the TRACE_EVENT() macro (from trace_events.h) will create
6+
* both the trace event and the tracepoint it will attach the event to,
7+
* TRACE_CUSTOM_EVENT() is to create only a custom version of an existing
8+
* trace event (created by TRACE_EVENT() or DEFINE_EVENT()), and will
9+
* be placed in the "custom" system.
10+
*/
11+
12+
#include <linux/trace_events.h>
13+
14+
/* All custom events are placed in the custom group */
15+
#undef TRACE_SYSTEM
16+
#define TRACE_SYSTEM custom
17+
18+
#ifndef TRACE_SYSTEM_VAR
19+
#define TRACE_SYSTEM_VAR TRACE_SYSTEM
20+
#endif
21+
22+
/* The init stage creates the system string and enum mappings */
23+
24+
#include "stages/init.h"
25+
26+
#undef TRACE_CUSTOM_EVENT
27+
#define TRACE_CUSTOM_EVENT(name, proto, args, tstruct, assign, print) \
28+
DECLARE_CUSTOM_EVENT_CLASS(name, \
29+
PARAMS(proto), \
30+
PARAMS(args), \
31+
PARAMS(tstruct), \
32+
PARAMS(assign), \
33+
PARAMS(print)); \
34+
DEFINE_CUSTOM_EVENT(name, name, PARAMS(proto), PARAMS(args));
35+
36+
/* Stage 1 creates the structure of the recorded event layout */
37+
38+
#include "stages/stage1_defines.h"
39+
40+
#undef DECLARE_CUSTOM_EVENT_CLASS
41+
#define DECLARE_CUSTOM_EVENT_CLASS(name, proto, args, tstruct, assign, print) \
42+
struct trace_custom_event_raw_##name { \
43+
struct trace_entry ent; \
44+
tstruct \
45+
char __data[]; \
46+
}; \
47+
\
48+
static struct trace_event_class custom_event_class_##name;
49+
50+
#undef DEFINE_CUSTOM_EVENT
51+
#define DEFINE_CUSTOM_EVENT(template, name, proto, args) \
52+
static struct trace_event_call __used \
53+
__attribute__((__aligned__(4))) custom_event_##name
54+
55+
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
56+
57+
/* Stage 2 creates the custom class */
58+
59+
#include "stages/stage2_defines.h"
60+
61+
#undef DECLARE_CUSTOM_EVENT_CLASS
62+
#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
63+
struct trace_custom_event_data_offsets_##call { \
64+
tstruct; \
65+
};
66+
67+
#undef DEFINE_CUSTOM_EVENT
68+
#define DEFINE_CUSTOM_EVENT(template, name, proto, args)
69+
70+
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
71+
72+
/* Stage 3 create the way to print the custom event */
73+
74+
#include "stages/stage3_defines.h"
75+
76+
#undef DECLARE_CUSTOM_EVENT_CLASS
77+
#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
78+
static notrace enum print_line_t \
79+
trace_custom_raw_output_##call(struct trace_iterator *iter, int flags, \
80+
struct trace_event *trace_event) \
81+
{ \
82+
struct trace_seq *s = &iter->seq; \
83+
struct trace_seq __maybe_unused *p = &iter->tmp_seq; \
84+
struct trace_custom_event_raw_##call *field; \
85+
int ret; \
86+
\
87+
field = (typeof(field))iter->ent; \
88+
\
89+
ret = trace_raw_output_prep(iter, trace_event); \
90+
if (ret != TRACE_TYPE_HANDLED) \
91+
return ret; \
92+
\
93+
trace_event_printf(iter, print); \
94+
\
95+
return trace_handle_return(s); \
96+
} \
97+
static struct trace_event_functions trace_custom_event_type_funcs_##call = { \
98+
.trace = trace_custom_raw_output_##call, \
99+
};
100+
101+
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
102+
103+
/* Stage 4 creates the offset layout for the fields */
104+
105+
#include "stages/stage4_defines.h"
106+
107+
#undef DECLARE_CUSTOM_EVENT_CLASS
108+
#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, func, print) \
109+
static struct trace_event_fields trace_custom_event_fields_##call[] = { \
110+
tstruct \
111+
{} };
112+
113+
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
114+
115+
/* Stage 5 creates the helper function for dynamic fields */
116+
117+
#include "stages/stage5_defines.h"
118+
119+
#undef DECLARE_CUSTOM_EVENT_CLASS
120+
#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
121+
static inline notrace int trace_custom_event_get_offsets_##call( \
122+
struct trace_custom_event_data_offsets_##call *__data_offsets, proto) \
123+
{ \
124+
int __data_size = 0; \
125+
int __maybe_unused __item_length; \
126+
struct trace_custom_event_raw_##call __maybe_unused *entry; \
127+
\
128+
tstruct; \
129+
\
130+
return __data_size; \
131+
}
132+
133+
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
134+
135+
/* Stage 6 creates the probe function that records the event */
136+
137+
#include "stages/stage6_defines.h"
138+
139+
#undef DECLARE_CUSTOM_EVENT_CLASS
140+
#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
141+
\
142+
static notrace void \
143+
trace_custom_event_raw_event_##call(void *__data, proto) \
144+
{ \
145+
struct trace_event_file *trace_file = __data; \
146+
struct trace_custom_event_data_offsets_##call __maybe_unused __data_offsets; \
147+
struct trace_event_buffer fbuffer; \
148+
struct trace_custom_event_raw_##call *entry; \
149+
int __data_size; \
150+
\
151+
if (trace_trigger_soft_disabled(trace_file)) \
152+
return; \
153+
\
154+
__data_size = trace_custom_event_get_offsets_##call(&__data_offsets, args); \
155+
\
156+
entry = trace_event_buffer_reserve(&fbuffer, trace_file, \
157+
sizeof(*entry) + __data_size); \
158+
\
159+
if (!entry) \
160+
return; \
161+
\
162+
tstruct \
163+
\
164+
{ assign; } \
165+
\
166+
trace_event_buffer_commit(&fbuffer); \
167+
}
168+
/*
169+
* The ftrace_test_custom_probe is compiled out, it is only here as a build time check
170+
* to make sure that if the tracepoint handling changes, the ftrace probe will
171+
* fail to compile unless it too is updated.
172+
*/
173+
174+
#undef DEFINE_CUSTOM_EVENT
175+
#define DEFINE_CUSTOM_EVENT(template, call, proto, args) \
176+
static inline void ftrace_test_custom_probe_##call(void) \
177+
{ \
178+
check_trace_callback_type_##call(trace_custom_event_raw_event_##template); \
179+
}
180+
181+
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
182+
183+
/* Stage 7 creates the actual class and event structure for the custom event */
184+
185+
#include "stages/stage7_defines.h"
186+
187+
#undef DECLARE_CUSTOM_EVENT_CLASS
188+
#define DECLARE_CUSTOM_EVENT_CLASS(call, proto, args, tstruct, assign, print) \
189+
static char custom_print_fmt_##call[] = print; \
190+
static struct trace_event_class __used __refdata custom_event_class_##call = { \
191+
.system = TRACE_SYSTEM_STRING, \
192+
.fields_array = trace_custom_event_fields_##call, \
193+
.fields = LIST_HEAD_INIT(custom_event_class_##call.fields),\
194+
.raw_init = trace_event_raw_init, \
195+
.probe = trace_custom_event_raw_event_##call, \
196+
.reg = trace_event_reg, \
197+
};
198+
199+
#undef DEFINE_CUSTOM_EVENT
200+
#define DEFINE_CUSTOM_EVENT(template, call, proto, args) \
201+
\
202+
static struct trace_event_call __used custom_event_##call = { \
203+
.name = #call, \
204+
.class = &custom_event_class_##template, \
205+
.event.funcs = &trace_custom_event_type_funcs_##template, \
206+
.print_fmt = custom_print_fmt_##template, \
207+
.flags = TRACE_EVENT_FL_CUSTOM, \
208+
}; \
209+
static inline int trace_custom_event_##call##_update(struct tracepoint *tp) \
210+
{ \
211+
if (tp->name && strcmp(tp->name, #call) == 0) { \
212+
custom_event_##call.tp = tp; \
213+
custom_event_##call.flags = TRACE_EVENT_FL_TRACEPOINT; \
214+
return 1; \
215+
} \
216+
return 0; \
217+
} \
218+
static struct trace_event_call __used \
219+
__section("_ftrace_events") *__custom_event_##call = &custom_event_##call
220+
221+
#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)

samples/trace_events/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
# Here trace-events-sample.c does the CREATE_TRACE_POINTS.
1212
#
1313
CFLAGS_trace-events-sample.o := -I$(src)
14+
CFLAGS_trace_custom_sched.o := -I$(src)
1415

1516
obj-$(CONFIG_SAMPLE_TRACE_EVENTS) += trace-events-sample.o
16-
1717
obj-$(CONFIG_SAMPLE_TRACE_CUSTOM_EVENTS) += trace_custom_sched.o

0 commit comments

Comments
 (0)