X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=include%2Flttng%2Fust-tracepoint-event.h;h=0a397e50c6871e18d4d30bfbe7709343422ca9ad;hb=HEAD;hp=6983ef1691d39949e3a72fe11cedf7030cf1d050;hpb=44c72f10aa3cace72ffe40a0f9bb7aadb9c82dc8;p=lttng-ust.git diff --git a/include/lttng/ust-tracepoint-event.h b/include/lttng/ust-tracepoint-event.h index 6983ef16..5d845ae1 100644 --- a/include/lttng/ust-tracepoint-event.h +++ b/include/lttng/ust-tracepoint-event.h @@ -1,474 +1,1292 @@ -/* - * Copyright (c) 2011 - Mathieu Desnoyers - * - * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED - * OR IMPLIED. ANY USE IS AT YOUR OWN RISK. - * - * Permission is hereby granted to use or copy this program - * for any purpose, provided the above notices are retained on all copies. - * Permission to modify the code and to distribute modified code is granted, - * provided the above notices are retained, and a notice that the code was - * modified is included with the above copyright notice. - */ +// SPDX-FileCopyrightText: 2011-2012 Mathieu Desnoyers +// +// SPDX-License-Identifier: MIT +#include #include +#include #include +#include #include -#include +#include +#include +#include +#include +#include +#include #include +#include + +#if LTTNG_UST_COMPAT_API(0) +#define TP_FIELDS LTTNG_UST_TP_FIELDS + +#define ctf_integer lttng_ust_field_integer +#define ctf_integer_hex lttng_ust_field_integer_hex +#define ctf_integer_network lttng_ust_field_integer_network +#define ctf_integer_network_hex lttng_ust_field_integer_network_hex +#define ctf_integer_nowrite lttng_ust_field_integer_nowrite + +#define ctf_float lttng_ust_field_float +#define ctf_float_nowrite lttng_ust_field_float_nowrite + +#define ctf_array lttng_ust_field_array +#define ctf_array_hex lttng_ust_field_array_hex +#define ctf_array_network lttng_ust_field_array_network +#define ctf_array_network_hex lttng_ust_field_array_network_hex +#define ctf_array_text lttng_ust_field_array_text +#define ctf_array_nowrite lttng_ust_field_array_nowrite +#define ctf_array_nowrite_hex lttng_ust_field_array_nowrite_hex +#define ctf_array_network_nowrite lttng_ust_field_array_network_nowrite +#define ctf_array_network_nowrite_hex lttng_ust_field_array_network_nowrite_hex +#define ctf_array_text_nowrite lttng_ust_field_array_text_nowrite + +#define ctf_sequence lttng_ust_field_sequence +#define ctf_sequence_hex lttng_ust_field_sequence_hex +#define ctf_sequence_network lttng_ust_field_sequence_network +#define ctf_sequence_network_hex lttng_ust_field_sequence_network_hex +#define ctf_sequence_text lttng_ust_field_sequence_text +#define ctf_sequence_nowrite lttng_ust_field_sequence_nowrite +#define ctf_sequence_nowrite_hex lttng_ust_field_sequence_nowrite_hex +#define ctf_sequence_network_nowrite lttng_ust_field_sequence_network_nowrite +#define ctf_sequence_network_nowrite_hex lttng_ust_field_sequence_network_nowrite_hex +#define ctf_sequence_text_nowrite lttng_ust_field_sequence_text_nowrite + +#define ctf_string lttng_ust_field_string +#define ctf_string_nowrite lttng_ust_field_string_nowrite + +#define ctf_unused lttng_ust_field_unused +#define ctf_unused_nowrite lttng_ust_field_unused_nowrite + +#define ctf_enum lttng_ust_field_enum +#define ctf_enum_nowrite lttng_ust_field_enum_nowrite +#define ctf_enum_value lttng_ust_field_enum_value +#define ctf_enum_range lttng_ust_field_enum_range +#define ctf_enum_auto lttng_ust_field_enum_auto +#endif /* #if LTTNG_UST_COMPAT_API(0) */ + +#define LTTNG_UST__NULL_STRING "(null)" /* - * Macro declarations used for all stages. - */ - -#undef ctf_integer -#define ctf_integer(_type, _item, _src) \ - ctf_integer_ext(_type, _item, _src, BYTE_ORDER, 10) - -#undef ctf_integer_hex -#define ctf_integer_hex(_type, _item, _src) \ - ctf_integer_ext(_type, _item, _src, BYTE_ORDER, 16) - -#undef ctf_integer_network -#define ctf_integer_network(_type, _item, _src) \ - ctf_integer_ext(_type, _item, _src, BIG_ENDIAN, 10) - -#undef ctf_integer_network_hex -#define ctf_integer_network_hex(_type, _item, _src) \ - ctf_integer_ext(_type, _item, _src, BIG_ENDIAN, 16) - -/* ctf_float is redefined at each step */ - -#undef ctf_array -#define ctf_array(_type, _item, _src, _length) \ - ctf_array_encoded(_type, _item, _src, _length, none) - -#undef ctf_array_text -#define ctf_array_text(_type, _item, _src, _length) \ - ctf_array_encoded(_type, _item, _src, _length, UTF8) - -#undef ctf_sequence -#define ctf_sequence(_type, _item, _src, _length_type, _src_length) \ - ctf_sequence_encoded(_type, _item, _src, \ - _length_type, _src_length, none) - -#undef ctf_sequence_text -#define ctf_sequence_text(_type, _item, _src, _length_type, _src_length) \ - ctf_sequence_encoded(_type, _item, _src, \ - _length_type, _src_length, UTF8) - -/* ctf_string is redefined at each step */ - -/* - * TRACEPOINT_EVENT_CLASS declares a class of tracepoints receiving the + * LTTNG_UST_TRACEPOINT_EVENT_CLASS declares a class of tracepoints receiving the * same arguments and having the same field layout. * - * TRACEPOINT_EVENT_INSTANCE declares an instance of a tracepoint, with + * LTTNG_UST_TRACEPOINT_EVENT_INSTANCE declares an instance of a tracepoint, with * its own provider and name. It refers to a class (template). * - * TRACEPOINT_EVENT declared both a class and an instance and does a + * LTTNG_UST_TRACEPOINT_EVENT declared both a class and an instance and does a * direct mapping from the instance to the class. */ -#undef TRACEPOINT_EVENT -#define TRACEPOINT_EVENT(_provider, _name, _args, _fields) \ - TRACEPOINT_EVENT_CLASS(_provider, _name, \ - _TP_PARAMS(_args), \ - _TP_PARAMS(_fields)) \ - TRACEPOINT_EVENT_INSTANCE(_provider, _name, _name, \ - _TP_PARAMS(args)) +#undef LTTNG_UST_TRACEPOINT_EVENT +#define LTTNG_UST_TRACEPOINT_EVENT(_provider, _name, _args, _fields) \ + LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, \ + LTTNG_UST__TP_PARAMS(_args), \ + LTTNG_UST__TP_PARAMS(_fields)) \ + LTTNG_UST__TRACEPOINT_EVENT_INSTANCE(_provider, _name, _provider, _name, \ + LTTNG_UST__TP_PARAMS(_args)) + +#undef LTTNG_UST_TRACEPOINT_EVENT_CLASS +#define LTTNG_UST_TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ + LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, LTTNG_UST__TP_PARAMS(_args), LTTNG_UST__TP_PARAMS(_fields)) + +#undef LTTNG_UST_TRACEPOINT_EVENT_INSTANCE +#define LTTNG_UST_TRACEPOINT_EVENT_INSTANCE(_template_provider, _template_name, _provider, _name, _args) \ + LTTNG_UST__TRACEPOINT_EVENT_INSTANCE(_template_provider, _template_name, _provider, _name, LTTNG_UST__TP_PARAMS(_args)) /* Helpers */ -#define _TP_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +#define LTTNG_UST__TP_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) -#define _tp_max_t(type, x, y) \ +#define lttng_ust__tp_max_t(type, x, y) \ ({ \ - type __max1 = (x); \ - type __max2 = (y); \ - __max1 > __max2 ? __max1: __max2; \ + type lttng_ust__max1 = (x); \ + type lttng_ust__max2 = (y); \ + lttng_ust__max1 > lttng_ust__max2 ? lttng_ust__max1: lttng_ust__max2; \ }) /* * Stage 0 of tracepoint event generation. * - * Check that each TRACEPOINT_EVENT provider argument match the - * TRACEPOINT_PROVIDER by creating dummy callbacks. + * Check that each LTTNG_UST_TRACEPOINT_EVENT provider argument match the + * LTTNG_UST_TRACEPOINT_PROVIDER by creating dummy callbacks. */ -/* Reset all macros within TRACEPOINT_EVENT */ +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ #include static inline -void _TP_COMBINE_TOKENS(__tracepoint_provider_mismatch_, TRACEPOINT_PROVIDER)(void) +void LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust_tracepoint_provider_mismatch_, LTTNG_UST_TRACEPOINT_PROVIDER)(void) + lttng_ust_notrace; +static inline +void LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust_tracepoint_provider_mismatch_, LTTNG_UST_TRACEPOINT_PROVIDER)(void) { } -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ - __tracepoint_provider_mismatch_##_provider(); +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ + lttng_ust_tracepoint_provider_mismatch_##_provider(); -#undef TRACEPOINT_EVENT_INSTANCE -#define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ - __tracepoint_provider_mismatch_##_provider(); +#undef LTTNG_UST__TRACEPOINT_EVENT_INSTANCE +#define LTTNG_UST__TRACEPOINT_EVENT_INSTANCE(_template_provider, _template_name, _provider, _name, _args) \ + lttng_ust_tracepoint_provider_mismatch_##_provider(); -static __attribute__((unused)) -void _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(void) +static inline +void LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust_tracepoint_provider_check_, LTTNG_UST_TRACEPOINT_PROVIDER)(void) + lttng_ust_notrace; +static inline +void LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust_tracepoint_provider_check_, LTTNG_UST_TRACEPOINT_PROVIDER)(void) { -#include TRACEPOINT_INCLUDE +#include LTTNG_UST_TRACEPOINT_INCLUDE } /* - * Stage 1 of tracepoint event generation. + * Stage 0.1 of tracepoint event generation. * - * Create event field type metadata section. - * Each event produce an array of fields. + * Check that each LTTNG_UST_TRACEPOINT_EVENT provider:name does not exceed the + * tracepoint name length limit. */ -/* Reset all macros within TRACEPOINT_EVENT */ +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ #include -#undef ctf_integer_ext -#define ctf_integer_ext(_type, _item, _src, _byte_order, _base) \ - { \ - .name = #_item, \ - .type = __type_integer(_type, _byte_order, _base, none),\ - }, - -#undef ctf_float -#define ctf_float(_type, _item, _src) \ - { \ - .name = #_item, \ - .type = __type_float(_type), \ - }, - -#undef ctf_array_encoded -#define ctf_array_encoded(_type, _item, _src, _length, _encoding) \ - { \ - .name = #_item, \ - .type = \ - { \ - .atype = atype_array, \ - .u.array = \ - { \ - .length = _length, \ - .elem_type = __type_integer(_type, BYTE_ORDER, 10, _encoding), \ - }, \ - }, \ - }, - -#undef ctf_sequence_encoded -#define ctf_sequence_encoded(_type, _item, _src, \ - _length_type, _src_length, _encoding) \ - { \ - .name = #_item, \ - .type = \ - { \ - .atype = atype_sequence, \ - .u.sequence = \ - { \ - .length_type = __type_integer(_length_type, BYTE_ORDER, 10, none), \ - .elem_type = __type_integer(_type, BYTE_ORDER, 10, _encoding), \ - }, \ - }, \ - }, - -#undef ctf_string -#define ctf_string(_item, _src) \ - { \ - .name = #_item, \ - .type = \ - { \ - .atype = atype_string, \ - .u.basic.string.encoding = lttng_encode_UTF8, \ - }, \ - }, - -#undef TP_FIELDS -#define TP_FIELDS(args...) args /* Only one used in this phase */ - -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ - static const struct lttng_event_field __event_fields___##_provider##___##_name[] = { \ - _fields \ +#undef LTTNG_UST__TRACEPOINT_EVENT_INSTANCE +#define LTTNG_UST__TRACEPOINT_EVENT_INSTANCE(_template_provider, _template_name, _provider, _name, _args) \ + lttng_ust_tracepoint_validate_name_len(_provider, _name); + +#include LTTNG_UST_TRACEPOINT_INCLUDE + +/* + * Stage 0.2 of tracepoint event generation. + * + * Create dummy trace prototypes for each event class, and for each used + * template. This will allow checking whether the prototypes from the + * class and the instance using the class actually match. + */ + +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ +#include + +#undef LTTNG_UST_TP_ARGS +#define LTTNG_UST_TP_ARGS(...) __VA_ARGS__ + +#undef LTTNG_UST__TRACEPOINT_EVENT_INSTANCE +#define LTTNG_UST__TRACEPOINT_EVENT_INSTANCE(_template_provider, _template_name, _provider, _name, _args) \ +void lttng_ust__event_template_proto___##_template_provider##___##_template_name(LTTNG_UST__TP_ARGS_DATA_PROTO(_args)); + +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +void lttng_ust__event_template_proto___##_provider##___##_name(LTTNG_UST__TP_ARGS_DATA_PROTO(_args)); + +#include LTTNG_UST_TRACEPOINT_INCLUDE + +/* + * Stage 0.9 of tracepoint event generation + * + * Unfolding the enums + */ +#include + +/* Enumeration entry (single value) */ +#undef lttng_ust_field_enum_value +#define lttng_ust_field_enum_value(_string, _value) \ + LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_enum_entry, { \ + .struct_size = sizeof(struct lttng_ust_enum_entry), \ + .start = { \ + .value = lttng_ust_is_signed_type(__typeof__(_value)) ? \ + (long long) (_value) : (_value), \ + .signedness = lttng_ust_is_signed_type(__typeof__(_value)), \ + }, \ + .end = { \ + .value = lttng_ust_is_signed_type(__typeof__(_value)) ? \ + (long long) (_value) : (_value), \ + .signedness = lttng_ust_is_signed_type(__typeof__(_value)), \ + }, \ + .string = (_string), \ + }), + +/* Enumeration entry (range) */ +#undef lttng_ust_field_enum_range +#define lttng_ust_field_enum_range(_string, _range_start, _range_end) \ + LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_enum_entry, { \ + .struct_size = sizeof(struct lttng_ust_enum_entry), \ + .start = { \ + .value = lttng_ust_is_signed_type(__typeof__(_range_start)) ? \ + (long long) (_range_start) : (_range_start), \ + .signedness = lttng_ust_is_signed_type(__typeof__(_range_start)), \ + }, \ + .end = { \ + .value = lttng_ust_is_signed_type(__typeof__(_range_end)) ? \ + (long long) (_range_end) : (_range_end), \ + .signedness = lttng_ust_is_signed_type(__typeof__(_range_end)), \ + }, \ + .string = (_string), \ + }), + +/* Enumeration entry (automatic value; follows the rules of CTF) */ +#undef lttng_ust_field_enum_auto +#define lttng_ust_field_enum_auto(_string) \ + LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_enum_entry, { \ + .struct_size = sizeof(struct lttng_ust_enum_entry), \ + .start = { \ + .value = -1ULL, \ + .signedness = 0, \ + }, \ + .end = { \ + .value = -1ULL, \ + .signedness = 0, \ + }, \ + .string = (_string), \ + .options = LTTNG_UST_ENUM_ENTRY_OPTION_IS_AUTO, \ + }), + +#undef LTTNG_UST_TP_ENUM_VALUES +#define LTTNG_UST_TP_ENUM_VALUES(...) \ + __VA_ARGS__ + +#if LTTNG_UST_COMPAT_API(0) +# undef TP_ENUM_VALUES +# define TP_ENUM_VALUES LTTNG_UST_TP_ENUM_VALUES +#endif /* #if LTTNG_UST_COMPAT_API(0) */ + +#undef LTTNG_UST_TRACEPOINT_ENUM +#define LTTNG_UST_TRACEPOINT_ENUM(_provider, _name, _values) \ + const struct lttng_ust_enum_entry * const __enum_values__##_provider##_##_name[] = { \ + _values \ + lttng_ust_field_enum_value("", 0) /* Dummy, 0-len array forbidden by C99. */ \ }; +#include LTTNG_UST_TRACEPOINT_INCLUDE -#include TRACEPOINT_INCLUDE /* - * Stage 2 of tracepoint event generation. + * Stage 0.9.0 + * Verifying sequence length types are of an unsigned type. + */ + +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ +#include +#include +#include + +/* + * Note that it is not possible to encode the length type as a C identifier, + * since it can be multiple tokens. + */ +#undef lttng_ust__field_sequence_encoded +#define lttng_ust__field_sequence_encoded(_type, _item, _src, _byte_order, \ + _length_type, _src_length, _encoding, _nowrite, \ + _elem_type_base) \ + lttng_ust_static_assert(!lttng_ust_is_signed_type(_length_type), \ + "Length type " #_length_type " is not a unsigned integer type", \ + Length_type_is_not_a_unsigned_integer_type); + +#undef LTTNG_UST_TP_FIELDS +#define LTTNG_UST_TP_FIELDS(...) __VA_ARGS__ /* Only one used in this phase */ + +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ + _fields + +#include LTTNG_UST_TRACEPOINT_INCLUDE + +#if defined(__cplusplus) + +/* + * Stage 0.9.1 + * Verifying array and sequence elements are of an integer or pointer + * type. * - * Create probe callback prototypes. + * This compile-time check is only enabled in C++, because the C + * implementation of lttng_ust_is_pointer_type does not support opaque + * pointer types. */ -/* Reset all macros within TRACEPOINT_EVENT */ +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ #include +#include +#include + +#undef lttng_ust__field_array_encoded +#define lttng_ust__field_array_encoded(_type, _item, _src, _byte_order, \ + _length, _encoding, _nowrite, \ + _elem_type_base) \ + lttng_ust_field_array_element_type_is_supported(_type, _item); -#undef TP_ARGS -#define TP_ARGS(args...) args +#undef lttng_ust__field_sequence_encoded +#define lttng_ust__field_sequence_encoded(_type, _item, _src, _byte_order, \ + _length_type, _src_length, _encoding, _nowrite, \ + _elem_type_base) \ + lttng_ust_field_array_element_type_is_supported(_type, _item); -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ -static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); +#undef LTTNG_UST_TP_FIELDS +#define LTTNG_UST_TP_FIELDS(...) __VA_ARGS__ /* Only one used in this phase */ -#include TRACEPOINT_INCLUDE +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ + _fields + +#include LTTNG_UST_TRACEPOINT_INCLUDE + +#endif /* - * Stage 3 of tracepoint event generation. + * Stage 0.9.2 of tracepoint event generation. * - * Create an array of events. + * Create probe signature */ -/* Reset all macros within TRACEPOINT_EVENT */ +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ #include -#undef TRACEPOINT_EVENT_INSTANCE -#define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ - { \ - .fields = __event_fields___##_provider##___##_template,\ - .name = #_provider ":" #_name, \ - .probe_callback = (void *) &__event_probe__##_provider##___##_template,\ - .nr_fields = _TP_ARRAY_SIZE(__event_fields___##_provider##___##_template), \ - }, - -static const struct lttng_event_desc _TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)[] = { -#include TRACEPOINT_INCLUDE -}; +#undef LTTNG_UST_TP_ARGS +#define LTTNG_UST_TP_ARGS(...) __VA_ARGS__ + +#define LTTNG_UST__TP_EXTRACT_STRING2(...) #__VA_ARGS__ + +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static const char __tp_event_signature___##_provider##___##_name[] = \ + LTTNG_UST__TP_EXTRACT_STRING2(_args); + +#include LTTNG_UST_TRACEPOINT_INCLUDE +#undef LTTNG_UST__TP_EXTRACT_STRING2 /* - * Stage 4 of tracepoint event generation. + * Stage 1 of tracepoint event generation. * - * Create a toplevel descriptor for the whole probe. + * Create probe callback prototypes. */ -/* non-const because list head will be modified when registered. */ -static struct lttng_probe_desc _TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER) = { - .event_desc = _TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER), - .nr_events = _TP_ARRAY_SIZE(_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)), -}; +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ +#include + +#undef LTTNG_UST_TP_ARGS +#define LTTNG_UST_TP_ARGS(...) __VA_ARGS__ + +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static void lttng_ust__event_probe__##_provider##___##_name(LTTNG_UST__TP_ARGS_DATA_PROTO(_args)); + +#include LTTNG_UST_TRACEPOINT_INCLUDE /* - * Stage 5 of tracepoint event generation. + * Stage 1.1 of tracepoint event generation. + * + * Declare toplevel descriptor for the whole probe. + * Unlike C, C++ does not allow tentative definitions. Therefore, we + * need to explicitly declare the variable with "extern", using hidden + * visibility to keep this symbol from being exported to the global + * symbol table. + */ + +extern const struct lttng_ust_probe_desc LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_desc___, LTTNG_UST_TRACEPOINT_PROVIDER) + __attribute__((visibility("hidden"))); + +/* + * Stage 2 of tracepoint event generation. + * + * Create event field type metadata section. + * Each event produce an array of fields. + */ + +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ +#include +#include +#include + +#undef lttng_ust__field_integer_ext +#define lttng_ust__field_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \ + LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_event_field, { \ + .struct_size = sizeof(struct lttng_ust_event_field), \ + .name = #_item, \ + .type = lttng_ust_type_integer_define(_type, _byte_order, _base), \ + .nowrite = _nowrite, \ + .nofilter = 0, \ + }), + +#undef lttng_ust__field_float +#define lttng_ust__field_float(_type, _item, _src, _nowrite) \ + LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_event_field, { \ + .struct_size = sizeof(struct lttng_ust_event_field), \ + .name = #_item, \ + .type = lttng_ust_type_float_define(_type), \ + .nowrite = _nowrite, \ + .nofilter = 0, \ + }), + +#undef lttng_ust__field_array_encoded +#define lttng_ust__field_array_encoded(_type, _item, _src, _byte_order, \ + _length, _encoding, _nowrite, \ + _elem_type_base) \ + LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_event_field, { \ + .struct_size = sizeof(struct lttng_ust_event_field), \ + .name = #_item, \ + .type = (const struct lttng_ust_type_common *) LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_type_array, { \ + .parent = { \ + .type = lttng_ust_type_array, \ + }, \ + .struct_size = sizeof(struct lttng_ust_type_array), \ + .elem_type = lttng_ust_type_integer_define(_type, _byte_order, _elem_type_base), \ + .length = _length, \ + .alignment = 0, \ + .encoding = lttng_ust_string_encoding_##_encoding, \ + }), \ + .nowrite = _nowrite, \ + .nofilter = 0, \ + }), + +#undef lttng_ust__field_sequence_encoded +#define lttng_ust__field_sequence_encoded(_type, _item, _src, _byte_order, \ + _length_type, _src_length, _encoding, _nowrite, \ + _elem_type_base) \ + LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_event_field, { \ + .struct_size = sizeof(struct lttng_ust_event_field), \ + .name = "_" #_item "_length", \ + .type = lttng_ust_type_integer_define(_length_type, LTTNG_UST_BYTE_ORDER, 10), \ + .nowrite = _nowrite, \ + .nofilter = 1, \ + }), \ + LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_event_field, { \ + .struct_size = sizeof(struct lttng_ust_event_field), \ + .name = #_item, \ + .type = (const struct lttng_ust_type_common *) LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_type_sequence, { \ + .parent = { \ + .type = lttng_ust_type_sequence, \ + }, \ + .struct_size = sizeof(struct lttng_ust_type_sequence), \ + .length_name = NULL, /* Use previous field. */ \ + .elem_type = lttng_ust_type_integer_define(_type, _byte_order, _elem_type_base), \ + .alignment = 0, \ + .encoding = lttng_ust_string_encoding_##_encoding, \ + }), \ + .nowrite = _nowrite, \ + .nofilter = 0, \ + }), + +#undef lttng_ust__field_string +#define lttng_ust__field_string(_item, _src, _nowrite) \ + LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_event_field, { \ + .struct_size = sizeof(struct lttng_ust_event_field), \ + .name = #_item, \ + .type = (const struct lttng_ust_type_common *) LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_type_string, { \ + .parent = { \ + .type = lttng_ust_type_string, \ + }, \ + .struct_size = sizeof(struct lttng_ust_type_string), \ + .encoding = lttng_ust_string_encoding_UTF8, \ + }), \ + .nowrite = _nowrite, \ + .nofilter = 0, \ + }), + +#undef lttng_ust__field_unused +#define lttng_ust__field_unused(_src) + +#undef lttng_ust__field_enum +#define lttng_ust__field_enum(_provider, _name, _type, _item, _src, _nowrite) \ + LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_event_field, { \ + .struct_size = sizeof(struct lttng_ust_event_field), \ + .name = #_item, \ + .type = (const struct lttng_ust_type_common *) LTTNG_UST_COMPOUND_LITERAL(const struct lttng_ust_type_enum, { \ + .parent = { \ + .type = lttng_ust_type_enum, \ + }, \ + .struct_size = sizeof(struct lttng_ust_type_enum), \ + .desc = &__enum_##_provider##_##_name, \ + .container_type = lttng_ust_type_integer_define(_type, LTTNG_UST_BYTE_ORDER, 10), \ + }), \ + .nowrite = _nowrite, \ + .nofilter = 0, \ + }), + +#undef LTTNG_UST_TP_FIELDS +#define LTTNG_UST_TP_FIELDS(...) __VA_ARGS__ /* Only one used in this phase */ + +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ + static const struct lttng_ust_event_field * const lttng_ust__event_fields___##_provider##___##_name[] = { \ + _fields \ + lttng_ust_field_integer(int, dummy, 0) /* Dummy, C99 forbids 0-len array. */ \ + }; \ + static const struct lttng_ust_tracepoint_class lttng_ust__event_class___##_provider##___##_name = { \ + .struct_size = sizeof(struct lttng_ust_tracepoint_class), \ + .fields = lttng_ust__event_fields___##_provider##___##_name, \ + .nr_fields = LTTNG_UST__TP_ARRAY_SIZE(lttng_ust__event_fields___##_provider##___##_name) - 1, \ + .probe_callback = (void (*)(void)) <tng_ust__event_probe__##_provider##___##_name, \ + .signature = __tp_event_signature___##_provider##___##_name, \ + .probe_desc = <tng_ust__probe_desc___##_provider, \ + }; + +#undef LTTNG_UST_TRACEPOINT_ENUM +#define LTTNG_UST_TRACEPOINT_ENUM(_provider, _name, _values) \ + static const struct lttng_ust_enum_desc __enum_##_provider##_##_name = { \ + .struct_size = sizeof(struct lttng_ust_enum_desc), \ + .name = #_provider "_" #_name, \ + .entries = __enum_values__##_provider##_##_name, \ + .nr_entries = LTTNG_UST__TP_ARRAY_SIZE(__enum_values__##_provider##_##_name) - 1, \ + .probe_desc = <tng_ust__probe_desc___##_provider, \ + }; + +#include LTTNG_UST_TRACEPOINT_INCLUDE + +/* + * Stage 3.0 of tracepoint event generation. * * Create static inline function that calculates event size. */ -/* Reset all macros within TRACEPOINT_EVENT */ +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ #include +#include -#undef ctf_integer_ext -#define ctf_integer_ext(_type, _item, _src, _byte_order, _base) \ - __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ +#undef lttng_ust__field_integer_ext +#define lttng_ust__field_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \ + if (0) \ + (void) (_src); /* Unused */ \ + __event_len += lttng_ust_ring_buffer_align(__event_len, lttng_ust_rb_alignof(_type)); \ __event_len += sizeof(_type); -#undef ctf_float -#define ctf_float(_type, _item, _src) \ - __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ +#undef lttng_ust__field_float +#define lttng_ust__field_float(_type, _item, _src, _nowrite) \ + if (0) \ + (void) (_src); /* Unused */ \ + __event_len += lttng_ust_ring_buffer_align(__event_len, lttng_ust_rb_alignof(_type)); \ __event_len += sizeof(_type); -#undef ctf_array_encoded -#define ctf_array_encoded(_type, _item, _src, _length, _encoding) \ - __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ +#undef lttng_ust__field_array_encoded +#define lttng_ust__field_array_encoded(_type, _item, _src, _byte_order, _length, _encoding, \ + _nowrite, _elem_type_base) \ + if (0) \ + (void) (_src); /* Unused */ \ + __event_len += lttng_ust_ring_buffer_align(__event_len, lttng_ust_rb_alignof(_type)); \ __event_len += sizeof(_type) * (_length); -#undef ctf_sequence_encoded -#define ctf_sequence_encoded(_type, _item, _src, _length_type, \ - _src_length, _encoding) \ - __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_length_type)); \ +#undef lttng_ust__field_sequence_encoded +#define lttng_ust__field_sequence_encoded(_type, _item, _src, _byte_order, _length_type, \ + _src_length, _encoding, _nowrite, _elem_type_base) \ + if (0) \ + (void) (_src); /* Unused */ \ + __event_len += lttng_ust_ring_buffer_align(__event_len, lttng_ust_rb_alignof(_length_type)); \ __event_len += sizeof(_length_type); \ - __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ + __event_len += lttng_ust_ring_buffer_align(__event_len, lttng_ust_rb_alignof(_type)); \ __dynamic_len[__dynamic_len_idx] = (_src_length); \ __event_len += sizeof(_type) * __dynamic_len[__dynamic_len_idx]; \ __dynamic_len_idx++; -#undef ctf_string -#define ctf_string(_item, _src) \ - __event_len += __dynamic_len[__dynamic_len_idx++] = strlen(_src) + 1; +#undef lttng_ust__field_string +#define lttng_ust__field_string(_item, _src, _nowrite) \ + __event_len += __dynamic_len[__dynamic_len_idx++] = \ + strlen((_src) ? (_src) : LTTNG_UST__NULL_STRING) + 1; + +#undef lttng_ust__field_unused +#define lttng_ust__field_unused(_src) \ + if (0) \ + (void) (_src); /* Unused */ + +#undef lttng_ust__field_enum +#define lttng_ust__field_enum(_provider, _name, _type, _item, _src, _nowrite) \ + lttng_ust__field_integer_ext(_type, _item, _src, LTTNG_UST_BYTE_ORDER, 10, _nowrite) -#undef TP_ARGS -#define TP_ARGS(args...) args +#undef LTTNG_UST_TP_ARGS +#define LTTNG_UST_TP_ARGS(...) __VA_ARGS__ -#undef TP_FIELDS -#define TP_FIELDS(args...) args +#undef LTTNG_UST_TP_FIELDS +#define LTTNG_UST_TP_FIELDS(...) __VA_ARGS__ -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ -static inline size_t __event_get_size__##_provider##___##_name(size_t *__dynamic_len, _TP_ARGS_DATA_PROTO(_args)) \ +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static inline \ +size_t lttng_ust__event_get_size__##_provider##___##_name(size_t *__dynamic_len, LTTNG_UST__TP_ARGS_DATA_PROTO(_args)) \ + lttng_ust_notrace; \ +static inline \ +size_t lttng_ust__event_get_size__##_provider##___##_name( \ + size_t *__dynamic_len __attribute__((__unused__)), \ + LTTNG_UST__TP_ARGS_DATA_PROTO(_args)) \ { \ size_t __event_len = 0; \ - unsigned int __dynamic_len_idx = 0; \ + unsigned int __dynamic_len_idx __attribute__((__unused__)) = 0; \ \ if (0) \ - (void) __dynamic_len_idx; /* don't warn if unused */ \ + (void) __tp_data; /* don't warn if unused */ \ + \ _fields \ return __event_len; \ } -#include TRACEPOINT_INCLUDE +#include LTTNG_UST_TRACEPOINT_INCLUDE /* - * Stage 6 of tracepoint event generation. + * Stage 3.1 of tracepoint event generation. * - * Create static inline function that calculates event payload alignment. + * Create static inline function that layout the filter stack data. + * We make both write and nowrite data available to the filter. */ -/* Reset all macros within TRACEPOINT_EVENT */ +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ #include +#include +#include + +#undef lttng_ust__field_integer_ext +#define lttng_ust__field_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \ + if (lttng_ust_is_signed_type(_type)) { \ + int64_t __ctf_tmp_int64; \ + switch (sizeof(_type)) { \ + case 1: \ + { \ + union { _type t; int8_t v; } __tmp = { (_type) (_src) }; \ + __ctf_tmp_int64 = (int64_t) __tmp.v; \ + break; \ + } \ + case 2: \ + { \ + union { _type t; int16_t v; } __tmp = { (_type) (_src) }; \ + if (_byte_order != LTTNG_UST_BYTE_ORDER) \ + __tmp.v = lttng_ust_bswap_16(__tmp.v); \ + __ctf_tmp_int64 = (int64_t) __tmp.v; \ + break; \ + } \ + case 4: \ + { \ + union { _type t; int32_t v; } __tmp = { (_type) (_src) }; \ + if (_byte_order != LTTNG_UST_BYTE_ORDER) \ + __tmp.v = lttng_ust_bswap_32(__tmp.v); \ + __ctf_tmp_int64 = (int64_t) __tmp.v; \ + break; \ + } \ + case 8: \ + { \ + union { _type t; int64_t v; } __tmp = { (_type) (_src) }; \ + if (_byte_order != LTTNG_UST_BYTE_ORDER) \ + __tmp.v = lttng_ust_bswap_64(__tmp.v); \ + __ctf_tmp_int64 = (int64_t) __tmp.v; \ + break; \ + } \ + default: \ + abort(); \ + }; \ + memcpy(__stack_data, &__ctf_tmp_int64, sizeof(int64_t)); \ + } else { \ + uint64_t __ctf_tmp_uint64; \ + switch (sizeof(_type)) { \ + case 1: \ + { \ + union { _type t; uint8_t v; } __tmp = { (_type) (_src) }; \ + __ctf_tmp_uint64 = (uint64_t) __tmp.v; \ + break; \ + } \ + case 2: \ + { \ + union { _type t; uint16_t v; } __tmp = { (_type) (_src) }; \ + if (_byte_order != LTTNG_UST_BYTE_ORDER) \ + __tmp.v = lttng_ust_bswap_16(__tmp.v); \ + __ctf_tmp_uint64 = (uint64_t) __tmp.v; \ + break; \ + } \ + case 4: \ + { \ + union { _type t; uint32_t v; } __tmp = { (_type) (_src) }; \ + if (_byte_order != LTTNG_UST_BYTE_ORDER) \ + __tmp.v = lttng_ust_bswap_32(__tmp.v); \ + __ctf_tmp_uint64 = (uint64_t) __tmp.v; \ + break; \ + } \ + case 8: \ + { \ + union { _type t; uint64_t v; } __tmp = { (_type) (_src) }; \ + if (_byte_order != LTTNG_UST_BYTE_ORDER) \ + __tmp.v = lttng_ust_bswap_64(__tmp.v); \ + __ctf_tmp_uint64 = (uint64_t) __tmp.v; \ + break; \ + } \ + default: \ + abort(); \ + }; \ + memcpy(__stack_data, &__ctf_tmp_uint64, sizeof(uint64_t)); \ + } \ + __stack_data += sizeof(int64_t); + +#undef lttng_ust__field_float +#define lttng_ust__field_float(_type, _item, _src, _nowrite) \ + { \ + double __ctf_tmp_double = (double) (_type) (_src); \ + memcpy(__stack_data, &__ctf_tmp_double, sizeof(double)); \ + __stack_data += sizeof(double); \ + } + +#undef lttng_ust__field_array_encoded +#define lttng_ust__field_array_encoded(_type, _item, _src, _byte_order, _length, \ + _encoding, _nowrite, _elem_type_base) \ + { \ + unsigned long __ctf_tmp_ulong = (unsigned long) (_length); \ + const void *__ctf_tmp_ptr = (_src); \ + memcpy(__stack_data, &__ctf_tmp_ulong, sizeof(unsigned long)); \ + __stack_data += sizeof(unsigned long); \ + memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \ + __stack_data += sizeof(void *); \ + } + +#undef lttng_ust__field_sequence_encoded +#define lttng_ust__field_sequence_encoded(_type, _item, _src, _byte_order, _length_type, \ + _src_length, _encoding, _nowrite, _elem_type_base) \ + { \ + unsigned long __ctf_tmp_ulong = (unsigned long) (_src_length); \ + const void *__ctf_tmp_ptr = (_src); \ + memcpy(__stack_data, &__ctf_tmp_ulong, sizeof(unsigned long)); \ + __stack_data += sizeof(unsigned long); \ + memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \ + __stack_data += sizeof(void *); \ + } -#undef ctf_integer_ext -#define ctf_integer_ext(_type, _item, _src, _byte_order, _base) \ - __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type)); +#undef lttng_ust__field_string +#define lttng_ust__field_string(_item, _src, _nowrite) \ + { \ + const void *__ctf_tmp_ptr = \ + ((_src) ? (_src) : LTTNG_UST__NULL_STRING); \ + memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \ + __stack_data += sizeof(void *); \ + } -#undef ctf_float -#define ctf_float(_type, _item, _src) \ - __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type)); +#undef lttng_ust__field_unused +#define lttng_ust__field_unused(_src) \ + if (0) \ + (void) (_src); -#undef ctf_array_encoded -#define ctf_array_encoded(_type, _item, _src, _length, _encoding) \ - __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type)); +#undef lttng_ust__field_enum +#define lttng_ust__field_enum(_provider, _name, _type, _item, _src, _nowrite) \ + lttng_ust__field_integer_ext(_type, _item, _src, LTTNG_UST_BYTE_ORDER, 10, _nowrite) -#undef ctf_sequence_encoded -#define ctf_sequence_encoded(_type, _item, _src, _length_type, \ - _src_length, _encoding) \ - __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_length_type)); \ - __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type)); +#undef LTTNG_UST_TP_ARGS +#define LTTNG_UST_TP_ARGS(...) __VA_ARGS__ -#undef ctf_string -#define ctf_string(_item, _src) +#undef LTTNG_UST_TP_FIELDS +#define LTTNG_UST_TP_FIELDS(...) __VA_ARGS__ + +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static inline \ +void lttng_ust__event_prepare_interpreter_stack__##_provider##___##_name(char *__stack_data,\ + LTTNG_UST__TP_ARGS_DATA_PROTO(_args)) \ +{ \ + if (0) { \ + (void) __tp_data; /* don't warn if unused */ \ + (void) __stack_data; /* don't warn if unused */ \ + } \ + \ + _fields \ +} -#undef TP_ARGS -#define TP_ARGS(args...) args +#include LTTNG_UST_TRACEPOINT_INCLUDE -#undef TP_FIELDS -#define TP_FIELDS(args...) args +/* + * Stage 4 of tracepoint event generation. + * + * Create static inline function that calculates event payload alignment. + */ -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ +#include +#include + +#undef lttng_ust__field_integer_ext +#define lttng_ust__field_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \ + if (0) \ + (void) (_src); /* Unused */ \ + __event_align = lttng_ust__tp_max_t(size_t, __event_align, lttng_ust_rb_alignof(_type)); + +#undef lttng_ust__field_float +#define lttng_ust__field_float(_type, _item, _src, _nowrite) \ + if (0) \ + (void) (_src); /* Unused */ \ + __event_align = lttng_ust__tp_max_t(size_t, __event_align, lttng_ust_rb_alignof(_type)); + +#undef lttng_ust__field_array_encoded +#define lttng_ust__field_array_encoded(_type, _item, _src, _byte_order, _length, \ + _encoding, _nowrite, _elem_type_base) \ + if (0) \ + (void) (_src); /* Unused */ \ + __event_align = lttng_ust__tp_max_t(size_t, __event_align, lttng_ust_rb_alignof(_type)); + +#undef lttng_ust__field_sequence_encoded +#define lttng_ust__field_sequence_encoded(_type, _item, _src, _byte_order, _length_type, \ + _src_length, _encoding, _nowrite, _elem_type_base) \ + if (0) \ + (void) (_src); /* Unused */ \ + if (0) \ + (void) (_src_length); /* Unused */ \ + __event_align = lttng_ust__tp_max_t(size_t, __event_align, lttng_ust_rb_alignof(_length_type)); \ + __event_align = lttng_ust__tp_max_t(size_t, __event_align, lttng_ust_rb_alignof(_type)); + +#undef lttng_ust__field_string +#define lttng_ust__field_string(_item, _src, _nowrite) \ + if (0) \ + (void) (_src); /* Unused */ + +#undef lttng_ust__field_unused +#define lttng_ust__field_unused(_src) \ + if (0) \ + (void) (_src); /* Unused */ + +#undef lttng_ust__field_enum +#define lttng_ust__field_enum(_provider, _name, _type, _item, _src, _nowrite) \ + lttng_ust__field_integer_ext(_type, _item, _src, LTTNG_UST_BYTE_ORDER, 10, _nowrite) + +#undef LTTNG_UST_TP_ARGS +#define LTTNG_UST_TP_ARGS(...) __VA_ARGS__ + +#undef LTTNG_UST_TP_FIELDS +#define LTTNG_UST_TP_FIELDS(...) __VA_ARGS__ + +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ static inline \ -size_t __event_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args)) \ +size_t lttng_ust__event_get_align__##_provider##___##_name(LTTNG_UST__TP_ARGS_PROTO(_args)) \ + lttng_ust_notrace; \ +static inline \ +size_t lttng_ust__event_get_align__##_provider##___##_name(LTTNG_UST__TP_ARGS_PROTO(_args)) \ { \ size_t __event_align = 1; \ _fields \ return __event_align; \ } -#include TRACEPOINT_INCLUDE +#include LTTNG_UST_TRACEPOINT_INCLUDE /* - * Stage 7 of tracepoint event generation. + * Stage 5 of tracepoint event generation. * * Create the probe function. This function calls event size calculation * and writes event data into the buffer. */ -/* Reset all macros within TRACEPOINT_EVENT */ +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ #include +#include -#undef ctf_integer_ext -#define ctf_integer_ext(_type, _item, _src, _byte_order, _base) \ +#undef lttng_ust__field_integer_ext +#define lttng_ust__field_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \ { \ _type __tmp = (_src); \ - lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(__tmp));\ - __chan->ops->event_write(&__ctx, &__tmp, sizeof(__tmp));\ + __chan->ops->event_write(&__ctx, &__tmp, sizeof(__tmp), lttng_ust_rb_alignof(__tmp));\ } -#undef ctf_float -#define ctf_float(_type, _item, _src) \ +#undef lttng_ust__field_float +#define lttng_ust__field_float(_type, _item, _src, _nowrite) \ { \ _type __tmp = (_src); \ - lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(__tmp));\ - __chan->ops->event_write(&__ctx, &__tmp, sizeof(__tmp));\ + __chan->ops->event_write(&__ctx, &__tmp, sizeof(__tmp), lttng_ust_rb_alignof(__tmp));\ } -#undef ctf_array_encoded -#define ctf_array_encoded(_type, _item, _src, _length, _encoding) \ - lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_type)); \ - __chan->ops->event_write(&__ctx, _src, sizeof(_type) * (_length)); - -#undef ctf_sequence_encoded -#define ctf_sequence_encoded(_type, _item, _src, _length_type, \ - _src_length, _encoding) \ +#undef lttng_ust__field_array_encoded +#define lttng_ust__field_array_encoded(_type, _item, _src, _byte_order, _length, \ + _encoding, _nowrite, _elem_type_base) \ + if (lttng_ust_string_encoding_##_encoding == lttng_ust_string_encoding_none) \ + __chan->ops->event_write(&__ctx, _src, sizeof(_type) * (_length), lttng_ust_rb_alignof(_type)); \ + else \ + __chan->ops->event_pstrcpy_pad(&__ctx, (const char *) (_src), _length); + +#undef lttng_ust__field_sequence_encoded +#define lttng_ust__field_sequence_encoded(_type, _item, _src, _byte_order, _length_type, \ + _src_length, _encoding, _nowrite, _elem_type_base) \ { \ - _length_type __tmpl = __dynamic_len[__dynamic_len_idx]; \ - lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\ - __chan->ops->event_write(&__ctx, &__tmpl, sizeof(_length_type));\ + _length_type __tmpl = __stackvar.__dynamic_len[__dynamic_len_idx]; \ + __chan->ops->event_write(&__ctx, &__tmpl, sizeof(_length_type), lttng_ust_rb_alignof(_length_type));\ } \ - lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_type)); \ - __chan->ops->event_write(&__ctx, _src, \ - sizeof(_type) * __get_dynamic_len(dest)); + if (lttng_ust_string_encoding_##_encoding == lttng_ust_string_encoding_none) \ + __chan->ops->event_write(&__ctx, _src, \ + sizeof(_type) * lttng_ust__get_dynamic_len(dest), lttng_ust_rb_alignof(_type)); \ + else \ + __chan->ops->event_pstrcpy_pad(&__ctx, (const char *) (_src), lttng_ust__get_dynamic_len(dest)); \ + +#undef lttng_ust__field_string +#define lttng_ust__field_string(_item, _src, _nowrite) \ + { \ + const char *__ctf_tmp_string = \ + ((_src) ? (_src) : LTTNG_UST__NULL_STRING); \ + __chan->ops->event_strcpy(&__ctx, __ctf_tmp_string, \ + lttng_ust__get_dynamic_len(dest)); \ + } + +#undef lttng_ust__field_unused +#define lttng_ust__field_unused(_src) -#undef ctf_string -#define ctf_string(_item, _src) \ - lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(*(_src))); \ - __chan->ops->event_write(&__ctx, _src, __get_dynamic_len(dest)); +#undef lttng_ust__field_enum +#define lttng_ust__field_enum(_provider, _name, _type, _item, _src, _nowrite) \ + lttng_ust__field_integer_ext(_type, _item, _src, LTTNG_UST_BYTE_ORDER, 10, _nowrite) /* Beware: this get len actually consumes the len value */ -#undef __get_dynamic_len -#define __get_dynamic_len(field) __dynamic_len[__dynamic_len_idx++] +#undef lttng_ust__get_dynamic_len +#define lttng_ust__get_dynamic_len(field) __stackvar.__dynamic_len[__dynamic_len_idx++] -#undef TP_ARGS -#define TP_ARGS(args...) args +#undef LTTNG_UST_TP_ARGS +#define LTTNG_UST_TP_ARGS(...) __VA_ARGS__ -#undef TP_FIELDS -#define TP_FIELDS(args...) args +#undef LTTNG_UST_TP_FIELDS +#define LTTNG_UST_TP_FIELDS(...) __VA_ARGS__ -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ -static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args))\ +/* + * For state dump, check that "session" argument (mandatory) matches the + * session this event belongs to. Ensures that we write state dump data only + * into the started session, not into all sessions. + */ +#undef LTTNG_UST__TP_SESSION_CHECK +#ifdef LTTNG_UST_TP_SESSION_CHECK +#define LTTNG_UST__TP_SESSION_CHECK(session, csession) (session == csession) +#else /* TP_SESSION_CHECK */ +#define LTTNG_UST__TP_SESSION_CHECK(session, csession) 1 +#endif /* TP_SESSION_CHECK */ + +/* + * Use of __builtin_return_address(0) sometimes seems to cause stack + * corruption on 32-bit PowerPC. Disable this feature on that + * architecture for now by always using the NULL value for the ip + * context. + */ +#undef LTTNG_UST__TP_IP_PARAM + +#ifdef LTTNG_UST_TP_IP_PARAM +#define LTTNG_UST__TP_IP_PARAM(x) (x) +#else /* TP_IP_PARAM */ + +#if defined(LTTNG_UST_ARCH_PPC) && !defined(LTTNG_UST_ARCH_PPC64) +#define LTTNG_UST__TP_IP_PARAM(x) NULL +#else +#define LTTNG_UST__TP_IP_PARAM(x) __builtin_return_address(0) +#endif + +#endif /* TP_IP_PARAM */ + +/* + * Using twice size for filter stack data to hold size and pointer for + * each field (worse case). For integers, max size required is 64-bit. + * Same for double-precision floats. Those fit within + * 2*sizeof(unsigned long) for all supported architectures. + * Perform UNION (||) of filter runtime list. + */ +#undef LTTNG_UST__TRACEPOINT_EVENT_CLASS +#define LTTNG_UST__TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static \ +void lttng_ust__event_probe__##_provider##___##_name(LTTNG_UST__TP_ARGS_DATA_PROTO(_args)) \ + lttng_ust_notrace; \ +static \ +void lttng_ust__event_probe__##_provider##___##_name(LTTNG_UST__TP_ARGS_DATA_PROTO(_args)) \ { \ - struct ltt_event *__event = __tp_data; \ - struct ltt_channel *__chan = __event->chan; \ - struct lttng_ust_lib_ring_buffer_ctx __ctx; \ - size_t __event_len, __event_align; \ + struct lttng_ust_event_common *__event = (struct lttng_ust_event_common *) __tp_data; \ size_t __dynamic_len_idx = 0; \ - size_t __dynamic_len[_TP_ARRAY_SIZE(__event_fields___##_provider##___##_name)]; \ + const size_t __num_fields = LTTNG_UST__TP_ARRAY_SIZE(lttng_ust__event_fields___##_provider##___##_name) - 1; \ + struct lttng_ust_probe_ctx __probe_ctx; \ + union { \ + size_t __dynamic_len[__num_fields]; \ + char __interpreter_stack_data[2 * sizeof(unsigned long) * __num_fields]; \ + } __stackvar; \ int __ret; \ + bool __interpreter_stack_prepared = false; \ \ if (0) \ (void) __dynamic_len_idx; /* don't warn if unused */ \ - if (caa_unlikely(!CMM_ACCESS_ONCE(__chan->session->active))) \ - return; \ - if (caa_unlikely(!CMM_ACCESS_ONCE(__chan->enabled))) \ - return; \ + switch (__event->type) { \ + case LTTNG_UST_EVENT_TYPE_RECORDER: \ + { \ + struct lttng_ust_event_recorder *__event_recorder = (struct lttng_ust_event_recorder *) __event->child; \ + struct lttng_ust_channel_buffer *__chan = __event_recorder->chan; \ + struct lttng_ust_channel_common *__chan_common = __chan->parent; \ + \ + if (!LTTNG_UST__TP_SESSION_CHECK(session, __chan_common->session)) \ + return; \ + if (caa_unlikely(!CMM_ACCESS_ONCE(__chan_common->session->active))) \ + return; \ + if (caa_unlikely(!CMM_ACCESS_ONCE(__chan_common->enabled))) \ + return; \ + break; \ + } \ + case LTTNG_UST_EVENT_TYPE_NOTIFIER: \ + break; \ + } \ if (caa_unlikely(!CMM_ACCESS_ONCE(__event->enabled))) \ return; \ - __event_len = __event_get_size__##_provider##___##_name(__dynamic_len,\ - _TP_ARGS_DATA_VAR(_args)); \ - __event_align = __event_get_align__##_provider##___##_name(_TP_ARGS_VAR(_args)); \ - lib_ring_buffer_ctx_init(&__ctx, __chan->chan, __event, __event_len, \ - __event_align, -1, __chan->handle); \ - __ret = __chan->ops->event_reserve(&__ctx, __event->id); \ - if (__ret < 0) \ + if (caa_unlikely(!LTTNG_UST_TP_RCU_LINK_TEST())) \ return; \ - _fields \ - __chan->ops->event_commit(&__ctx); \ + __probe_ctx.struct_size = sizeof(struct lttng_ust_probe_ctx); \ + __probe_ctx.ip = LTTNG_UST__TP_IP_PARAM(LTTNG_UST_TP_IP_PARAM); \ + if (caa_unlikely(CMM_ACCESS_ONCE(__event->eval_filter))) { \ + lttng_ust__event_prepare_interpreter_stack__##_provider##___##_name(__stackvar.__interpreter_stack_data, \ + LTTNG_UST__TP_ARGS_DATA_VAR(_args)); \ + __interpreter_stack_prepared = true; \ + if (caa_likely(__event->run_filter(__event, \ + __stackvar.__interpreter_stack_data, &__probe_ctx, NULL) != LTTNG_UST_EVENT_FILTER_ACCEPT)) \ + return; \ + } \ + switch (__event->type) { \ + case LTTNG_UST_EVENT_TYPE_RECORDER: \ + { \ + size_t __event_len, __event_align; \ + struct lttng_ust_event_recorder *__event_recorder = (struct lttng_ust_event_recorder *) __event->child; \ + struct lttng_ust_channel_buffer *__chan = __event_recorder->chan; \ + struct lttng_ust_ring_buffer_ctx __ctx; \ + \ + __event_len = lttng_ust__event_get_size__##_provider##___##_name(__stackvar.__dynamic_len, \ + LTTNG_UST__TP_ARGS_DATA_VAR(_args)); \ + __event_align = lttng_ust__event_get_align__##_provider##___##_name(LTTNG_UST__TP_ARGS_VAR(_args)); \ + lttng_ust_ring_buffer_ctx_init(&__ctx, __event_recorder, __event_len, __event_align, \ + &__probe_ctx); \ + __ret = __chan->ops->event_reserve(&__ctx); \ + if (__ret < 0) \ + return; \ + _fields \ + __chan->ops->event_commit(&__ctx); \ + break; \ + } \ + case LTTNG_UST_EVENT_TYPE_NOTIFIER: \ + { \ + struct lttng_ust_event_notifier *__event_notifier = (struct lttng_ust_event_notifier *) __event->child; \ + struct lttng_ust_notification_ctx __notif_ctx; \ + \ + __notif_ctx.struct_size = sizeof(struct lttng_ust_notification_ctx); \ + __notif_ctx.eval_capture = CMM_ACCESS_ONCE(__event_notifier->eval_capture); \ + \ + if (caa_unlikely(!__interpreter_stack_prepared && __notif_ctx.eval_capture)) \ + lttng_ust__event_prepare_interpreter_stack__##_provider##___##_name(__stackvar.__interpreter_stack_data, \ + LTTNG_UST__TP_ARGS_DATA_VAR(_args)); \ + \ + __event_notifier->notification_send(__event_notifier, \ + __stackvar.__interpreter_stack_data, \ + &__probe_ctx, \ + &__notif_ctx); \ + break; \ + } \ + } \ } -#include TRACEPOINT_INCLUDE +#include LTTNG_UST_TRACEPOINT_INCLUDE + +#undef lttng_ust__get_dynamic_len + +/* + * Stage 6 of tracepoint event generation. + * + * Tracepoint loglevel mapping definition generation. We generate a + * symbol for each mapping for a provider/event to ensure at most a 1 to + * 1 mapping between events and loglevels. If the symbol is repeated, + * the compiler will complain. + */ + +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ +#include + +/* + * Declare _loglevel___##__provider##___##__name as non-static, with + * hidden visibility for c++ handling of weakref. We do a weakref to the + * symbol in a later stage, which requires that the symbol is not + * mangled. + */ +#ifdef __cplusplus +#define LTTNG_UST_TP_EXTERN_C extern "C" +#else +#define LTTNG_UST_TP_EXTERN_C +#endif + +#undef LTTNG_UST_TRACEPOINT_LOGLEVEL +#define LTTNG_UST_TRACEPOINT_LOGLEVEL(__provider, __name, __loglevel) \ +static const int _loglevel_value___##__provider##___##__name = __loglevel; \ +LTTNG_UST_TP_EXTERN_C const int * const _loglevel___##__provider##___##__name \ + __attribute__((visibility("hidden"))) = \ + &_loglevel_value___##__provider##___##__name; + +#include LTTNG_UST_TRACEPOINT_INCLUDE + +#undef LTTNG_UST_TP_EXTERN_C + +/* + * Stage 6.1 of tracepoint event generation. + * + * Tracepoint UML URI info. + */ + +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ +#include + +/* + * Declare _model_emf_uri___##__provider##___##__name as non-static, + * with hidden visibility for c++ handling of weakref. We do a weakref + * to the symbol in a later stage, which requires that the symbol is not + * mangled. + */ +#ifdef __cplusplus +#define LTTNG_UST_TP_EXTERN_C extern "C" +#else +#define LTTNG_UST_TP_EXTERN_C +#endif + +#undef LTTNG_UST_TRACEPOINT_MODEL_EMF_URI +#define LTTNG_UST_TRACEPOINT_MODEL_EMF_URI(__provider, __name, __uri) \ +LTTNG_UST_TP_EXTERN_C const char * const _model_emf_uri___##__provider##___##__name \ + __attribute__((visibility("hidden"))) = __uri; \ + +#include LTTNG_UST_TRACEPOINT_INCLUDE + +#undef LTTNG_UST_TP_EXTERN_C + +/* + * Stage 7.0 of tracepoint event generation. + * + * Create events description structures. We use a weakref because + * loglevels are optional. If not declared, the event will point to + * a loglevel that contains NULL. + * + * C++ requires that const objects have a user-declared default + * constructor. However, in both C++ and C, weakref cannot be + * initialized because it causes the weakref attribute to be ignored. + * Therefore, the loglevel and model_emf_uri pointers are not const + * to ensure C++ compilers default-initialize them. + */ + +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ +#include + +#undef LTTNG_UST__TRACEPOINT_EVENT_INSTANCE +#define LTTNG_UST__TRACEPOINT_EVENT_INSTANCE(_template_provider, _template_name, _provider, _name, _args) \ +static const int * \ + __ref_loglevel___##_provider##___##_name \ + __attribute__((weakref ("_loglevel___" #_provider "___" #_name))); \ +static const char * \ + __ref_model_emf_uri___##_provider##___##_name \ + __attribute__((weakref ("_model_emf_uri___" #_provider "___" #_name)));\ +static const struct lttng_ust_event_desc lttng_ust__event_desc___##_provider##_##_name = { \ + .struct_size = sizeof(struct lttng_ust_event_desc), \ + .event_name = #_name, \ + .probe_desc = <tng_ust__probe_desc___##_provider, \ + .tp_class = <tng_ust__event_class___##_template_provider##___##_template_name, \ + .loglevel = &__ref_loglevel___##_provider##___##_name, \ + .model_emf_uri = &__ref_model_emf_uri___##_provider##___##_name, \ +}; + +#include LTTNG_UST_TRACEPOINT_INCLUDE + +/* + * Stage 7.1 of tracepoint event generation. + * + * Create array of events. + */ + +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ +#include + +#undef LTTNG_UST__TRACEPOINT_EVENT_INSTANCE +#define LTTNG_UST__TRACEPOINT_EVENT_INSTANCE(_template_provider, _template_name, _provider, _name, _args) \ + <tng_ust__event_desc___##_provider##_##_name, + +static const struct lttng_ust_event_desc * const LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__provider_event_desc___, LTTNG_UST_TRACEPOINT_PROVIDER)[] = { +#include LTTNG_UST_TRACEPOINT_INCLUDE + NULL, /* Dummy, C99 forbids 0-len array. */ +}; -#undef __get_dynamic_len /* * Stage 8 of tracepoint event generation. * + * Create a toplevel descriptor for the whole probe. + */ + +const struct lttng_ust_probe_desc LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_desc___, LTTNG_UST_TRACEPOINT_PROVIDER) = { + .struct_size = sizeof(struct lttng_ust_probe_desc), + .provider_name = lttng_ust__tp_stringify(LTTNG_UST_TRACEPOINT_PROVIDER), + .event_desc = LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__provider_event_desc___, LTTNG_UST_TRACEPOINT_PROVIDER), + .nr_events = LTTNG_UST__TP_ARRAY_SIZE(LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__provider_event_desc___, LTTNG_UST_TRACEPOINT_PROVIDER)) - 1, + .major = LTTNG_UST_PROVIDER_MAJOR, + .minor = LTTNG_UST_PROVIDER_MINOR, +}; + +static int LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_register_refcount___, LTTNG_UST_TRACEPOINT_PROVIDER); +static struct lttng_ust_registered_probe *LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_register_cookie___, LTTNG_UST_TRACEPOINT_PROVIDER); + +/* + * Stage 9 of tracepoint event generation. + * * Register/unregister probes at module load/unload. + * + * Generate the constructor as an externally visible symbol for use when + * linking the probe statically. + * + * Register refcount is protected by libc dynamic loader mutex. + * + * Note that when building this code as C++, the definition of constructors + * and destructors invoking the registration and unregistration functions + * must be performed _after_ the initialization of the probes. + * + * This is because we rely on the order of initialization of static variables + * and anonymous namespaces (their order of declaration) to ensure probes are + * fully initialized, see + * https://en.cppreference.com/w/cpp/language/initialization. This is especially + * important when LTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP is defined as + * compound literals are then dynamically initialized. */ -/* Reset all macros within TRACEPOINT_EVENT */ +/* Reset all macros within LTTNG_UST_TRACEPOINT_EVENT */ #include -static void __attribute__((constructor)) -_TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void) +static void +LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__events_init__, LTTNG_UST_TRACEPOINT_PROVIDER)(void) lttng_ust_notrace; +static void +LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__events_init__, LTTNG_UST_TRACEPOINT_PROVIDER)(void) { - int ret; + struct lttng_ust_registered_probe *reg_probe; - ret = ltt_probe_register(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); - assert(!ret); + if (LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_register_refcount___, + LTTNG_UST_TRACEPOINT_PROVIDER)++) { + return; + } + /* + * lttng_ust_tracepoint_provider_check_ ## LTTNG_UST_TRACEPOINT_PROVIDER() is a + * static inline function that ensures every probe PROVIDER + * argument match the provider within which they appear. It + * calls empty static inline functions, and therefore has no + * runtime effect. However, if it detects an error, a linker + * error will appear. + */ + LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust_tracepoint_provider_check_, LTTNG_UST_TRACEPOINT_PROVIDER)(); + assert(!LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_register_cookie___, LTTNG_UST_TRACEPOINT_PROVIDER)); + reg_probe = lttng_ust_probe_register(<TNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_desc___, LTTNG_UST_TRACEPOINT_PROVIDER)); + if (!reg_probe) { + fprintf(stderr, "LTTng-UST: Error while registering tracepoint probe.\n"); + abort(); + } + LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_register_cookie___, LTTNG_UST_TRACEPOINT_PROVIDER) = reg_probe; } -static void __attribute__((destructor)) -_TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void) +static void +LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__events_exit__, LTTNG_UST_TRACEPOINT_PROVIDER)(void) lttng_ust_notrace; +static void +LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__events_exit__, LTTNG_UST_TRACEPOINT_PROVIDER)(void) { - ltt_probe_unregister(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); + if (--LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_register_refcount___, + LTTNG_UST_TRACEPOINT_PROVIDER)) { + return; + } + lttng_ust_probe_unregister(LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_register_cookie___, LTTNG_UST_TRACEPOINT_PROVIDER)); + LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__probe_register_cookie___, LTTNG_UST_TRACEPOINT_PROVIDER) = NULL; } + +LTTNG_UST_DECLARE_CONSTRUCTOR_DESTRUCTOR( + LTTNG_UST_TRACEPOINT_PROVIDER, + LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__events_init__, LTTNG_UST_TRACEPOINT_PROVIDER), + LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust__events_exit__, LTTNG_UST_TRACEPOINT_PROVIDER), + lttng_ust_notrace) + +/* + * LTTNG_UST_TRACEPOINT_PROVIDER_HIDDEN_DEFINITION: Define this before + * including a tracepoint instrumentation header to hide symbols + * associated with the tracepoint provider. This is useful if the + * tracepoint definition (including the header after defining + * LTTNG_UST_TRACEPOINT_DEFINE) is in the same module as the provider + * (including the header after defining + * LTTNG_UST_TRACEPOINT_CREATE_PROBES). + */ +#undef LTTNG_UST__TRACEPOINT_PROVIDER_DEFINITION_VISIBILITY +#ifdef LTTNG_UST_TRACEPOINT_PROVIDER_HIDDEN_DEFINITION +#define LTTNG_UST__TRACEPOINT_PROVIDER_DEFINITION_VISIBILITY __attribute__((visibility("hidden"))) +#else +#define LTTNG_UST__TRACEPOINT_PROVIDER_DEFINITION_VISIBILITY __attribute__((visibility("default"))) +#endif + +int LTTNG_UST__TP_COMBINE_TOKENS(lttng_ust_tracepoint_provider_, LTTNG_UST_TRACEPOINT_PROVIDER) + LTTNG_UST__TRACEPOINT_PROVIDER_DEFINITION_VISIBILITY;