Add CTF enum type support to tracepoint event
[lttng-ust.git] / include / lttng / ust-tracepoint-event.h
1 /*
2 * Copyright (c) 2011-2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <urcu/compiler.h>
26 #include <urcu/rculist.h>
27 #include <lttng/ust-events.h>
28 #include <lttng/ringbuffer-config.h>
29 #include <lttng/ust-compiler.h>
30 #include <lttng/tracepoint.h>
31 #include <string.h>
32
33 #undef tp_list_for_each_entry_rcu
34 #define tp_list_for_each_entry_rcu(pos, head, member) \
35 for (pos = cds_list_entry(tp_rcu_dereference_bp((head)->next), __typeof__(*pos), member); \
36 &pos->member != (head); \
37 pos = cds_list_entry(tp_rcu_dereference_bp(pos->member.next), __typeof__(*pos), member))
38
39 /*
40 * TRACEPOINT_EVENT_CLASS declares a class of tracepoints receiving the
41 * same arguments and having the same field layout.
42 *
43 * TRACEPOINT_EVENT_INSTANCE declares an instance of a tracepoint, with
44 * its own provider and name. It refers to a class (template).
45 *
46 * TRACEPOINT_EVENT declared both a class and an instance and does a
47 * direct mapping from the instance to the class.
48 */
49
50 #undef TRACEPOINT_EVENT
51 #define TRACEPOINT_EVENT(_provider, _name, _args, _fields) \
52 TRACEPOINT_EVENT_CLASS(_provider, _name, \
53 _TP_PARAMS(_args), \
54 _TP_PARAMS(_fields)) \
55 TRACEPOINT_EVENT_INSTANCE(_provider, _name, _name, \
56 _TP_PARAMS(_args))
57
58 /* Helpers */
59 #define _TP_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
60
61 #define _tp_max_t(type, x, y) \
62 ({ \
63 type __max1 = (x); \
64 type __max2 = (y); \
65 __max1 > __max2 ? __max1: __max2; \
66 })
67
68 /*
69 * Stage 0 of tracepoint event generation.
70 *
71 * Check that each TRACEPOINT_EVENT provider argument match the
72 * TRACEPOINT_PROVIDER by creating dummy callbacks.
73 */
74
75 /* Reset all macros within TRACEPOINT_EVENT */
76 #include <lttng/ust-tracepoint-event-reset.h>
77
78 static inline lttng_ust_notrace
79 void _TP_COMBINE_TOKENS(__tracepoint_provider_mismatch_, TRACEPOINT_PROVIDER)(void);
80 static inline
81 void _TP_COMBINE_TOKENS(__tracepoint_provider_mismatch_, TRACEPOINT_PROVIDER)(void)
82 {
83 }
84
85 #undef TRACEPOINT_EVENT_CLASS
86 #define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \
87 __tracepoint_provider_mismatch_##_provider();
88
89 #undef TRACEPOINT_EVENT_INSTANCE
90 #define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \
91 __tracepoint_provider_mismatch_##_provider();
92
93 static inline lttng_ust_notrace
94 void _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(void);
95 static inline
96 void _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(void)
97 {
98 #include TRACEPOINT_INCLUDE
99 }
100
101 /*
102 * Stage 0.1 of tracepoint event generation.
103 *
104 * Check that each TRACEPOINT_EVENT provider:name does not exceed the
105 * tracepoint name length limit.
106 */
107
108 /* Reset all macros within TRACEPOINT_EVENT */
109 #include <lttng/ust-tracepoint-event-reset.h>
110
111 #undef TRACEPOINT_EVENT_INSTANCE
112 #define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \
113 static const char \
114 __tp_name_len_check##_provider##___##_name[LTTNG_UST_SYM_NAME_LEN] \
115 __attribute__((unused)) = \
116 #_provider ":" #_name;
117
118 #include TRACEPOINT_INCLUDE
119
120 /*
121 * Stage 0.9 of tracepoint event generation
122 *
123 * Unfolding the enums
124 */
125 #include <lttng/ust-tracepoint-event-reset.h>
126
127 /* Enumeration entry (single value) */
128 #undef ctf_enum_value
129 #define ctf_enum_value(_string, _value) \
130 { _value, _value, _string },
131
132 /* Enumeration entry (range) */
133 #undef ctf_enum_range
134 #define ctf_enum_range(_string, _range_start, _range_end) \
135 { _range_start, _range_end, _string },
136
137 #undef TP_ENUM_VALUES
138 #define TP_ENUM_VALUES(...) \
139 __VA_ARGS__
140
141 #undef TRACEPOINT_ENUM
142 #define TRACEPOINT_ENUM(_provider, _name, _values) \
143 const struct lttng_enum_entry __enum_values__##_provider##_##_name[] = { \
144 _values \
145 };
146
147 #include TRACEPOINT_INCLUDE
148
149 /*
150 * Stage 1 of tracepoint event generation.
151 *
152 * Create event field type metadata section.
153 * Each event produce an array of fields.
154 */
155
156 /* Reset all macros within TRACEPOINT_EVENT */
157 #include <lttng/ust-tracepoint-event-reset.h>
158 #include <lttng/ust-tracepoint-event-write.h>
159 #include <lttng/ust-tracepoint-event-nowrite.h>
160
161 #undef _ctf_integer_ext
162 #define _ctf_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \
163 { \
164 .name = #_item, \
165 .type = __type_integer(_type, _byte_order, _base, none),\
166 .nowrite = _nowrite, \
167 },
168
169 #undef _ctf_float
170 #define _ctf_float(_type, _item, _src, _nowrite) \
171 { \
172 .name = #_item, \
173 .type = __type_float(_type), \
174 .nowrite = _nowrite, \
175 },
176
177 #undef _ctf_array_encoded
178 #define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \
179 { \
180 .name = #_item, \
181 .type = \
182 { \
183 .atype = atype_array, \
184 .u = \
185 { \
186 .array = \
187 { \
188 .elem_type = __type_integer(_type, BYTE_ORDER, 10, _encoding), \
189 .length = _length, \
190 } \
191 } \
192 }, \
193 .nowrite = _nowrite, \
194 },
195
196 #undef _ctf_sequence_encoded
197 #define _ctf_sequence_encoded(_type, _item, _src, \
198 _length_type, _src_length, _encoding, _nowrite, \
199 _elem_type_base) \
200 { \
201 .name = #_item, \
202 .type = \
203 { \
204 .atype = atype_sequence, \
205 .u = \
206 { \
207 .sequence = \
208 { \
209 .length_type = __type_integer(_length_type, BYTE_ORDER, 10, none), \
210 .elem_type = __type_integer(_type, BYTE_ORDER, _elem_type_base, _encoding), \
211 }, \
212 }, \
213 }, \
214 .nowrite = _nowrite, \
215 },
216
217 #undef _ctf_string
218 #define _ctf_string(_item, _src, _nowrite) \
219 { \
220 .name = #_item, \
221 .type = \
222 { \
223 .atype = atype_string, \
224 .u = \
225 { \
226 .basic = { .string = { .encoding = lttng_encode_UTF8 } } \
227 }, \
228 }, \
229 .nowrite = _nowrite, \
230 },
231
232 #undef _ctf_enum
233 #define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \
234 { \
235 .name = #_item, \
236 .type = { \
237 .atype = atype_enum, \
238 .u = { \
239 .basic = { \
240 .enumeration = { \
241 .desc = &__enum_##_provider##_##_name, \
242 .container_type = { \
243 .size = sizeof(_type) * CHAR_BIT, \
244 .alignment = lttng_alignof(_type) * CHAR_BIT, \
245 .signedness = lttng_is_signed_type(_type), \
246 .reverse_byte_order = 0, \
247 .base = 10, \
248 .encoding = lttng_encode_none, \
249 }, \
250 }, \
251 }, \
252 }, \
253 }, \
254 .nowrite = _nowrite, \
255 },
256
257 #undef TP_FIELDS
258 #define TP_FIELDS(...) __VA_ARGS__ /* Only one used in this phase */
259
260 #undef TRACEPOINT_EVENT_CLASS
261 #define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \
262 static const struct lttng_event_field __event_fields___##_provider##___##_name[] = { \
263 _fields \
264 };
265
266 #undef TRACEPOINT_ENUM
267 #define TRACEPOINT_ENUM(_provider, _name, _values) \
268 static const struct lttng_enum_desc __enum_##_provider##_##_name = { \
269 .name = #_provider "_" #_name, \
270 .entries = __enum_values__##_provider##_##_name, \
271 .nr_entries = _TP_ARRAY_SIZE(__enum_values__##_provider##_##_name), \
272 };
273
274 #include TRACEPOINT_INCLUDE
275
276 /*
277 * Stage 2 of tracepoint event generation.
278 *
279 * Create probe callback prototypes.
280 */
281
282 /* Reset all macros within TRACEPOINT_EVENT */
283 #include <lttng/ust-tracepoint-event-reset.h>
284
285 #undef TP_ARGS
286 #define TP_ARGS(...) __VA_ARGS__
287
288 #undef TRACEPOINT_EVENT_CLASS
289 #define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \
290 static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args));
291
292 #include TRACEPOINT_INCLUDE
293
294 /*
295 * Stage 3.0 of tracepoint event generation.
296 *
297 * Create static inline function that calculates event size.
298 */
299
300 /* Reset all macros within TRACEPOINT_EVENT */
301 #include <lttng/ust-tracepoint-event-reset.h>
302 #include <lttng/ust-tracepoint-event-write.h>
303
304 #undef _ctf_integer_ext
305 #define _ctf_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \
306 __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \
307 __event_len += sizeof(_type);
308
309 #undef _ctf_float
310 #define _ctf_float(_type, _item, _src, _nowrite) \
311 __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \
312 __event_len += sizeof(_type);
313
314 #undef _ctf_array_encoded
315 #define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \
316 __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \
317 __event_len += sizeof(_type) * (_length);
318
319 #undef _ctf_sequence_encoded
320 #define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
321 _src_length, _encoding, _nowrite, _elem_type_base) \
322 __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_length_type)); \
323 __event_len += sizeof(_length_type); \
324 __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \
325 __dynamic_len[__dynamic_len_idx] = (_src_length); \
326 __event_len += sizeof(_type) * __dynamic_len[__dynamic_len_idx]; \
327 __dynamic_len_idx++;
328
329 #undef _ctf_string
330 #define _ctf_string(_item, _src, _nowrite) \
331 __event_len += __dynamic_len[__dynamic_len_idx++] = strlen(_src) + 1;
332
333 #undef _ctf_enum
334 #define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \
335 _ctf_integer_ext(_type, _item, _src, BYTE_ORDER, 10, _nowrite)
336
337 #undef TP_ARGS
338 #define TP_ARGS(...) __VA_ARGS__
339
340 #undef TP_FIELDS
341 #define TP_FIELDS(...) __VA_ARGS__
342
343 #undef TRACEPOINT_EVENT_CLASS
344 #define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \
345 static inline lttng_ust_notrace \
346 size_t __event_get_size__##_provider##___##_name(size_t *__dynamic_len, _TP_ARGS_DATA_PROTO(_args)); \
347 static inline \
348 size_t __event_get_size__##_provider##___##_name(size_t *__dynamic_len, _TP_ARGS_DATA_PROTO(_args)) \
349 { \
350 size_t __event_len = 0; \
351 unsigned int __dynamic_len_idx = 0; \
352 \
353 if (0) \
354 (void) __dynamic_len_idx; /* don't warn if unused */ \
355 _fields \
356 return __event_len; \
357 }
358
359 #include TRACEPOINT_INCLUDE
360
361 /*
362 * Stage 3.1 of tracepoint event generation.
363 *
364 * Create static inline function that layout the filter stack data.
365 * We make both write and nowrite data available to the filter.
366 */
367
368 /* Reset all macros within TRACEPOINT_EVENT */
369 #include <lttng/ust-tracepoint-event-reset.h>
370 #include <lttng/ust-tracepoint-event-write.h>
371 #include <lttng/ust-tracepoint-event-nowrite.h>
372
373 #undef _ctf_integer_ext
374 #define _ctf_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \
375 if (lttng_is_signed_type(_type)) { \
376 int64_t __ctf_tmp_int64; \
377 switch (sizeof(_type)) { \
378 case 1: \
379 { \
380 union { _type t; int8_t v; } __tmp = { (_type) (_src) }; \
381 __ctf_tmp_int64 = (int64_t) __tmp.v; \
382 break; \
383 } \
384 case 2: \
385 { \
386 union { _type t; int16_t v; } __tmp = { (_type) (_src) }; \
387 __ctf_tmp_int64 = (int64_t) __tmp.v; \
388 break; \
389 } \
390 case 4: \
391 { \
392 union { _type t; int32_t v; } __tmp = { (_type) (_src) }; \
393 __ctf_tmp_int64 = (int64_t) __tmp.v; \
394 break; \
395 } \
396 case 8: \
397 { \
398 union { _type t; int64_t v; } __tmp = { (_type) (_src) }; \
399 __ctf_tmp_int64 = (int64_t) __tmp.v; \
400 break; \
401 } \
402 default: \
403 abort(); \
404 }; \
405 memcpy(__stack_data, &__ctf_tmp_int64, sizeof(int64_t)); \
406 } else { \
407 uint64_t __ctf_tmp_uint64; \
408 switch (sizeof(_type)) { \
409 case 1: \
410 { \
411 union { _type t; uint8_t v; } __tmp = { (_type) (_src) }; \
412 __ctf_tmp_uint64 = (uint64_t) __tmp.v; \
413 break; \
414 } \
415 case 2: \
416 { \
417 union { _type t; uint16_t v; } __tmp = { (_type) (_src) }; \
418 __ctf_tmp_uint64 = (uint64_t) __tmp.v; \
419 break; \
420 } \
421 case 4: \
422 { \
423 union { _type t; uint32_t v; } __tmp = { (_type) (_src) }; \
424 __ctf_tmp_uint64 = (uint64_t) __tmp.v; \
425 break; \
426 } \
427 case 8: \
428 { \
429 union { _type t; uint64_t v; } __tmp = { (_type) (_src) }; \
430 __ctf_tmp_uint64 = (uint64_t) __tmp.v; \
431 break; \
432 } \
433 default: \
434 abort(); \
435 }; \
436 memcpy(__stack_data, &__ctf_tmp_uint64, sizeof(uint64_t)); \
437 } \
438 __stack_data += sizeof(int64_t);
439
440 #undef _ctf_float
441 #define _ctf_float(_type, _item, _src, _nowrite) \
442 { \
443 double __ctf_tmp_double = (double) (_type) (_src); \
444 memcpy(__stack_data, &__ctf_tmp_double, sizeof(double)); \
445 __stack_data += sizeof(double); \
446 }
447
448 #undef _ctf_array_encoded
449 #define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \
450 { \
451 unsigned long __ctf_tmp_ulong = (unsigned long) (_length); \
452 const void *__ctf_tmp_ptr = (_src); \
453 memcpy(__stack_data, &__ctf_tmp_ulong, sizeof(unsigned long)); \
454 __stack_data += sizeof(unsigned long); \
455 memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \
456 __stack_data += sizeof(void *); \
457 }
458
459 #undef _ctf_sequence_encoded
460 #define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
461 _src_length, _encoding, _nowrite, _elem_type_base) \
462 { \
463 unsigned long __ctf_tmp_ulong = (unsigned long) (_src_length); \
464 const void *__ctf_tmp_ptr = (_src); \
465 memcpy(__stack_data, &__ctf_tmp_ulong, sizeof(unsigned long)); \
466 __stack_data += sizeof(unsigned long); \
467 memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \
468 __stack_data += sizeof(void *); \
469 }
470
471 #undef _ctf_string
472 #define _ctf_string(_item, _src, _nowrite) \
473 { \
474 const void *__ctf_tmp_ptr = (_src); \
475 memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \
476 __stack_data += sizeof(void *); \
477 }
478
479 #undef _ctf_enum
480 #define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \
481 _ctf_integer_ext(_type, _item, _src, BYTE_ORDER, 10, _nowrite)
482
483 #undef TP_ARGS
484 #define TP_ARGS(...) __VA_ARGS__
485
486 #undef TP_FIELDS
487 #define TP_FIELDS(...) __VA_ARGS__
488
489 #undef TRACEPOINT_EVENT_CLASS
490 #define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \
491 static inline \
492 void __event_prepare_filter_stack__##_provider##___##_name(char *__stack_data,\
493 _TP_ARGS_DATA_PROTO(_args)) \
494 { \
495 _fields \
496 }
497
498 #include TRACEPOINT_INCLUDE
499
500 /*
501 * Stage 4 of tracepoint event generation.
502 *
503 * Create static inline function that calculates event payload alignment.
504 */
505
506 /* Reset all macros within TRACEPOINT_EVENT */
507 #include <lttng/ust-tracepoint-event-reset.h>
508 #include <lttng/ust-tracepoint-event-write.h>
509
510 #undef _ctf_integer_ext
511 #define _ctf_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \
512 __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type));
513
514 #undef _ctf_float
515 #define _ctf_float(_type, _item, _src, _nowrite) \
516 __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type));
517
518 #undef _ctf_array_encoded
519 #define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \
520 __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type));
521
522 #undef _ctf_sequence_encoded
523 #define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
524 _src_length, _encoding, _nowrite, _elem_type_base) \
525 __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_length_type)); \
526 __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type));
527
528 #undef _ctf_string
529 #define _ctf_string(_item, _src, _nowrite)
530
531 #undef _ctf_enum
532 #define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \
533 _ctf_integer_ext(_type, _item, _src, BYTE_ORDER, 10, _nowrite)
534
535 #undef TP_ARGS
536 #define TP_ARGS(...) __VA_ARGS__
537
538 #undef TP_FIELDS
539 #define TP_FIELDS(...) __VA_ARGS__
540
541 #undef TRACEPOINT_EVENT_CLASS
542 #define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \
543 static inline lttng_ust_notrace \
544 size_t __event_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args)); \
545 static inline \
546 size_t __event_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args)) \
547 { \
548 size_t __event_align = 1; \
549 _fields \
550 return __event_align; \
551 }
552
553 #include TRACEPOINT_INCLUDE
554
555
556 /*
557 * Stage 5 of tracepoint event generation.
558 *
559 * Create the probe function. This function calls event size calculation
560 * and writes event data into the buffer.
561 */
562
563 /* Reset all macros within TRACEPOINT_EVENT */
564 #include <lttng/ust-tracepoint-event-reset.h>
565 #include <lttng/ust-tracepoint-event-write.h>
566
567 #undef _ctf_integer_ext
568 #define _ctf_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \
569 { \
570 _type __tmp = (_src); \
571 lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(__tmp));\
572 __chan->ops->event_write(&__ctx, &__tmp, sizeof(__tmp));\
573 }
574
575 #undef _ctf_float
576 #define _ctf_float(_type, _item, _src, _nowrite) \
577 { \
578 _type __tmp = (_src); \
579 lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(__tmp));\
580 __chan->ops->event_write(&__ctx, &__tmp, sizeof(__tmp));\
581 }
582
583 #undef _ctf_array_encoded
584 #define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \
585 lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_type)); \
586 __chan->ops->event_write(&__ctx, _src, sizeof(_type) * (_length));
587
588 #undef _ctf_sequence_encoded
589 #define _ctf_sequence_encoded(_type, _item, _src, _length_type, \
590 _src_length, _encoding, _nowrite, _elem_type_base) \
591 { \
592 _length_type __tmpl = __stackvar.__dynamic_len[__dynamic_len_idx]; \
593 lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\
594 __chan->ops->event_write(&__ctx, &__tmpl, sizeof(_length_type));\
595 } \
596 lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_type)); \
597 __chan->ops->event_write(&__ctx, _src, \
598 sizeof(_type) * __get_dynamic_len(dest));
599
600 /*
601 * __chan->ops->u.has_strcpy is a flag letting us know if the LTTng-UST
602 * tracepoint provider ABI implements event_strcpy. This dynamic check
603 * can be removed when the tracepoint provider ABI moves to 2.
604 */
605 #if (LTTNG_UST_PROVIDER_MAJOR > 1)
606 #error "Tracepoint probe provider major version has changed. Please remove dynamic check for has_strcpy."
607 #endif
608
609 #undef _ctf_string
610 #define _ctf_string(_item, _src, _nowrite) \
611 lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(*(_src))); \
612 if (__chan->ops->u.has_strcpy) \
613 __chan->ops->event_strcpy(&__ctx, _src, \
614 __get_dynamic_len(dest)); \
615 else \
616 __chan->ops->event_write(&__ctx, _src, \
617 __get_dynamic_len(dest));
618
619 #undef _ctf_enum
620 #define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \
621 _ctf_integer_ext(_type, _item, _src, BYTE_ORDER, 10, _nowrite)
622
623 /* Beware: this get len actually consumes the len value */
624 #undef __get_dynamic_len
625 #define __get_dynamic_len(field) __stackvar.__dynamic_len[__dynamic_len_idx++]
626
627 #undef TP_ARGS
628 #define TP_ARGS(...) __VA_ARGS__
629
630 #undef TP_FIELDS
631 #define TP_FIELDS(...) __VA_ARGS__
632
633 /*
634 * For state dump, check that "session" argument (mandatory) matches the
635 * session this event belongs to. Ensures that we write state dump data only
636 * into the started session, not into all sessions.
637 */
638 #undef _TP_SESSION_CHECK
639 #ifdef TP_SESSION_CHECK
640 #define _TP_SESSION_CHECK(session, csession) (session == csession)
641 #else /* TP_SESSION_CHECK */
642 #define _TP_SESSION_CHECK(session, csession) 1
643 #endif /* TP_SESSION_CHECK */
644
645 #undef _TP_IP_PARAM
646 #ifdef TP_IP_PARAM
647 #define _TP_IP_PARAM(x) (x)
648 #else /* TP_IP_PARAM */
649 #define _TP_IP_PARAM(x) __builtin_return_address(0)
650 #endif /* TP_IP_PARAM */
651
652 /*
653 * Using twice size for filter stack data to hold size and pointer for
654 * each field (worse case). For integers, max size required is 64-bit.
655 * Same for double-precision floats. Those fit within
656 * 2*sizeof(unsigned long) for all supported architectures.
657 * Perform UNION (||) of filter runtime list.
658 */
659 #undef TRACEPOINT_EVENT_CLASS
660 #define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \
661 static lttng_ust_notrace \
662 void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); \
663 static \
664 void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \
665 { \
666 struct lttng_event *__event = (struct lttng_event *) __tp_data; \
667 struct lttng_channel *__chan = __event->chan; \
668 struct lttng_ust_lib_ring_buffer_ctx __ctx; \
669 size_t __event_len, __event_align; \
670 size_t __dynamic_len_idx = 0; \
671 union { \
672 size_t __dynamic_len[_TP_ARRAY_SIZE(__event_fields___##_provider##___##_name)]; \
673 char __filter_stack_data[2 * sizeof(unsigned long) * _TP_ARRAY_SIZE(__event_fields___##_provider##___##_name)]; \
674 } __stackvar; \
675 int __ret; \
676 \
677 if (0) \
678 (void) __dynamic_len_idx; /* don't warn if unused */ \
679 if (!_TP_SESSION_CHECK(session, __chan->session)) \
680 return; \
681 if (caa_unlikely(!CMM_ACCESS_ONCE(__chan->session->active))) \
682 return; \
683 if (caa_unlikely(!CMM_ACCESS_ONCE(__chan->enabled))) \
684 return; \
685 if (caa_unlikely(!CMM_ACCESS_ONCE(__event->enabled))) \
686 return; \
687 if (caa_unlikely(!TP_RCU_LINK_TEST())) \
688 return; \
689 if (caa_unlikely(!cds_list_empty(&__event->bytecode_runtime_head))) { \
690 struct lttng_bytecode_runtime *bc_runtime; \
691 int __filter_record = __event->has_enablers_without_bytecode; \
692 \
693 __event_prepare_filter_stack__##_provider##___##_name(__stackvar.__filter_stack_data, \
694 _TP_ARGS_DATA_VAR(_args)); \
695 tp_list_for_each_entry_rcu(bc_runtime, &__event->bytecode_runtime_head, node) { \
696 if (caa_unlikely(bc_runtime->filter(bc_runtime, \
697 __stackvar.__filter_stack_data) & LTTNG_FILTER_RECORD_FLAG)) \
698 __filter_record = 1; \
699 } \
700 if (caa_likely(!__filter_record)) \
701 return; \
702 } \
703 __event_len = __event_get_size__##_provider##___##_name(__stackvar.__dynamic_len, \
704 _TP_ARGS_DATA_VAR(_args)); \
705 __event_align = __event_get_align__##_provider##___##_name(_TP_ARGS_VAR(_args)); \
706 lib_ring_buffer_ctx_init(&__ctx, __chan->chan, __event, __event_len, \
707 __event_align, -1, __chan->handle); \
708 __ctx.ip = _TP_IP_PARAM(TP_IP_PARAM); \
709 __ret = __chan->ops->event_reserve(&__ctx, __event->id); \
710 if (__ret < 0) \
711 return; \
712 _fields \
713 __chan->ops->event_commit(&__ctx); \
714 }
715
716 #include TRACEPOINT_INCLUDE
717
718 #undef __get_dynamic_len
719
720 /*
721 * Stage 5.1 of tracepoint event generation.
722 *
723 * Create probe signature
724 */
725
726 /* Reset all macros within TRACEPOINT_EVENT */
727 #include <lttng/ust-tracepoint-event-reset.h>
728
729 #undef TP_ARGS
730 #define TP_ARGS(...) __VA_ARGS__
731
732 #define _TP_EXTRACT_STRING2(...) #__VA_ARGS__
733
734 #undef TRACEPOINT_EVENT_CLASS
735 #define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \
736 const char __tp_event_signature___##_provider##___##_name[] = \
737 _TP_EXTRACT_STRING2(_args);
738
739 #include TRACEPOINT_INCLUDE
740
741 #undef _TP_EXTRACT_STRING2
742
743 /*
744 * Stage 6 of tracepoint event generation.
745 *
746 * Tracepoint loglevel mapping definition generation. We generate a
747 * symbol for each mapping for a provider/event to ensure at most a 1 to
748 * 1 mapping between events and loglevels. If the symbol is repeated,
749 * the compiler will complain.
750 */
751
752 /* Reset all macros within TRACEPOINT_EVENT */
753 #include <lttng/ust-tracepoint-event-reset.h>
754
755 #undef TRACEPOINT_LOGLEVEL
756 #define TRACEPOINT_LOGLEVEL(__provider, __name, __loglevel) \
757 static const int _loglevel_value___##__provider##___##__name = __loglevel; \
758 static const int *_loglevel___##__provider##___##__name = \
759 &_loglevel_value___##__provider##___##__name;
760
761 #include TRACEPOINT_INCLUDE
762
763 /*
764 * Stage 6.1 of tracepoint event generation.
765 *
766 * Tracepoint UML URI info.
767 */
768
769 /* Reset all macros within TRACEPOINT_EVENT */
770 #include <lttng/ust-tracepoint-event-reset.h>
771
772 #undef TRACEPOINT_MODEL_EMF_URI
773 #define TRACEPOINT_MODEL_EMF_URI(__provider, __name, __uri) \
774 static const char *_model_emf_uri___##__provider##___##__name = __uri;
775
776 #include TRACEPOINT_INCLUDE
777
778 /*
779 * Stage 7.1 of tracepoint event generation.
780 *
781 * Create events description structures. We use a weakref because
782 * loglevels are optional. If not declared, the event will point to the
783 * a loglevel that contains NULL.
784 */
785
786 /* Reset all macros within TRACEPOINT_EVENT */
787 #include <lttng/ust-tracepoint-event-reset.h>
788
789 #undef TRACEPOINT_EVENT_INSTANCE
790 #define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \
791 static const int * \
792 __ref_loglevel___##_provider##___##_name \
793 __attribute__((weakref ("_loglevel___" #_provider "___" #_name))); \
794 static const char * \
795 __ref_model_emf_uri___##_provider##___##_name \
796 __attribute__((weakref ("_model_emf_uri___" #_provider "___" #_name)));\
797 const struct lttng_event_desc __event_desc___##_provider##_##_name = { \
798 .name = #_provider ":" #_name, \
799 .probe_callback = (void (*)(void)) &__event_probe__##_provider##___##_template,\
800 .ctx = NULL, \
801 .fields = __event_fields___##_provider##___##_template, \
802 .nr_fields = _TP_ARRAY_SIZE(__event_fields___##_provider##___##_template), \
803 .loglevel = &__ref_loglevel___##_provider##___##_name, \
804 .signature = __tp_event_signature___##_provider##___##_template, \
805 .u = { \
806 .ext = { \
807 .model_emf_uri = &__ref_model_emf_uri___##_provider##___##_name, \
808 }, \
809 }, \
810 };
811
812 #include TRACEPOINT_INCLUDE
813
814 /*
815 * Stage 7.2 of tracepoint event generation.
816 *
817 * Create array of events.
818 */
819
820 /* Reset all macros within TRACEPOINT_EVENT */
821 #include <lttng/ust-tracepoint-event-reset.h>
822
823 #undef TRACEPOINT_EVENT_INSTANCE
824 #define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \
825 &__event_desc___##_provider##_##_name,
826
827 static const struct lttng_event_desc *_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)[] = {
828 #include TRACEPOINT_INCLUDE
829 };
830
831
832 /*
833 * Stage 8 of tracepoint event generation.
834 *
835 * Create a toplevel descriptor for the whole probe.
836 */
837
838 /* non-const because list head will be modified when registered. */
839 static struct lttng_probe_desc _TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER) = {
840 .provider = __tp_stringify(TRACEPOINT_PROVIDER),
841 .event_desc = _TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER),
842 .nr_events = _TP_ARRAY_SIZE(_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)),
843 .head = { NULL, NULL },
844 .lazy_init_head = { NULL, NULL },
845 .lazy = 0,
846 .major = LTTNG_UST_PROVIDER_MAJOR,
847 .minor = LTTNG_UST_PROVIDER_MINOR,
848 };
849
850 static int _TP_COMBINE_TOKENS(__probe_register_refcount___, TRACEPOINT_PROVIDER);
851
852 /*
853 * Stage 9 of tracepoint event generation.
854 *
855 * Register/unregister probes at module load/unload.
856 *
857 * Generate the constructor as an externally visible symbol for use when
858 * linking the probe statically.
859 *
860 * Register refcount is protected by libc dynamic loader mutex.
861 */
862
863 /* Reset all macros within TRACEPOINT_EVENT */
864 #include <lttng/ust-tracepoint-event-reset.h>
865 static void lttng_ust_notrace __attribute__((constructor))
866 _TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void);
867 static void
868 _TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void)
869 {
870 int ret;
871
872 if (_TP_COMBINE_TOKENS(__probe_register_refcount___,
873 TRACEPOINT_PROVIDER)++) {
874 return;
875 }
876 /*
877 * __tracepoint_provider_check_ ## TRACEPOINT_PROVIDER() is a
878 * static inline function that ensures every probe PROVIDER
879 * argument match the provider within which they appear. It
880 * calls empty static inline functions, and therefore has no
881 * runtime effect. However, if it detects an error, a linker
882 * error will appear.
883 */
884 _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)();
885 ret = lttng_probe_register(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER));
886 if (ret) {
887 fprintf(stderr, "LTTng-UST: Error (%d) while registering tracepoint probe. Duplicate registration of tracepoint probes having the same name is not allowed.\n", ret);
888 abort();
889 }
890 }
891
892 static void lttng_ust_notrace __attribute__((destructor))
893 _TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void);
894 static void
895 _TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void)
896 {
897 if (--_TP_COMBINE_TOKENS(__probe_register_refcount___,
898 TRACEPOINT_PROVIDER)) {
899 return;
900 }
901 lttng_probe_unregister(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER));
902 }
903
904 int _TP_COMBINE_TOKENS(__tracepoint_provider_, TRACEPOINT_PROVIDER);
This page took 0.046486 seconds and 5 git commands to generate.