X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=include%2Flttng%2Fust-tracepoint-event.h;h=466d6d9f088751ec509bbbc3c9fbfc48aaeb8cf8;hb=c0c0989ab70574e09b2f7e8b48c2da6af664a849;hp=b3fb2d404e6f1785f3382bb5d3d48d462ee4c022;hpb=000b86624a1b4a10fcef3f5b39598f57f2d9d6cd;p=lttng-ust.git diff --git a/include/lttng/ust-tracepoint-event.h b/include/lttng/ust-tracepoint-event.h index b3fb2d40..466d6d9f 100644 --- a/include/lttng/ust-tracepoint-event.h +++ b/include/lttng/ust-tracepoint-event.h @@ -1,39 +1,28 @@ /* - * Copyright (c) 2011-2012 - Mathieu Desnoyers + * SPDX-License-Identifier: MIT * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * Copyright (C) 2011-2012 Mathieu Desnoyers */ +#include #include +#include #include #include #include #include #include #include +#include #include +#define __LTTNG_UST_NULL_STRING "(null)" + #undef tp_list_for_each_entry_rcu #define tp_list_for_each_entry_rcu(pos, head, member) \ - for (pos = cds_list_entry(tp_rcu_dereference_bp((head)->next), __typeof__(*pos), member); \ + for (pos = cds_list_entry(tp_rcu_dereference((head)->next), __typeof__(*pos), member); \ &pos->member != (head); \ - pos = cds_list_entry(tp_rcu_dereference_bp(pos->member.next), __typeof__(*pos), member)) + pos = cds_list_entry(tp_rcu_dereference(pos->member.next), __typeof__(*pos), member)) /* * TRACEPOINT_EVENT_CLASS declares a class of tracepoints receiving the @@ -48,12 +37,20 @@ #undef TRACEPOINT_EVENT #define TRACEPOINT_EVENT(_provider, _name, _args, _fields) \ - TRACEPOINT_EVENT_CLASS(_provider, _name, \ + _TRACEPOINT_EVENT_CLASS(_provider, _name, \ _TP_PARAMS(_args), \ _TP_PARAMS(_fields)) \ - TRACEPOINT_EVENT_INSTANCE(_provider, _name, _name, \ + _TRACEPOINT_EVENT_INSTANCE(_provider, _name, _name, \ _TP_PARAMS(_args)) +#undef TRACEPOINT_EVENT_CLASS +#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ + _TRACEPOINT_EVENT_CLASS(_provider, _name, _TP_PARAMS(_args), _TP_PARAMS(_fields)) + +#undef TRACEPOINT_EVENT_INSTANCE +#define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ + _TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _TP_PARAMS(_args)) + /* Helpers */ #define _TP_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) @@ -74,19 +71,23 @@ /* Reset all macros within TRACEPOINT_EVENT */ #include +static inline lttng_ust_notrace +void _TP_COMBINE_TOKENS(__tracepoint_provider_mismatch_, TRACEPOINT_PROVIDER)(void); static inline void _TP_COMBINE_TOKENS(__tracepoint_provider_mismatch_, TRACEPOINT_PROVIDER)(void) { } -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ __tracepoint_provider_mismatch_##_provider(); -#undef TRACEPOINT_EVENT_INSTANCE -#define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ +#undef _TRACEPOINT_EVENT_INSTANCE +#define _TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ __tracepoint_provider_mismatch_##_provider(); +static inline lttng_ust_notrace +void _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(void); static inline void _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(void) { @@ -103,8 +104,8 @@ void _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(void) /* Reset all macros within TRACEPOINT_EVENT */ #include -#undef TRACEPOINT_EVENT_INSTANCE -#define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ +#undef _TRACEPOINT_EVENT_INSTANCE +#define _TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ static const char \ __tp_name_len_check##_provider##___##_name[LTTNG_UST_SYM_NAME_LEN] \ __attribute__((unused)) = \ @@ -112,6 +113,134 @@ static const char \ #include 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 TRACEPOINT_EVENT */ +#include + +#undef TP_ARGS +#define TP_ARGS(...) __VA_ARGS__ + +#undef _TRACEPOINT_EVENT_INSTANCE +#define _TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ +void __event_template_proto___##_provider##___##_template(_TP_ARGS_DATA_PROTO(_args)); + +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +void __event_template_proto___##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); + +#include TRACEPOINT_INCLUDE + +/* + * Stage 0.9 of tracepoint event generation + * + * Unfolding the enums + */ +#include + +/* Enumeration entry (single value) */ +#undef ctf_enum_value +#define ctf_enum_value(_string, _value) \ + { \ + .start = { \ + .value = lttng_is_signed_type(__typeof__(_value)) ? \ + (long long) (_value) : (_value), \ + .signedness = lttng_is_signed_type(__typeof__(_value)), \ + }, \ + .end = { \ + .value = lttng_is_signed_type(__typeof__(_value)) ? \ + (long long) (_value) : (_value), \ + .signedness = lttng_is_signed_type(__typeof__(_value)), \ + }, \ + .string = (_string), \ + }, + +/* Enumeration entry (range) */ +#undef ctf_enum_range +#define ctf_enum_range(_string, _range_start, _range_end) \ + { \ + .start = { \ + .value = lttng_is_signed_type(__typeof__(_range_start)) ? \ + (long long) (_range_start) : (_range_start), \ + .signedness = lttng_is_signed_type(__typeof__(_range_start)), \ + }, \ + .end = { \ + .value = lttng_is_signed_type(__typeof__(_range_end)) ? \ + (long long) (_range_end) : (_range_end), \ + .signedness = lttng_is_signed_type(__typeof__(_range_end)), \ + }, \ + .string = (_string), \ + }, + +/* Enumeration entry (automatic value; follows the rules of CTF) */ +#undef ctf_enum_auto +#define ctf_enum_auto(_string) \ + { \ + .start = { \ + .value = -1ULL, \ + .signedness = 0, \ + }, \ + .end = { \ + .value = -1ULL, \ + .signedness = 0, \ + }, \ + .string = (_string), \ + .u = { \ + .extra = { \ + .options = LTTNG_ENUM_ENTRY_OPTION_IS_AUTO, \ + }, \ + }, \ + }, + +#undef TP_ENUM_VALUES +#define TP_ENUM_VALUES(...) \ + __VA_ARGS__ + +#undef TRACEPOINT_ENUM +#define TRACEPOINT_ENUM(_provider, _name, _values) \ + const struct lttng_enum_entry __enum_values__##_provider##_##_name[] = { \ + _values \ + ctf_enum_value("", 0) /* Dummy, 0-len array forbidden by C99. */ \ + }; +#include TRACEPOINT_INCLUDE + +/* + * Stage 0.9.1 + * Verifying array and sequence elements are of an integer type. + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#include +#include +#include + +#undef _ctf_array_encoded +#define _ctf_array_encoded(_type, _item, _src, _byte_order, \ + _length, _encoding, _nowrite, \ + _elem_type_base) \ + _lttng_array_element_type_is_supported(_type, _item) + +#undef _ctf_sequence_encoded +#define _ctf_sequence_encoded(_type, _item, _src, _byte_order, \ + _length_type, _src_length, _encoding, _nowrite, \ + _elem_type_base) \ + _lttng_array_element_type_is_supported(_type, _item) + +#undef TP_FIELDS +#define TP_FIELDS(...) __VA_ARGS__ /* Only one used in this phase */ + +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ + _fields + +#include TRACEPOINT_INCLUDE + /* * Stage 1 of tracepoint event generation. * @@ -130,6 +259,11 @@ static const char \ .name = #_item, \ .type = __type_integer(_type, _byte_order, _base, none),\ .nowrite = _nowrite, \ + .u = { \ + .ext = { \ + .nofilter = 0, \ + }, \ + }, \ }, #undef _ctf_float @@ -138,39 +272,77 @@ static const char \ .name = #_item, \ .type = __type_float(_type), \ .nowrite = _nowrite, \ + .u = { \ + .ext = { \ + .nofilter = 0, \ + }, \ + }, \ }, #undef _ctf_array_encoded -#define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \ +#define _ctf_array_encoded(_type, _item, _src, _byte_order, \ + _length, _encoding, _nowrite, \ + _elem_type_base) \ { \ .name = #_item, \ .type = \ { \ - .atype = atype_array, \ - .u.array = \ + .atype = atype_array_nestable, \ + .u = \ { \ - .length = _length, \ - .elem_type = __type_integer(_type, BYTE_ORDER, 10, _encoding), \ - }, \ + .array_nestable = \ + { \ + .elem_type = __LTTNG_COMPOUND_LITERAL(struct lttng_type, \ + __type_integer(_type, _byte_order, _elem_type_base, _encoding)), \ + .length = _length, \ + .alignment = 0, \ + } \ + } \ }, \ .nowrite = _nowrite, \ + .u = { \ + .ext = { \ + .nofilter = 0, \ + }, \ + }, \ }, #undef _ctf_sequence_encoded -#define _ctf_sequence_encoded(_type, _item, _src, \ - _length_type, _src_length, _encoding, _nowrite) \ +#define _ctf_sequence_encoded(_type, _item, _src, _byte_order, \ + _length_type, _src_length, _encoding, _nowrite, \ + _elem_type_base) \ + { \ + .name = "_" #_item "_length", \ + .type = __type_integer(_length_type, BYTE_ORDER, 10, none), \ + .nowrite = _nowrite, \ + .u = { \ + .ext = { \ + .nofilter = 1, \ + }, \ + }, \ + }, \ { \ .name = #_item, \ .type = \ { \ - .atype = atype_sequence, \ - .u.sequence = \ + .atype = atype_sequence_nestable, \ + .u = \ { \ - .length_type = __type_integer(_length_type, BYTE_ORDER, 10, none), \ - .elem_type = __type_integer(_type, BYTE_ORDER, 10, _encoding), \ + .sequence_nestable = \ + { \ + .length_name = "_" #_item "_length", \ + .elem_type = __LTTNG_COMPOUND_LITERAL(struct lttng_type, \ + __type_integer(_type, _byte_order, _elem_type_base, _encoding)), \ + .alignment = 0, \ + }, \ }, \ }, \ .nowrite = _nowrite, \ + .u = { \ + .ext = { \ + .nofilter = 0, \ + }, \ + }, \ }, #undef _ctf_string @@ -180,18 +352,57 @@ static const char \ .type = \ { \ .atype = atype_string, \ - .u.basic.string.encoding = lttng_encode_UTF8, \ + .u = \ + { \ + .string = { .encoding = lttng_encode_UTF8 } \ + }, \ }, \ .nowrite = _nowrite, \ + .u = { \ + .ext = { \ + .nofilter = 0, \ + }, \ + }, \ + }, + +#undef _ctf_enum +#define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \ + { \ + .name = #_item, \ + .type = { \ + .atype = atype_enum_nestable, \ + .u = { \ + .enum_nestable = { \ + .desc = &__enum_##_provider##_##_name, \ + .container_type = __LTTNG_COMPOUND_LITERAL(struct lttng_type, \ + __type_integer(_type, BYTE_ORDER, 10, none)), \ + }, \ + }, \ + }, \ + .nowrite = _nowrite, \ + .u = { \ + .ext = { \ + .nofilter = 0, \ + }, \ + }, \ }, #undef TP_FIELDS #define TP_FIELDS(...) __VA_ARGS__ /* Only one used in this phase */ -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ static const struct lttng_event_field __event_fields___##_provider##___##_name[] = { \ _fields \ + ctf_integer(int, dummy, 0) /* Dummy, C99 forbids 0-len array. */ \ + }; + +#undef TRACEPOINT_ENUM +#define TRACEPOINT_ENUM(_provider, _name, _values) \ + static const struct lttng_enum_desc __enum_##_provider##_##_name = { \ + .name = #_provider "_" #_name, \ + .entries = __enum_values__##_provider##_##_name, \ + .nr_entries = _TP_ARRAY_SIZE(__enum_values__##_provider##_##_name) - 1, \ }; #include TRACEPOINT_INCLUDE @@ -208,14 +419,32 @@ static const char \ #undef TP_ARGS #define TP_ARGS(...) __VA_ARGS__ -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); #include TRACEPOINT_INCLUDE /* - * Stage 3 of tracepoint event generation. + * Stage 2.1 of tracepoint event generation. + * + * Create probe event notifier callback prototypes. + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#include + +#undef TP_ARGS +#define TP_ARGS(...) __VA_ARGS__ + +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static void __event_notifier_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); + +#include TRACEPOINT_INCLUDE + +/* + * Stage 3.0 of tracepoint event generation. * * Create static inline function that calculates event size. */ @@ -235,13 +464,14 @@ static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); __event_len += sizeof(_type); #undef _ctf_array_encoded -#define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \ +#define _ctf_array_encoded(_type, _item, _src, _byte_order, _length, _encoding, \ + _nowrite, _elem_type_base) \ __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ __event_len += sizeof(_type) * (_length); #undef _ctf_sequence_encoded -#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \ - _src_length, _encoding, _nowrite) \ +#define _ctf_sequence_encoded(_type, _item, _src, _byte_order, _length_type, \ + _src_length, _encoding, _nowrite, _elem_type_base) \ __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_length_type)); \ __event_len += sizeof(_length_type); \ __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ @@ -251,7 +481,12 @@ static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); #undef _ctf_string #define _ctf_string(_item, _src, _nowrite) \ - __event_len += __dynamic_len[__dynamic_len_idx++] = strlen(_src) + 1; + __event_len += __dynamic_len[__dynamic_len_idx++] = \ + strlen((_src) ? (_src) : __LTTNG_UST_NULL_STRING) + 1; + +#undef _ctf_enum +#define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \ + _ctf_integer_ext(_type, _item, _src, BYTE_ORDER, 10, _nowrite) #undef TP_ARGS #define TP_ARGS(...) __VA_ARGS__ @@ -259,8 +494,8 @@ static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); #undef TP_FIELDS #define TP_FIELDS(...) __VA_ARGS__ -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ static inline lttng_ust_notrace \ size_t __event_get_size__##_provider##___##_name(size_t *__dynamic_len, _TP_ARGS_DATA_PROTO(_args)); \ static inline \ @@ -292,10 +527,78 @@ size_t __event_get_size__##_provider##___##_name(size_t *__dynamic_len, _TP_ARGS #undef _ctf_integer_ext #define _ctf_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \ if (lttng_is_signed_type(_type)) { \ - int64_t __ctf_tmp_int64 = (int64_t) (_type) (_src); \ + 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 != BYTE_ORDER) \ + __tmp.v = 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 != BYTE_ORDER) \ + __tmp.v = 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 != BYTE_ORDER) \ + __tmp.v = 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 = (uint64_t) (_type) (_src); \ + 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 != BYTE_ORDER) \ + __tmp.v = 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 != BYTE_ORDER) \ + __tmp.v = 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 != BYTE_ORDER) \ + __tmp.v = 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); @@ -309,46 +612,52 @@ size_t __event_get_size__##_provider##___##_name(size_t *__dynamic_len, _TP_ARGS } #undef _ctf_array_encoded -#define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \ +#define _ctf_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 **); \ + memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \ + __stack_data += sizeof(void *); \ } #undef _ctf_sequence_encoded -#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \ - _src_length, _encoding, _nowrite) \ +#define _ctf_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 **); \ + memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void *)); \ + __stack_data += sizeof(void *); \ } #undef _ctf_string #define _ctf_string(_item, _src, _nowrite) \ { \ - const void *__ctf_tmp_ptr = (_src); \ - memcpy(__stack_data, &__ctf_tmp_ptr, sizeof(void **)); \ - __stack_data += sizeof(void **); \ + 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_enum +#define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \ + _ctf_integer_ext(_type, _item, _src, BYTE_ORDER, 10, _nowrite) + #undef TP_ARGS #define TP_ARGS(...) __VA_ARGS__ #undef TP_FIELDS #define TP_FIELDS(...) __VA_ARGS__ -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ static inline \ -void __event_prepare_filter_stack__##_provider##___##_name(char *__stack_data,\ +void __event_prepare_interpreter_stack__##_provider##___##_name(char *__stack_data,\ _TP_ARGS_DATA_PROTO(_args)) \ { \ _fields \ @@ -356,8 +665,6 @@ void __event_prepare_filter_stack__##_provider##___##_name(char *__stack_data,\ #include TRACEPOINT_INCLUDE - - /* * Stage 4 of tracepoint event generation. * @@ -377,26 +684,31 @@ void __event_prepare_filter_stack__##_provider##___##_name(char *__stack_data,\ __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type)); #undef _ctf_array_encoded -#define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \ +#define _ctf_array_encoded(_type, _item, _src, _byte_order, _length, \ + _encoding, _nowrite, _elem_type_base) \ __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type)); #undef _ctf_sequence_encoded -#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \ - _src_length, _encoding, _nowrite) \ +#define _ctf_sequence_encoded(_type, _item, _src, _byte_order, _length_type, \ + _src_length, _encoding, _nowrite, _elem_type_base) \ __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 _ctf_string #define _ctf_string(_item, _src, _nowrite) +#undef _ctf_enum +#define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \ + _ctf_integer_ext(_type, _item, _src, BYTE_ORDER, 10, _nowrite) + #undef TP_ARGS #define TP_ARGS(...) __VA_ARGS__ #undef TP_FIELDS #define TP_FIELDS(...) __VA_ARGS__ -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ static inline lttng_ust_notrace \ size_t __event_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args)); \ static inline \ @@ -438,13 +750,14 @@ size_t __event_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args)) \ } #undef _ctf_array_encoded -#define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \ +#define _ctf_array_encoded(_type, _item, _src, _byte_order, _length, \ + _encoding, _nowrite, _elem_type_base) \ 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, _nowrite) \ +#define _ctf_sequence_encoded(_type, _item, _src, _byte_order, _length_type, \ + _src_length, _encoding, _nowrite, _elem_type_base) \ { \ _length_type __tmpl = __stackvar.__dynamic_len[__dynamic_len_idx]; \ lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\ @@ -456,8 +769,19 @@ size_t __event_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args)) \ #undef _ctf_string #define _ctf_string(_item, _src, _nowrite) \ - lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(*(_src))); \ - __chan->ops->event_write(&__ctx, _src, __get_dynamic_len(dest)); + { \ + const char *__ctf_tmp_string = \ + ((_src) ? (_src) : __LTTNG_UST_NULL_STRING); \ + lib_ring_buffer_align_ctx(&__ctx, \ + lttng_alignof(*__ctf_tmp_string)); \ + __chan->ops->event_strcpy(&__ctx, __ctf_tmp_string, \ + __get_dynamic_len(dest)); \ + } + + +#undef _ctf_enum +#define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \ + _ctf_integer_ext(_type, _item, _src, BYTE_ORDER, 10, _nowrite) /* Beware: this get len actually consumes the len value */ #undef __get_dynamic_len @@ -469,6 +793,37 @@ size_t __event_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args)) \ #undef TP_FIELDS #define TP_FIELDS(...) __VA_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 _TP_SESSION_CHECK +#ifdef TP_SESSION_CHECK +#define _TP_SESSION_CHECK(session, csession) (session == csession) +#else /* TP_SESSION_CHECK */ +#define _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 _TP_IP_PARAM +#ifdef TP_IP_PARAM +#define _TP_IP_PARAM(x) (x) +#else /* TP_IP_PARAM */ + +#if defined(__PPC__) && !defined(__PPC64__) +#define _TP_IP_PARAM(x) NULL +#else /* #if defined(__PPC__) && !defined(__PPC64__) */ +#define _TP_IP_PARAM(x) __builtin_return_address(0) +#endif /* #else #if defined(__PPC__) && !defined(__PPC64__) */ + +#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. @@ -476,42 +831,50 @@ size_t __event_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args)) \ * 2*sizeof(unsigned long) for all supported architectures. * Perform UNION (||) of filter runtime list. */ -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ static lttng_ust_notrace \ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); \ static \ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \ { \ - struct lttng_event *__event = __tp_data; \ + struct lttng_event *__event = (struct lttng_event *) __tp_data; \ struct lttng_channel *__chan = __event->chan; \ struct lttng_ust_lib_ring_buffer_ctx __ctx; \ + struct lttng_stack_ctx __lttng_ctx; \ size_t __event_len, __event_align; \ size_t __dynamic_len_idx = 0; \ + const size_t __num_fields = _TP_ARRAY_SIZE(__event_fields___##_provider##___##_name) - 1; \ union { \ - size_t __dynamic_len[_TP_ARRAY_SIZE(__event_fields___##_provider##___##_name)]; \ - char __filter_stack_data[2 * sizeof(unsigned long) * _TP_ARRAY_SIZE(__event_fields___##_provider##___##_name)]; \ + size_t __dynamic_len[__num_fields]; \ + char __filter_stack_data[2 * sizeof(unsigned long) * __num_fields]; \ } __stackvar; \ int __ret; \ \ if (0) \ (void) __dynamic_len_idx; /* don't warn if unused */ \ + if (!_TP_SESSION_CHECK(session, __chan->session)) \ + return; \ if (caa_unlikely(!CMM_ACCESS_ONCE(__chan->session->active))) \ return; \ if (caa_unlikely(!CMM_ACCESS_ONCE(__chan->enabled))) \ return; \ if (caa_unlikely(!CMM_ACCESS_ONCE(__event->enabled))) \ return; \ - if (caa_unlikely(!cds_list_empty(&__event->bytecode_runtime_head))) { \ - struct lttng_bytecode_runtime *bc_runtime; \ + if (caa_unlikely(!TP_RCU_LINK_TEST())) \ + return; \ + if (caa_unlikely(!cds_list_empty(&__event->filter_bytecode_runtime_head))) { \ + struct lttng_bytecode_runtime *__filter_bc_runtime; \ int __filter_record = __event->has_enablers_without_bytecode; \ \ - __event_prepare_filter_stack__##_provider##___##_name(__stackvar.__filter_stack_data, \ + __event_prepare_interpreter_stack__##_provider##___##_name(__stackvar.__filter_stack_data, \ _TP_ARGS_DATA_VAR(_args)); \ - tp_list_for_each_entry_rcu(bc_runtime, &__event->bytecode_runtime_head, node) { \ - if (caa_unlikely(bc_runtime->filter(bc_runtime, \ - __stackvar.__filter_stack_data) & LTTNG_FILTER_RECORD_FLAG)) \ + tp_list_for_each_entry_rcu(__filter_bc_runtime, &__event->filter_bytecode_runtime_head, node) { \ + if (caa_unlikely(__filter_bc_runtime->interpreter_funcs.filter(__filter_bc_runtime, \ + __stackvar.__filter_stack_data) & LTTNG_INTERPRETER_RECORD_FLAG)) { \ __filter_record = 1; \ + break; \ + } \ } \ if (caa_likely(!__filter_record)) \ return; \ @@ -519,8 +882,13 @@ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \ __event_len = __event_get_size__##_provider##___##_name(__stackvar.__dynamic_len, \ _TP_ARGS_DATA_VAR(_args)); \ __event_align = __event_get_align__##_provider##___##_name(_TP_ARGS_VAR(_args)); \ + memset(&__lttng_ctx, 0, sizeof(__lttng_ctx)); \ + __lttng_ctx.event = __event; \ + __lttng_ctx.chan_ctx = tp_rcu_dereference(__chan->ctx); \ + __lttng_ctx.event_ctx = tp_rcu_dereference(__event->ctx); \ lib_ring_buffer_ctx_init(&__ctx, __chan->chan, __event, __event_len, \ - __event_align, -1, __chan->handle); \ + __event_align, -1, __chan->handle, &__lttng_ctx); \ + __ctx.ip = _TP_IP_PARAM(TP_IP_PARAM); \ __ret = __chan->ops->event_reserve(&__ctx, __event->id); \ if (__ret < 0) \ return; \ @@ -546,15 +914,62 @@ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \ #define _TP_EXTRACT_STRING2(...) #__VA_ARGS__ -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ -const char __tp_event_signature___##_provider##___##_name[] = \ +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static const char __tp_event_signature___##_provider##___##_name[] = \ _TP_EXTRACT_STRING2(_args); #include TRACEPOINT_INCLUDE #undef _TP_EXTRACT_STRING2 +/* + * Stage 5.2 of tracepoint event generation. + * + * Create the event notifier probe function. + */ +#undef _TRACEPOINT_EVENT_CLASS +#define _TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static lttng_ust_notrace \ +void __event_notifier_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); \ +static \ +void __event_notifier_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \ +{ \ + struct lttng_event_notifier *__event_notifier = (struct lttng_event_notifier *) __tp_data; \ + const size_t __num_fields = _TP_ARRAY_SIZE(__event_fields___##_provider##___##_name) - 1;\ + union { \ + size_t __dynamic_len[__num_fields]; \ + char __interpreter_stack_data[2 * sizeof(unsigned long) * __num_fields]; \ + } __stackvar; \ + \ + if (caa_unlikely(!CMM_ACCESS_ONCE(__event_notifier->enabled))) \ + return; \ + if (caa_unlikely(!TP_RCU_LINK_TEST())) \ + return; \ + if (caa_unlikely(!cds_list_empty(&__event_notifier->filter_bytecode_runtime_head))) { \ + struct lttng_bytecode_runtime *__filter_bc_runtime; \ + int __filter_record = __event_notifier->has_enablers_without_bytecode; \ + \ + __event_prepare_interpreter_stack__##_provider##___##_name(__stackvar.__interpreter_stack_data, \ + _TP_ARGS_DATA_VAR(_args)); \ + tp_list_for_each_entry_rcu(__filter_bc_runtime, &__event_notifier->filter_bytecode_runtime_head, node) { \ + if (caa_unlikely(__filter_bc_runtime->interpreter_funcs.filter(__filter_bc_runtime, \ + __stackvar.__interpreter_stack_data) & LTTNG_INTERPRETER_RECORD_FLAG)) \ + __filter_record = 1; \ + } \ + if (caa_likely(!__filter_record)) \ + return; \ + } \ + if (caa_unlikely(!cds_list_empty(&__event_notifier->capture_bytecode_runtime_head))) \ + __event_prepare_interpreter_stack__##_provider##___##_name(__stackvar.__interpreter_stack_data, \ + _TP_ARGS_DATA_VAR(_args)); \ + \ + __event_notifier->notification_send(__event_notifier, \ + __stackvar.__interpreter_stack_data); \ +} + +#include TRACEPOINT_INCLUDE + /* * Stage 6 of tracepoint event generation. * @@ -567,14 +982,29 @@ const char __tp_event_signature___##_provider##___##_name[] = \ /* Reset all macros within 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_TP_EXTERN_C extern "C" +#else +#define LTTNG_TP_EXTERN_C +#endif + #undef TRACEPOINT_LOGLEVEL #define TRACEPOINT_LOGLEVEL(__provider, __name, __loglevel) \ static const int _loglevel_value___##__provider##___##__name = __loglevel; \ -static const int *_loglevel___##__provider##___##__name = \ +LTTNG_TP_EXTERN_C const int *_loglevel___##__provider##___##__name \ + __attribute__((visibility("hidden"))) = \ &_loglevel_value___##__provider##___##__name; #include TRACEPOINT_INCLUDE +#undef LTTNG_TP_EXTERN_C + /* * Stage 6.1 of tracepoint event generation. * @@ -584,12 +1014,27 @@ static const int *_loglevel___##__provider##___##__name = \ /* Reset all macros within 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_TP_EXTERN_C extern "C" +#else +#define LTTNG_TP_EXTERN_C +#endif + #undef TRACEPOINT_MODEL_EMF_URI #define TRACEPOINT_MODEL_EMF_URI(__provider, __name, __uri) \ -static const char *_model_emf_uri___##__provider##___##__name = __uri; +LTTNG_TP_EXTERN_C const char *_model_emf_uri___##__provider##___##__name \ + __attribute__((visibility("hidden"))) = __uri; \ #include TRACEPOINT_INCLUDE +#undef LTTNG_TP_EXTERN_C + /* * Stage 7.1 of tracepoint event generation. * @@ -601,22 +1046,28 @@ static const char *_model_emf_uri___##__provider##___##__name = __uri; /* Reset all macros within TRACEPOINT_EVENT */ #include -#undef TRACEPOINT_EVENT_INSTANCE -#define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ +#undef _TRACEPOINT_EVENT_INSTANCE +#define _TRACEPOINT_EVENT_INSTANCE(_provider, _template, _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)));\ -const struct lttng_event_desc __event_desc___##_provider##_##_name = { \ - .fields = __event_fields___##_provider##___##_template, \ +static const struct lttng_event_desc __event_desc___##_provider##_##_name = { \ .name = #_provider ":" #_name, \ .probe_callback = (void (*)(void)) &__event_probe__##_provider##___##_template,\ - .nr_fields = _TP_ARRAY_SIZE(__event_fields___##_provider##___##_template), \ + .ctx = NULL, \ + .fields = __event_fields___##_provider##___##_template, \ + .nr_fields = _TP_ARRAY_SIZE(__event_fields___##_provider##___##_template) - 1, \ .loglevel = &__ref_loglevel___##_provider##___##_name, \ .signature = __tp_event_signature___##_provider##___##_template, \ - .u.ext.model_emf_uri = &__ref_model_emf_uri___##_provider##___##_name, \ + .u = { \ + .ext = { \ + .model_emf_uri = &__ref_model_emf_uri___##_provider##___##_name, \ + .event_notifier_callback = (void (*)(void)) &__event_notifier_probe__##_provider##___##_template,\ + }, \ + }, \ }; #include TRACEPOINT_INCLUDE @@ -630,12 +1081,13 @@ const struct lttng_event_desc __event_desc___##_provider##_##_name = { \ /* Reset all macros within TRACEPOINT_EVENT */ #include -#undef TRACEPOINT_EVENT_INSTANCE -#define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ +#undef _TRACEPOINT_EVENT_INSTANCE +#define _TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ &__event_desc___##_provider##_##_name, static const struct lttng_event_desc *_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)[] = { #include TRACEPOINT_INCLUDE + NULL, /* Dummy, C99 forbids 0-len array. */ }; @@ -649,9 +1101,16 @@ static const struct lttng_event_desc *_TP_COMBINE_TOKENS(__event_desc___, TRACEP static struct lttng_probe_desc _TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER) = { .provider = __tp_stringify(TRACEPOINT_PROVIDER), .event_desc = _TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER), - .nr_events = _TP_ARRAY_SIZE(_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)), + .nr_events = _TP_ARRAY_SIZE(_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)) - 1, + .head = { NULL, NULL }, + .lazy_init_head = { NULL, NULL }, + .lazy = 0, + .major = LTTNG_UST_PROVIDER_MAJOR, + .minor = LTTNG_UST_PROVIDER_MINOR, }; +static int _TP_COMBINE_TOKENS(__probe_register_refcount___, TRACEPOINT_PROVIDER); + /* * Stage 9 of tracepoint event generation. * @@ -659,6 +1118,8 @@ static struct lttng_probe_desc _TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PR * * Generate the constructor as an externally visible symbol for use when * linking the probe statically. + * + * Register refcount is protected by libc dynamic loader mutex. */ /* Reset all macros within TRACEPOINT_EVENT */ @@ -670,6 +1131,10 @@ _TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void) { int ret; + if (_TP_COMBINE_TOKENS(__probe_register_refcount___, + TRACEPOINT_PROVIDER)++) { + return; + } /* * __tracepoint_provider_check_ ## TRACEPOINT_PROVIDER() is a * static inline function that ensures every probe PROVIDER @@ -680,7 +1145,10 @@ _TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void) */ _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(); ret = lttng_probe_register(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); - assert(!ret); + if (ret) { + fprintf(stderr, "LTTng-UST: Error (%d) while registering tracepoint probe.\n", ret); + abort(); + } } static void lttng_ust_notrace __attribute__((destructor)) @@ -688,7 +1156,12 @@ _TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void); static void _TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void) { + if (--_TP_COMBINE_TOKENS(__probe_register_refcount___, + TRACEPOINT_PROVIDER)) { + return; + } lttng_probe_unregister(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); } -int _TP_COMBINE_TOKENS(__tracepoint_provider_, TRACEPOINT_PROVIDER); +int _TP_COMBINE_TOKENS(__tracepoint_provider_, TRACEPOINT_PROVIDER) +__attribute__((visibility("default")));