Commit | Line | Data |
---|---|---|
40652b65 | 1 | #include <lttng.h> |
299338c8 | 2 | #include <lttng-types.h> |
d0dd2ecb | 3 | #include <linux/debugfs.h> |
b13f3ebe | 4 | #include "../wrapper/vmalloc.h" /* for wrapper_vmalloc_sync_all() */ |
f3bc08c5 | 5 | #include "../wrapper/ringbuffer/frontend_types.h" |
e763dbf5 | 6 | #include "../ltt-events.h" |
6db3d13b | 7 | #include "../ltt-tracer-core.h" |
40652b65 | 8 | |
299338c8 MD |
9 | struct lttng_event_field { |
10 | const char *name; | |
11 | const struct lttng_type type; | |
12 | }; | |
13 | ||
14 | struct lttng_event_desc { | |
15 | const struct lttng_event_field *fields; | |
d0dd2ecb | 16 | const char *name; |
19c57fbf | 17 | void *probe_callback; |
d0dd2ecb | 18 | unsigned int nr_fields; |
299338c8 | 19 | }; |
40652b65 MD |
20 | |
21 | /* | |
6db3d13b | 22 | * Macro declarations used for all stages. |
40652b65 MD |
23 | */ |
24 | ||
25 | /* | |
26 | * DECLARE_EVENT_CLASS can be used to add a generic function | |
27 | * handlers for events. That is, if all events have the same | |
28 | * parameters and just have distinct trace points. | |
29 | * Each tracepoint can be defined with DEFINE_EVENT and that | |
30 | * will map the DECLARE_EVENT_CLASS to the tracepoint. | |
31 | * | |
32 | * TRACE_EVENT is a one to one mapping between tracepoint and template. | |
33 | */ | |
6db3d13b | 34 | |
40652b65 MD |
35 | #undef TRACE_EVENT |
36 | #define TRACE_EVENT(name, proto, args, tstruct, assign, print) \ | |
37 | DECLARE_EVENT_CLASS(name, \ | |
38 | PARAMS(proto), \ | |
39 | PARAMS(args), \ | |
40 | PARAMS(tstruct), \ | |
41 | PARAMS(assign), \ | |
299338c8 MD |
42 | PARAMS(print)) \ |
43 | DEFINE_EVENT(name, name, PARAMS(proto), PARAMS(args)) | |
40652b65 | 44 | |
6db3d13b MD |
45 | #undef DEFINE_EVENT_PRINT |
46 | #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ | |
47 | DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args)) | |
48 | ||
49 | /* Callbacks are meaningless to LTTng. */ | |
50 | #undef TRACE_EVENT_FN | |
51 | #define TRACE_EVENT_FN(name, proto, args, tstruct, \ | |
52 | assign, print, reg, unreg) \ | |
53 | TRACE_EVENT(name, PARAMS(proto), PARAMS(args), \ | |
54 | PARAMS(tstruct), PARAMS(assign), PARAMS(print)) \ | |
55 | ||
f62b389e MD |
56 | /* |
57 | * Stage 0.1 of the trace events. | |
58 | * | |
59 | * Create dummy trace calls for each events, verifying that the LTTng module | |
60 | * TRACE_EVENT headers match the kernel arguments. Will be optimized out by the | |
61 | * compiler. | |
62 | */ | |
63 | ||
64 | #include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ | |
65 | ||
66 | #undef TP_PROTO | |
67 | #define TP_PROTO(args...) args | |
68 | ||
69 | #undef TP_ARGS | |
70 | #define TP_ARGS(args...) args | |
71 | ||
72 | #undef DEFINE_EVENT | |
73 | #define DEFINE_EVENT(_template, _name, _proto, _args) \ | |
7eb827f2 | 74 | void trace_##_name(_proto); |
f62b389e MD |
75 | |
76 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | |
77 | ||
6db3d13b MD |
78 | /* |
79 | * Stage 1 of the trace events. | |
80 | * | |
81 | * Create event field type metadata section. | |
82 | * Each event produce an array of fields. | |
83 | */ | |
84 | ||
85 | #include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ | |
86 | ||
1d12cebd MD |
87 | /* Named field types must be defined in lttng-types.h */ |
88 | ||
40652b65 | 89 | #undef __field |
299338c8 MD |
90 | #define __field(_type, _item) \ |
91 | { .name = #_item, .type = { .atype = atype_integer, .name = #_type} }, | |
40652b65 MD |
92 | |
93 | #undef __field_ext | |
6db3d13b | 94 | #define __field_ext(_type, _item, _filter_type) __field(_type, _item) |
40652b65 MD |
95 | |
96 | #undef __array | |
299338c8 MD |
97 | #define __array(_type, _item, _length) \ |
98 | { \ | |
99 | .name = #_item, \ | |
100 | .type = { \ | |
101 | .atype = atype_array, \ | |
102 | .name = NULL, \ | |
103 | .u.array.elem_type = #_type, \ | |
104 | .u.array.length = _length, \ | |
105 | }, \ | |
106 | }, | |
40652b65 MD |
107 | |
108 | #undef __dynamic_array | |
299338c8 MD |
109 | #define __dynamic_array(_type, _item, _length) \ |
110 | { \ | |
111 | .name = #_item, \ | |
112 | .type = { \ | |
113 | .atype = atype_sequence, \ | |
114 | .name = NULL, \ | |
115 | .u.sequence.elem_type = #_type, \ | |
116 | .u.sequence.length_type = "u32", \ | |
117 | }, \ | |
118 | }, | |
40652b65 MD |
119 | |
120 | #undef __string | |
1d12cebd | 121 | #define __string(_item, _src) \ |
299338c8 | 122 | { \ |
0d1d4002 | 123 | .name = #_item, \ |
299338c8 MD |
124 | .type = { \ |
125 | .atype = atype_string, \ | |
126 | .name = NULL, \ | |
127 | .u.string.encoding = lttng_encode_UTF8, \ | |
128 | }, \ | |
129 | }, | |
1d12cebd | 130 | |
40652b65 | 131 | #undef TP_STRUCT__entry |
1d12cebd MD |
132 | #define TP_STRUCT__entry(args...) args /* Only one used in this phase */ |
133 | ||
40652b65 | 134 | #undef DECLARE_EVENT_CLASS |
0d1d4002 MD |
135 | #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ |
136 | static const struct lttng_event_field __event_fields___##_name[] = { \ | |
137 | _tstruct \ | |
299338c8 MD |
138 | }; |
139 | ||
299338c8 MD |
140 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) |
141 | ||
19c57fbf MD |
142 | /* |
143 | * Stage 1.1 of the trace events. | |
144 | * | |
145 | * Create probe callback prototypes. | |
146 | */ | |
147 | ||
148 | #include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ | |
149 | ||
150 | #undef TP_PROTO | |
151 | #define TP_PROTO(args...) args | |
152 | ||
153 | #undef DECLARE_EVENT_CLASS | |
154 | #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ | |
155 | static void __event_probe__##_name(void *__data, _proto); | |
156 | ||
157 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | |
158 | ||
299338c8 MD |
159 | /* |
160 | * Stage 2 of the trace events. | |
161 | * | |
162 | * Create an array of events. | |
163 | */ | |
164 | ||
299338c8 MD |
165 | /* Named field types must be defined in lttng-types.h */ |
166 | ||
6db3d13b | 167 | #include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ |
299338c8 | 168 | |
d32a57a2 MD |
169 | #undef DEFINE_EVENT |
170 | #define DEFINE_EVENT(_template, _name, _proto, _args) \ | |
171 | { \ | |
172 | .fields = __event_fields___##_template, \ | |
173 | .name = #_name, \ | |
19c57fbf | 174 | .probe_callback = (void *) &__event_probe__##_template,\ |
d32a57a2 | 175 | .nr_fields = ARRAY_SIZE(__event_fields___##_template), \ |
6db3d13b | 176 | }, |
40652b65 | 177 | |
d0dd2ecb MD |
178 | #define TP_ID1(_token, _system) _token##_system |
179 | #define TP_ID(_token, _system) TP_ID1(_token, _system) | |
40652b65 | 180 | |
d0dd2ecb | 181 | static const struct lttng_event_desc TP_ID(__event_desc___, TRACE_SYSTEM)[] = { |
40652b65 | 182 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) |
299338c8 MD |
183 | }; |
184 | ||
d0dd2ecb MD |
185 | #undef TP_ID1 |
186 | #undef TP_ID | |
187 | ||
188 | /* | |
189 | * Stage 3 of the trace events. | |
190 | * | |
191 | * Create seq file metadata output. | |
192 | */ | |
193 | ||
d0dd2ecb MD |
194 | #define TP_ID1(_token, _system) _token##_system |
195 | #define TP_ID(_token, _system) TP_ID1(_token, _system) | |
d0dd2ecb MD |
196 | |
197 | static void *TP_ID(__lttng_seq_start__, TRACE_SYSTEM)(struct seq_file *m, | |
198 | loff_t *pos) | |
199 | { | |
6db3d13b MD |
200 | const struct lttng_event_desc *desc = |
201 | &TP_ID(__event_desc___, TRACE_SYSTEM)[*pos]; | |
d0dd2ecb | 202 | |
6db3d13b MD |
203 | if (desc > &TP_ID(__event_desc___, TRACE_SYSTEM) |
204 | [ARRAY_SIZE(TP_ID(__event_desc___, TRACE_SYSTEM)) - 1]) | |
d0dd2ecb MD |
205 | return NULL; |
206 | return (void *) desc; | |
207 | } | |
208 | ||
209 | static void *TP_ID(__lttng_seq_next__, TRACE_SYSTEM)(struct seq_file *m, | |
210 | void *p, loff_t *ppos) | |
211 | { | |
6db3d13b MD |
212 | const struct lttng_event_desc *desc = |
213 | &TP_ID(__event_desc___, TRACE_SYSTEM)[++(*ppos)]; | |
d0dd2ecb | 214 | |
6db3d13b MD |
215 | if (desc > &TP_ID(__event_desc___, TRACE_SYSTEM) |
216 | [ARRAY_SIZE(TP_ID(__event_desc___, TRACE_SYSTEM)) - 1]) | |
d0dd2ecb MD |
217 | return NULL; |
218 | return (void *) desc; | |
219 | } | |
220 | ||
221 | static void TP_ID(__lttng_seq_stop__, TRACE_SYSTEM)(struct seq_file *m, | |
222 | void *p) | |
223 | { | |
224 | } | |
225 | ||
226 | static int TP_ID(__lttng_seq_show__, TRACE_SYSTEM)(struct seq_file *m, | |
227 | void *p) | |
228 | { | |
229 | const struct lttng_event_desc *desc = p; | |
230 | int i; | |
231 | ||
232 | seq_printf(m, "event {\n" | |
233 | "\tname = %s;\n" | |
234 | "\tid = UNKNOWN;\n" | |
235 | "\tstream = UNKNOWN;\n" | |
236 | "\tfields = {\n", | |
237 | desc->name); | |
238 | for (i = 0; i < desc->nr_fields; i++) { | |
239 | if (desc->fields[i].type.name) /* Named type */ | |
240 | seq_printf(m, "\t\t%s", | |
241 | desc->fields[i].type.name); | |
242 | else /* Nameless type */ | |
243 | lttng_print_event_type(m, 2, &desc->fields[i].type); | |
244 | seq_printf(m, " %s;\n", desc->fields[i].name); | |
245 | } | |
246 | seq_printf(m, "\t};\n"); | |
247 | seq_printf(m, "};\n"); | |
248 | return 0; | |
249 | } | |
250 | ||
251 | static const | |
252 | struct seq_operations TP_ID(__lttng_types_seq_ops__, TRACE_SYSTEM) = { | |
253 | .start = TP_ID(__lttng_seq_start__, TRACE_SYSTEM), | |
254 | .next = TP_ID(__lttng_seq_next__, TRACE_SYSTEM), | |
255 | .stop = TP_ID(__lttng_seq_stop__, TRACE_SYSTEM), | |
256 | .show = TP_ID(__lttng_seq_show__, TRACE_SYSTEM), | |
257 | }; | |
258 | ||
259 | static int | |
260 | TP_ID(__lttng_types_open__, TRACE_SYSTEM)(struct inode *inode, struct file *file) | |
261 | { | |
262 | return seq_open(file, &TP_ID(__lttng_types_seq_ops__, TRACE_SYSTEM)); | |
263 | } | |
264 | ||
6db3d13b MD |
265 | static const |
266 | struct file_operations TP_ID(__lttng_types_fops__, TRACE_SYSTEM) = { | |
d0dd2ecb MD |
267 | .open = TP_ID(__lttng_types_open__, TRACE_SYSTEM), |
268 | .read = seq_read, | |
269 | .llseek = seq_lseek, | |
270 | .release = seq_release_private, | |
271 | }; | |
272 | ||
273 | static struct dentry *TP_ID(__lttng_types_dentry__, TRACE_SYSTEM); | |
274 | ||
275 | static int TP_ID(__lttng_types_init__, TRACE_SYSTEM)(void) | |
276 | { | |
277 | int ret = 0; | |
278 | ||
279 | TP_ID(__lttng_types_dentry__, TRACE_SYSTEM) = | |
6db3d13b MD |
280 | debugfs_create_file("lttng-events-" __stringify(TRACE_SYSTEM), |
281 | S_IWUSR, NULL, NULL, | |
282 | &TP_ID(__lttng_types_fops__, TRACE_SYSTEM)); | |
d0dd2ecb MD |
283 | if (IS_ERR(TP_ID(__lttng_types_dentry__, TRACE_SYSTEM)) |
284 | || !TP_ID(__lttng_types_dentry__, TRACE_SYSTEM)) { | |
285 | printk(KERN_ERR "Error creating LTTng type export file\n"); | |
286 | ret = -ENOMEM; | |
287 | goto error; | |
288 | } | |
289 | error: | |
290 | return ret; | |
291 | } | |
292 | ||
d0dd2ecb MD |
293 | static void TP_ID(__lttng_types_exit__, TRACE_SYSTEM)(void) |
294 | { | |
295 | debugfs_remove(TP_ID(__lttng_types_dentry__, TRACE_SYSTEM)); | |
296 | } | |
297 | ||
d0dd2ecb MD |
298 | #undef TP_ID1 |
299 | #undef TP_ID | |
300 | ||
40652b65 | 301 | /* |
6db3d13b | 302 | * Stage 4 of the trace events. |
40652b65 MD |
303 | * |
304 | * Create static inline function that calculates event size. | |
305 | */ | |
306 | ||
6db3d13b | 307 | #include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ |
40652b65 | 308 | |
6db3d13b MD |
309 | /* Named field types must be defined in lttng-types.h */ |
310 | ||
311 | #undef __field | |
85a80742 MD |
312 | #define __field(_type, _item) \ |
313 | __event_len += lib_ring_buffer_align(__event_len, __alignof__(_type)); \ | |
0d1d4002 | 314 | __event_len += sizeof(_type); |
6db3d13b MD |
315 | |
316 | #undef __field_ext | |
317 | #define __field_ext(_type, _item, _filter_type) __field(_type, _item) | |
318 | ||
319 | #undef __array | |
85a80742 MD |
320 | #define __array(_type, _item, _length) \ |
321 | __event_len += lib_ring_buffer_align(__event_len, __alignof__(_type)); \ | |
0d1d4002 | 322 | __event_len += sizeof(_type) * (_length); |
6db3d13b MD |
323 | |
324 | #undef __dynamic_array | |
85a80742 MD |
325 | #define __dynamic_array(_type, _item, _length) \ |
326 | __event_len += lib_ring_buffer_align(__event_len, __alignof__(u32)); \ | |
327 | __event_len += sizeof(u32); \ | |
328 | __event_len += lib_ring_buffer_align(__event_len, __alignof__(_type)); \ | |
0d1d4002 | 329 | __event_len += sizeof(_type) * (_length); |
6db3d13b MD |
330 | |
331 | #undef __string | |
85a80742 | 332 | #define __string(_item, _src) \ |
0d1d4002 MD |
333 | __event_len += __dynamic_len[__dynamic_len_idx++] = strlen(_src) + 1; |
334 | ||
335 | #undef TP_PROTO | |
336 | #define TP_PROTO(args...) args | |
6db3d13b MD |
337 | |
338 | #undef TP_STRUCT__entry | |
0d1d4002 | 339 | #define TP_STRUCT__entry(args...) args |
6db3d13b MD |
340 | |
341 | #undef DECLARE_EVENT_CLASS | |
0d1d4002 MD |
342 | #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ |
343 | static inline size_t __event_get_size__##_name(size_t *__dynamic_len, _proto) \ | |
344 | { \ | |
345 | size_t __event_len = 0; \ | |
346 | unsigned int __dynamic_len_idx = 0; \ | |
347 | \ | |
348 | if (0) \ | |
349 | (void) __dynamic_len_idx; /* don't warn if unused */ \ | |
350 | _tstruct \ | |
351 | return __event_len; \ | |
6db3d13b | 352 | } |
40652b65 MD |
353 | |
354 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | |
355 | ||
6db3d13b | 356 | |
6db3d13b | 357 | |
40652b65 | 358 | /* |
e763dbf5 MD |
359 | * Stage 5 of the trace events. |
360 | * | |
361 | * Create static inline function that calculates event payload alignment. | |
362 | */ | |
363 | ||
364 | #include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ | |
365 | ||
366 | /* Named field types must be defined in lttng-types.h */ | |
367 | ||
368 | #undef __field | |
369 | #define __field(_type, _item) \ | |
67e5e60c | 370 | __event_align = max_t(size_t, __event_align, __alignof__(_type)); |
e763dbf5 MD |
371 | |
372 | #undef __field_ext | |
373 | #define __field_ext(_type, _item, _filter_type) __field(_type, _item) | |
374 | ||
375 | #undef __array | |
376 | #define __array(_type, _item, _length) \ | |
67e5e60c | 377 | __event_align = max_t(size_t, __event_align, __alignof__(_type)); |
e763dbf5 MD |
378 | |
379 | #undef __dynamic_array | |
380 | #define __dynamic_array(_type, _item, _length) \ | |
67e5e60c MD |
381 | __event_align = max_t(size_t, __event_align, __alignof__(u32)); \ |
382 | __event_align = max_t(size_t, __event_align, __alignof__(_type)); | |
e763dbf5 MD |
383 | |
384 | #undef __string | |
385 | #define __string(_item, _src) | |
386 | ||
387 | #undef TP_PROTO | |
388 | #define TP_PROTO(args...) args | |
389 | ||
390 | #undef TP_STRUCT__entry | |
391 | #define TP_STRUCT__entry(args...) args | |
392 | ||
393 | #undef DECLARE_EVENT_CLASS | |
394 | #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ | |
395 | static inline size_t __event_get_align__##_name(_proto) \ | |
396 | { \ | |
397 | size_t __event_align = 1; \ | |
398 | _tstruct \ | |
399 | return __event_align; \ | |
400 | } | |
401 | ||
402 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | |
403 | ||
404 | ||
e763dbf5 MD |
405 | /* |
406 | * Stage 6 of the trace events. | |
40652b65 | 407 | * |
3c4ffab9 MD |
408 | * Create structure declaration that allows the "assign" macros to access the |
409 | * field types. | |
410 | */ | |
411 | ||
412 | #include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ | |
413 | ||
414 | /* Named field types must be defined in lttng-types.h */ | |
415 | ||
416 | #undef __field | |
417 | #define __field(_type, _item) _type _item; | |
418 | ||
419 | #undef __field_ext | |
420 | #define __field_ext(_type, _item, _filter_type) __field(_type, _item) | |
421 | ||
422 | #undef __array | |
423 | #define __array(_type, _item, _length) _type _item; | |
424 | ||
425 | #undef __dynamic_array | |
426 | #define __dynamic_array(_type, _item, _length) _type _item; | |
427 | ||
428 | #undef __string | |
429 | #define __string(_item, _src) char _item; | |
430 | ||
431 | #undef TP_STRUCT__entry | |
432 | #define TP_STRUCT__entry(args...) args | |
433 | ||
434 | #undef DECLARE_EVENT_CLASS | |
435 | #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ | |
436 | struct __event_typemap__##_name { \ | |
437 | _tstruct \ | |
438 | }; | |
439 | ||
440 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | |
441 | ||
442 | ||
443 | /* | |
444 | * Stage 7 of the trace events. | |
445 | * | |
40652b65 MD |
446 | * Create the probe function : call even size calculation and write event data |
447 | * into the buffer. | |
e763dbf5 | 448 | * |
67e5e60c MD |
449 | * We use both the field and assignment macros to write the fields in the order |
450 | * defined in the field declaration. The field declarations control the | |
451 | * execution order, jumping to the appropriate assignment block. | |
40652b65 MD |
452 | */ |
453 | ||
e763dbf5 MD |
454 | #include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ |
455 | ||
456 | #undef __field | |
457 | #define __field(_type, _item) \ | |
e763dbf5 MD |
458 | goto __assign_##_item; \ |
459 | __end_field_##_item: | |
40652b65 | 460 | |
e763dbf5 MD |
461 | #undef __field_ext |
462 | #define __field_ext(_type, _item, _filter_type) __field(_type, _item) | |
40652b65 | 463 | |
e763dbf5 MD |
464 | #undef __array |
465 | #define __array(_type, _item, _length) \ | |
e763dbf5 MD |
466 | goto __assign_##_item; \ |
467 | __end_field_##_item: | |
40652b65 | 468 | |
e763dbf5 MD |
469 | #undef __dynamic_array |
470 | #define __dynamic_array(_type, _item, _length) \ | |
e763dbf5 MD |
471 | goto __assign_##_item##_1; \ |
472 | __end_field_##_item##_1: \ | |
e763dbf5 MD |
473 | goto __assign_##_item##_2; \ |
474 | __end_field_##_item##_2: | |
40652b65 | 475 | |
e763dbf5 MD |
476 | #undef __string |
477 | #define __string(_item, _src) \ | |
478 | goto __assign_##_item; \ | |
479 | __end_field_##_item: | |
480 | ||
481 | /* | |
482 | * Macros mapping tp_assign() to "=", tp_memcpy() to memcpy() and tp_strcpy() to | |
483 | * strcpy(). | |
484 | */ | |
485 | #undef tp_assign | |
486 | #define tp_assign(dest, src) \ | |
487 | __assign_##dest: \ | |
488 | { \ | |
3c4ffab9 MD |
489 | __typeof__(__typemap.dest) __tmp = (src); \ |
490 | lib_ring_buffer_align_ctx(&ctx, __alignof__(__tmp)); \ | |
491 | __chan->ops->event_write(&ctx, &__tmp, sizeof(__tmp)); \ | |
e763dbf5 MD |
492 | } \ |
493 | goto __end_field_##dest; | |
494 | ||
495 | #undef tp_memcpy | |
496 | #define tp_memcpy(dest, src, len) \ | |
497 | __assign_##dest: \ | |
3c4ffab9 | 498 | lib_ring_buffer_align_ctx(&ctx, __alignof__(__typemap.dest)); \ |
e763dbf5 MD |
499 | __chan->ops->event_write(&ctx, src, len); \ |
500 | goto __end_field_##dest; | |
501 | ||
502 | #undef tp_memcpy_dyn | |
503 | #define tp_memcpy_dyn(dest, src, len) \ | |
504 | __assign_##dest##_1: \ | |
505 | { \ | |
3c4ffab9 MD |
506 | u32 __tmpl = (len); \ |
507 | lib_ring_buffer_align_ctx(&ctx, __alignof__(u32)); \ | |
e763dbf5 MD |
508 | __chan->ops->event_write(&ctx, &__tmpl, sizeof(u32)); \ |
509 | } \ | |
510 | goto __end_field_##dest##_1; \ | |
511 | __assign_##dest##_2: \ | |
3c4ffab9 | 512 | lib_ring_buffer_align_ctx(&ctx, __alignof__(__typemap.dest)); \ |
e763dbf5 MD |
513 | __chan->ops->event_write(&ctx, src, len); \ |
514 | goto __end_field_##dest##_2; | |
515 | ||
516 | #undef tp_strcpy | |
517 | #define tp_strcpy(dest, src) \ | |
3c4ffab9 | 518 | tp_memcpy(dest, src, __get_dynamic_array_len(dest)) |
40652b65 | 519 | |
e763dbf5 MD |
520 | /* Named field types must be defined in lttng-types.h */ |
521 | ||
522 | #undef __get_str | |
523 | #define __get_str(field) field | |
524 | ||
525 | #undef __get_dynamic_array | |
526 | #define __get_dynamic_array(field) field | |
527 | ||
528 | /* Beware: this get len actually consumes the len value */ | |
529 | #undef __get_dynamic_array_len | |
530 | #define __get_dynamic_array_len(field) __dynamic_len[__dynamic_len_idx++] | |
531 | ||
532 | #undef TP_PROTO | |
533 | #define TP_PROTO(args...) args | |
534 | ||
535 | #undef TP_ARGS | |
536 | #define TP_ARGS(args...) args | |
537 | ||
538 | #undef TP_STRUCT__entry | |
539 | #define TP_STRUCT__entry(args...) args | |
540 | ||
541 | #undef TP_fast_assign | |
542 | #define TP_fast_assign(args...) args | |
543 | ||
544 | #undef DECLARE_EVENT_CLASS | |
545 | #define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \ | |
546 | static void __event_probe__##_name(void *__data, _proto) \ | |
547 | { \ | |
548 | struct ltt_event *__event = __data; \ | |
549 | struct ltt_channel *__chan = __event->chan; \ | |
550 | struct lib_ring_buffer_ctx ctx; \ | |
551 | size_t __event_len, __event_align; \ | |
552 | size_t __dynamic_len_idx = 0; \ | |
553 | size_t __dynamic_len[ARRAY_SIZE(__event_fields___##_name)]; \ | |
3c4ffab9 | 554 | struct __event_typemap__##_name __typemap; \ |
e763dbf5 MD |
555 | int __ret; \ |
556 | \ | |
557 | if (0) \ | |
558 | (void) __dynamic_len_idx; /* don't warn if unused */ \ | |
52fc2e1f MD |
559 | if (!ACCESS_ONCE(__chan->session->active)) \ |
560 | return; \ | |
e763dbf5 MD |
561 | __event_len = __event_get_size__##_name(__dynamic_len, _args); \ |
562 | __event_align = __event_get_align__##_name(_args); \ | |
563 | lib_ring_buffer_ctx_init(&ctx, __chan->chan, NULL, __event_len, \ | |
564 | __event_align, -1); \ | |
565 | __ret = __chan->ops->event_reserve(&ctx); \ | |
566 | if (__ret < 0) \ | |
567 | return; \ | |
568 | /* Control code (field ordering) */ \ | |
569 | _tstruct \ | |
570 | __chan->ops->event_commit(&ctx); \ | |
571 | return; \ | |
572 | /* Copy code, steered by control code */ \ | |
573 | _assign \ | |
574 | } | |
575 | ||
576 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | |
577 | ||
3afe7aac MD |
578 | /* |
579 | * Stage 8 of the trace events. | |
580 | * | |
581 | * Register/unregister probes at module load/unload. | |
582 | */ | |
583 | ||
584 | #include "lttng-events-reset.h" /* Reset all macros within TRACE_EVENT */ | |
585 | ||
586 | #define TP_ID1(_token, _system) _token##_system | |
587 | #define TP_ID(_token, _system) TP_ID1(_token, _system) | |
588 | #define module_init_eval1(_token, _system) module_init(_token##_system) | |
589 | #define module_init_eval(_token, _system) module_init_eval1(_token, _system) | |
590 | #define module_exit_eval1(_token, _system) module_exit(_token##_system) | |
591 | #define module_exit_eval(_token, _system) module_exit_eval1(_token, _system) | |
592 | ||
3afe7aac MD |
593 | static int TP_ID(__lttng_events_init__, TRACE_SYSTEM)(void) |
594 | { | |
19c57fbf MD |
595 | int ret; |
596 | int i; | |
3afe7aac | 597 | |
6d2a620c | 598 | wrapper_vmalloc_sync_all(); |
3afe7aac MD |
599 | ret = TP_ID(__lttng_types_init__, TRACE_SYSTEM)(); |
600 | if (ret) | |
601 | return ret; | |
19c57fbf MD |
602 | for (i = 0; i < ARRAY_SIZE(TP_ID(__event_desc___, TRACE_SYSTEM)); i++) { |
603 | const struct lttng_event_desc *event_desc; | |
604 | ||
605 | event_desc = &TP_ID(__event_desc___, TRACE_SYSTEM)[i]; | |
606 | ret = ltt_probe_register(event_desc->name, | |
607 | event_desc->probe_callback); | |
608 | if (ret) | |
609 | goto error; | |
610 | } | |
611 | return 0; | |
612 | ||
613 | error: | |
614 | for (i--; i >= 0; i--) { | |
615 | const struct lttng_event_desc *event_desc; | |
616 | ||
617 | event_desc = &TP_ID(__event_desc___, TRACE_SYSTEM)[i]; | |
618 | ltt_probe_unregister(event_desc->name); | |
619 | } | |
3afe7aac MD |
620 | return ret; |
621 | } | |
622 | ||
623 | module_init_eval(__lttng_events_init__, TRACE_SYSTEM); | |
624 | ||
3afe7aac MD |
625 | static void TP_ID(__lttng_events_exit__, TRACE_SYSTEM)(void) |
626 | { | |
19c57fbf MD |
627 | int i; |
628 | ||
629 | for (i = 0; i < ARRAY_SIZE(TP_ID(__event_desc___, TRACE_SYSTEM)); i++) { | |
630 | const struct lttng_event_desc *event_desc; | |
631 | ||
632 | event_desc = &TP_ID(__event_desc___, TRACE_SYSTEM)[i]; | |
633 | ltt_probe_unregister(event_desc->name); | |
634 | } | |
3afe7aac MD |
635 | TP_ID(__lttng_types_exit__, TRACE_SYSTEM)(); |
636 | } | |
637 | ||
638 | module_exit_eval(__lttng_events_exit__, TRACE_SYSTEM); | |
639 | ||
640 | #undef module_init_eval | |
641 | #undef module_exit_eval | |
642 | #undef TP_ID1 | |
643 | #undef TP_ID |