Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/include/trace/trace_custom_events.h
26285 views
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_struct_define.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_data_offsets.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_trace_output.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_event_fields.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_get_offsets.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_event_callback.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_class_define.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)
222
223