X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=include%2Flttng%2Fust-tracepoint-event.h;h=8f804d62432eace7d5be6fe8811e017e9b524b3c;hb=a5930599a9975ea65fc5435d7c58cd059b867057;hp=90e58e09319674ddd62b82d1c44e4bb516b9d216;hpb=7083f0fecaa692b819e63f484daf38399f58c905;p=lttng-ust.git diff --git a/include/lttng/ust-tracepoint-event.h b/include/lttng/ust-tracepoint-event.h index 90e58e09..8f804d62 100644 --- a/include/lttng/ust-tracepoint-event.h +++ b/include/lttng/ust-tracepoint-event.h @@ -1,108 +1,104 @@ /* - * Copyright (C) 2009 Steven Rostedt - * Copyright (C) 2011 Mathieu Desnoyers + * Copyright (c) 2011-2012 - Mathieu Desnoyers * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License. + * 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: * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. */ #include #include +#include #include -#include #include +#include +#include /* - * Macro declarations used for all stages. + * 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 + * its own provider and name. It refers to a class (template). + * + * TRACEPOINT_EVENT declared both a class and an instance and does a + * direct mapping from the instance to the class. */ -#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 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 ctf_integer_network -#define ctf_integer_network(_type, _item, _src) \ - ctf_integer_ext(_type, _item, _src, BIG_ENDIAN, 10) +/* Helpers */ +#define _TP_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) -#undef ctf_integer_network_hex -#define ctf_integer_network_hex(_type, _item, _src) \ - ctf_integer_ext(_type, _item, _src, BIG_ENDIAN, 16) +#define _tp_max_t(type, x, y) \ + ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1: __max2; \ + }) -/* ctf_float is redefined at each step */ +/* + * Stage 0 of tracepoint event generation. + * + * Check that each TRACEPOINT_EVENT provider argument match the + * TRACEPOINT_PROVIDER by creating dummy callbacks. + */ -#undef ctf_array -#define ctf_array(_type, _item, _src, _length) \ - ctf_array_encoded(_type, _item, _src, _length, none) +/* Reset all macros within TRACEPOINT_EVENT */ +#include -#undef ctf_array_text -#define ctf_array_text(_type, _item, _src, _length) \ - ctf_array_encoded(_type, _item, _src, _length, UTF8) +static inline +void _TP_COMBINE_TOKENS(__tracepoint_provider_mismatch_, TRACEPOINT_PROVIDER)(void) +{ +} -#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 TRACEPOINT_EVENT_CLASS +#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ + __tracepoint_provider_mismatch_##_provider(); -#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) +#undef TRACEPOINT_EVENT_INSTANCE +#define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args) \ + __tracepoint_provider_mismatch_##_provider(); -/* ctf_string is redefined at each step */ +static __attribute__((unused)) +void _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(void) +{ +#include TRACEPOINT_INCLUDE +} /* - * TRACEPOINT_EVENT_CLASS can be used to add a generic function handlers - * for events. That is, if all events have the same parameters and just - * have distinct trace points. Each tracepoint can be defined with - * TRACEPOINT_EVENT_INSTANCE and that will map the - * TRACEPOINT_EVENT_CLASS to the tracepoint. + * Stage 0.1 of tracepoint event generation. * - * TRACEPOINT_EVENT is a one to one mapping between tracepoint and - * template. + * Check that each TRACEPOINT_EVENT provider:name does not exceed the + * tracepoint name length limit. */ -#undef TRACEPOINT_EVENT -#define TRACEPOINT_EVENT(provider, name, proto, args, fields) \ - TRACEPOINT_EVENT_CLASS(provider, name, \ - TP_PARAMS(proto), \ - TP_PARAMS(args), \ - TP_PARAMS(fields)) \ - TRACEPOINT_EVENT_INSTANCE(provider, name, name, TP_PARAMS(proto), TP_PARAMS(args)) - -#undef TRACEPOINT_EVENT_NOARGS -#define TRACEPOINT_EVENT_NOARGS(provider, name, fields) \ - TRACEPOINT_EVENT_CLASS_NOARGS(provider, name, \ - TP_PARAMS(fields)) \ - TRACEPOINT_EVENT_INSTANCE_NOARGS(provider, name, name) - -/* Helpers */ -#define _TP_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) +/* Reset all macros within TRACEPOINT_EVENT */ +#include -#define _tp_max_t(type, x, y) \ - ({ \ - type __max1 = (x); \ - type __max2 = (y); \ - __max1 > __max2 ? __max1: __max2; \ - }) +#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)) = \ + #_provider ":" #_name; +#include TRACEPOINT_INCLUDE /* - * Stage 1 of the trace events. + * Stage 1 of tracepoint event generation. * * Create event field type metadata section. * Each event produce an array of fields. @@ -110,23 +106,27 @@ /* Reset all macros within TRACEPOINT_EVENT */ #include +#include +#include -#undef ctf_integer_ext -#define ctf_integer_ext(_type, _item, _src, _byte_order, _base) \ +#undef _ctf_integer_ext +#define _ctf_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \ { \ .name = #_item, \ .type = __type_integer(_type, _byte_order, _base, none),\ + .nowrite = _nowrite, \ }, -#undef ctf_float -#define ctf_float(_type, _item, _src) \ +#undef _ctf_float +#define _ctf_float(_type, _item, _src, _nowrite) \ { \ .name = #_item, \ .type = __type_float(_type), \ + .nowrite = _nowrite, \ }, -#undef ctf_array_encoded -#define ctf_array_encoded(_type, _item, _src, _length, _encoding) \ +#undef _ctf_array_encoded +#define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \ { \ .name = #_item, \ .type = \ @@ -138,11 +138,12 @@ .elem_type = __type_integer(_type, BYTE_ORDER, 10, _encoding), \ }, \ }, \ + .nowrite = _nowrite, \ }, -#undef ctf_sequence_encoded -#define ctf_sequence_encoded(_type, _item, _src, \ - _length_type, _src_length, _encoding) \ +#undef _ctf_sequence_encoded +#define _ctf_sequence_encoded(_type, _item, _src, \ + _length_type, _src_length, _encoding, _nowrite) \ { \ .name = #_item, \ .type = \ @@ -154,10 +155,11 @@ .elem_type = __type_integer(_type, BYTE_ORDER, 10, _encoding), \ }, \ }, \ + .nowrite = _nowrite, \ }, -#undef ctf_string -#define ctf_string(_item, _src) \ +#undef _ctf_string +#define _ctf_string(_item, _src, _nowrite) \ { \ .name = #_item, \ .type = \ @@ -165,25 +167,22 @@ .atype = atype_string, \ .u.basic.string.encoding = lttng_encode_UTF8, \ }, \ + .nowrite = _nowrite, \ }, #undef TP_FIELDS -#define TP_FIELDS(args...) args /* Only one used in this phase */ +#define TP_FIELDS(...) __VA_ARGS__ /* Only one used in this phase */ -#undef TRACEPOINT_EVENT_CLASS_NOARGS -#define TRACEPOINT_EVENT_CLASS_NOARGS(_provider, _name, _fields) \ +#undef TRACEPOINT_EVENT_CLASS +#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ static const struct lttng_event_field __event_fields___##_provider##___##_name[] = { \ - _fields \ + _fields \ }; -#undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _proto, _args, _fields) \ - TRACEPOINT_EVENT_CLASS_NOARGS(_provider, _name, TP_PARAMS(_fields)) - -#include TRACEPOINT_INCLUDE(TRACEPOINT_INCLUDE_FILE) +#include TRACEPOINT_INCLUDE /* - * Stage 2 of the trace events. + * Stage 2 of tracepoint event generation. * * Create probe callback prototypes. */ @@ -191,97 +190,43 @@ /* Reset all macros within TRACEPOINT_EVENT */ #include -#undef TP_PROTO -#define TP_PROTO(args...) args +#undef TP_ARGS +#define TP_ARGS(...) __VA_ARGS__ #undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _proto, _args, _fields) \ -static void __event_probe__##_provider##___##_name(void *__data, _proto); +#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); -#undef TRACEPOINT_EVENT_CLASS_NOARGS -#define TRACEPOINT_EVENT_CLASS_NOARGS(_provider, _name, _fields) \ -static void __event_probe__##_provider##___##_name(void *__data); - -#include TRACEPOINT_INCLUDE(TRACEPOINT_INCLUDE_FILE) +#include TRACEPOINT_INCLUDE /* - * Stage 3 of the trace events. - * - * Create an array of events. - */ - -/* Reset all macros within TRACEPOINT_EVENT */ -#include - -#undef TRACEPOINT_EVENT_INSTANCE_NOARGS -#define TRACEPOINT_EVENT_INSTANCE_NOARGS(_provider, _template, _name) \ - { \ - .fields = __event_fields___##_provider##___##_template,\ - .name = #_provider ":" #_name, \ - .probe_callback = (void *) &__event_probe__##_provider##___##_template,\ - .nr_fields = _TP_ARRAY_SIZE(__event_fields___##_provider##___##_template), \ - }, - -#undef TRACEPOINT_EVENT_INSTANCE -#define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _proto, _args) \ - TRACEPOINT_EVENT_INSTANCE_NOARGS(_provider, _template, _name) - -#define TP_ID1(_token, _system) _token##_system -#define TP_ID(_token, _system) TP_ID1(_token, _system) - -static const struct lttng_event_desc TP_ID(__event_desc___, TRACEPOINT_SYSTEM)[] = { -#include TRACEPOINT_INCLUDE(TRACEPOINT_INCLUDE_FILE) -}; - -#undef TP_ID1 -#undef TP_ID - - -/* - * Stage 4 of the trace events. - * - * Create a toplevel descriptor for the whole probe. - */ - -#define TP_ID1(_token, _system) _token##_system -#define TP_ID(_token, _system) TP_ID1(_token, _system) - -/* non-const because list head will be modified when registered. */ -static struct lttng_probe_desc TP_ID(__probe_desc___, TRACEPOINT_SYSTEM) = { - .event_desc = TP_ID(__event_desc___, TRACEPOINT_SYSTEM), - .nr_events = _TP_ARRAY_SIZE(TP_ID(__event_desc___, TRACEPOINT_SYSTEM)), -}; - -#undef TP_ID1 -#undef TP_ID - -/* - * Stage 5 of the trace events. + * Stage 3 of tracepoint event generation. * * Create static inline function that calculates event size. */ /* Reset all macros within TRACEPOINT_EVENT */ #include +#include -#undef ctf_integer_ext -#define ctf_integer_ext(_type, _item, _src, _byte_order, _base) \ +#undef _ctf_integer_ext +#define _ctf_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \ __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ __event_len += sizeof(_type); -#undef ctf_float -#define ctf_float(_type, _item, _src) \ +#undef _ctf_float +#define _ctf_float(_type, _item, _src, _nowrite) \ __event_len += lib_ring_buffer_align(__event_len, lttng_alignof(_type)); \ __event_len += sizeof(_type); -#undef ctf_array_encoded -#define ctf_array_encoded(_type, _item, _src, _length, _encoding) \ +#undef _ctf_array_encoded +#define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \ __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) \ +#undef _ctf_sequence_encoded +#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \ + _src_length, _encoding, _nowrite) \ __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)); \ @@ -289,19 +234,22 @@ static struct lttng_probe_desc TP_ID(__probe_desc___, TRACEPOINT_SYSTEM) = { __event_len += sizeof(_type) * __dynamic_len[__dynamic_len_idx]; \ __dynamic_len_idx++; -#undef ctf_string -#define ctf_string(_item, _src) \ +#undef _ctf_string +#define _ctf_string(_item, _src, _nowrite) \ __event_len += __dynamic_len[__dynamic_len_idx++] = strlen(_src) + 1; -#undef TP_PROTO -#define TP_PROTO(args...) args +#undef TP_ARGS +#define TP_ARGS(...) __VA_ARGS__ #undef TP_FIELDS -#define TP_FIELDS(args...) args +#define TP_FIELDS(...) __VA_ARGS__ #undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _proto, _args, _fields) \ -static inline size_t __event_get_size__##_provider##___##_name(size_t *__dynamic_len, _proto) \ +#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 \ +size_t __event_get_size__##_provider##___##_name(size_t *__dynamic_len, _TP_ARGS_DATA_PROTO(_args)) \ { \ size_t __event_len = 0; \ unsigned int __dynamic_len_idx = 0; \ @@ -312,96 +260,178 @@ static inline size_t __event_get_size__##_provider##___##_name(size_t *__dynamic return __event_len; \ } -#include TRACEPOINT_INCLUDE(TRACEPOINT_INCLUDE_FILE) +#include TRACEPOINT_INCLUDE /* - * Stage 6 of the trace events. + * Stage 3.1 of tracepoint event generation. + * + * 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 */ +#include +#include +#include + +#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); \ + memcpy(__stack_data, &__ctf_tmp_int64, sizeof(int64_t)); \ + } else { \ + uint64_t __ctf_tmp_uint64 = (uint64_t) (_type) (_src); \ + memcpy(__stack_data, &__ctf_tmp_uint64, sizeof(uint64_t)); \ + } \ + __stack_data += sizeof(int64_t); + +#undef _ctf_float +#define _ctf_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 _ctf_array_encoded +#define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \ + { \ + 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 _ctf_sequence_encoded +#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \ + _src_length, _encoding, _nowrite) \ + { \ + 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_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 **); \ + } + +#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) \ +static inline \ +void __event_prepare_filter_stack__##_provider##___##_name(char *__stack_data,\ + _TP_ARGS_DATA_PROTO(_args)) \ +{ \ + _fields \ +} + +#include TRACEPOINT_INCLUDE + + + +/* + * Stage 4 of tracepoint event generation. * * Create static inline function that calculates event payload alignment. */ /* Reset all macros within TRACEPOINT_EVENT */ #include +#include -#undef ctf_integer_ext -#define ctf_integer_ext(_type, _item, _src, _byte_order, _base) \ +#undef _ctf_integer_ext +#define _ctf_integer_ext(_type, _item, _src, _byte_order, _base, _nowrite) \ __event_align = _tp_max_t(size_t, __event_align, lttng_alignof(_type)); -#undef ctf_float -#define ctf_float(_type, _item, _src) \ +#undef _ctf_float +#define _ctf_float(_type, _item, _src, _nowrite) \ __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) \ +#undef _ctf_array_encoded +#define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \ __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) \ +#undef _ctf_sequence_encoded +#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \ + _src_length, _encoding, _nowrite) \ __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) +#undef _ctf_string +#define _ctf_string(_item, _src, _nowrite) -#undef TP_PROTO -#define TP_PROTO(args...) args +#undef TP_ARGS +#define TP_ARGS(...) __VA_ARGS__ #undef TP_FIELDS -#define TP_FIELDS(args...) args +#define TP_FIELDS(...) __VA_ARGS__ #undef TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _proto, _args, _fields) \ -static inline size_t __event_get_align__##_provider##___##_name(_proto) \ +#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 \ +size_t __event_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args)) \ { \ size_t __event_align = 1; \ _fields \ return __event_align; \ } -#include TRACEPOINT_INCLUDE(TRACEPOINT_INCLUDE_FILE) +#include TRACEPOINT_INCLUDE /* - * Stage 7 of the trace events. - * - * Create the probe function : call even size calculation and write event data - * into the buffer. + * Stage 5 of tracepoint event generation. * - * We use both the field and assignment macros to write the fields in the order - * defined in the field declaration. The field declarations control the - * execution order, jumping to the appropriate assignment block. + * Create the probe function. This function calls event size calculation + * and writes event data into the buffer. */ /* Reset all macros within TRACEPOINT_EVENT */ #include +#include -#undef ctf_integer_ext -#define ctf_integer_ext(_type, _item, _src, _byte_order, _base) \ +#undef _ctf_integer_ext +#define _ctf_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));\ } -#undef ctf_float -#define ctf_float(_type, _item, _src) \ +#undef _ctf_float +#define _ctf_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));\ } -#undef ctf_array_encoded -#define ctf_array_encoded(_type, _item, _src, _length, _encoding) \ +#undef _ctf_array_encoded +#define _ctf_array_encoded(_type, _item, _src, _length, _encoding, _nowrite) \ 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 _ctf_sequence_encoded +#define _ctf_sequence_encoded(_type, _item, _src, _length_type, \ + _src_length, _encoding, _nowrite) \ { \ - _length_type __tmpl = __dynamic_len[__dynamic_len_idx]; \ + _length_type __tmpl = __stackvar.__dynamic_len[__dynamic_len_idx]; \ lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_length_type));\ __chan->ops->event_write(&__ctx, &__tmpl, sizeof(_length_type));\ } \ @@ -409,34 +439,44 @@ static inline size_t __event_get_align__##_provider##___##_name(_proto) \ __chan->ops->event_write(&__ctx, _src, \ sizeof(_type) * __get_dynamic_len(dest)); -#undef ctf_string -#define ctf_string(_item, _src) \ +#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)); /* Beware: this get len actually consumes the len value */ #undef __get_dynamic_len -#define __get_dynamic_len(field) __dynamic_len[__dynamic_len_idx++] - -#undef TP_PROTO -#define TP_PROTO(args...) args +#define __get_dynamic_len(field) __stackvar.__dynamic_len[__dynamic_len_idx++] #undef TP_ARGS -#define TP_ARGS(args...) args +#define TP_ARGS(...) __VA_ARGS__ #undef TP_FIELDS -#define TP_FIELDS(args...) args +#define TP_FIELDS(...) __VA_ARGS__ +/* + * 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 TRACEPOINT_EVENT_CLASS -#define TRACEPOINT_EVENT_CLASS(_provider, _name, _proto, _args, _fields) \ -static void __event_probe__##_provider##___##_name(void *__data, _proto) \ +#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 ltt_event *__event = __data; \ - struct ltt_channel *__chan = __event->chan; \ - struct lttng_ust_lib_ring_buffer_ctx __ctx; \ + struct lttng_event *__event = __tp_data; \ + struct lttng_channel *__chan = __event->chan; \ + struct lttng_ust_lib_ring_buffer_ctx __ctx; \ size_t __event_len, __event_align; \ size_t __dynamic_len_idx = 0; \ - size_t __dynamic_len[_TP_ARRAY_SIZE(__event_fields___##_provider##___##_name)]; \ + 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)]; \ + } __stackvar; \ int __ret; \ \ if (0) \ @@ -447,35 +487,23 @@ static void __event_probe__##_provider##___##_name(void *__data, _proto) \ return; \ if (caa_unlikely(!CMM_ACCESS_ONCE(__event->enabled))) \ return; \ - __event_len = __event_get_size__##_provider##___##_name(__dynamic_len, _args); \ - __event_align = __event_get_align__##_provider##___##_name(_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) \ - return; \ - _fields \ - __chan->ops->event_commit(&__ctx); \ -} - -#undef TRACEPOINT_EVENT_CLASS_NOARGS -#define TRACEPOINT_EVENT_CLASS_NOARGS(_provider, _name, _fields) \ -static void __event_probe__##_provider##___##_name(void *__data) \ -{ \ - struct ltt_event *__event = __data; \ - struct ltt_channel *__chan = __event->chan; \ - struct lttng_ust_lib_ring_buffer_ctx __ctx; \ - size_t __event_len, __event_align; \ - int __ret; \ + if (caa_unlikely(!cds_list_empty(&__event->bytecode_runtime_head))) { \ + struct lttng_bytecode_runtime *bc_runtime; \ + int __filter_record = 0; \ \ - 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; \ - __event_len = 0; \ - __event_align = 1; \ + __event_prepare_filter_stack__##_provider##___##_name(__stackvar.__filter_stack_data, \ + _TP_ARGS_DATA_VAR(_args)); \ + cds_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)) \ + __filter_record = 1; \ + } \ + if (caa_likely(!__filter_record)) \ + return; \ + } \ + __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)); \ lib_ring_buffer_ctx_init(&__ctx, __chan->chan, __event, __event_len, \ __event_align, -1, __chan->handle); \ __ret = __chan->ops->event_reserve(&__ctx, __event->id); \ @@ -485,36 +513,158 @@ static void __event_probe__##_provider##___##_name(void *__data) \ __chan->ops->event_commit(&__ctx); \ } -#include TRACEPOINT_INCLUDE(TRACEPOINT_INCLUDE_FILE) +#include TRACEPOINT_INCLUDE #undef __get_dynamic_len /* - * Stage 8 of the trace events. + * Stage 5.1 of tracepoint event generation. * - * Register/unregister probes at module load/unload. + * Create probe signature + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#include + +#undef TP_ARGS +#define TP_ARGS(...) __VA_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[] = \ + _TP_EXTRACT_STRING2(_args); + +#include TRACEPOINT_INCLUDE + +#undef _TP_EXTRACT_STRING2 + +/* + * 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 TRACEPOINT_EVENT */ +#include + +#undef TRACEPOINT_LOGLEVEL +#define TRACEPOINT_LOGLEVEL(__provider, __name, __loglevel) \ +static const int _loglevel_value___##__provider##___##__name = __loglevel; \ +static const int *_loglevel___##__provider##___##__name = \ + &_loglevel_value___##__provider##___##__name; + +#include TRACEPOINT_INCLUDE + +/* + * Stage 6.1 of tracepoint event generation. + * + * Tracepoint UML URI info. */ /* Reset all macros within TRACEPOINT_EVENT */ #include -#define TP_ID1(_token, _system) _token##_system -#define TP_ID(_token, _system) TP_ID1(_token, _system) +#undef TRACEPOINT_MODEL_EMF_URI +#define TRACEPOINT_MODEL_EMF_URI(__provider, __name, __uri) \ +static const char *_model_emf_uri___##__provider##___##__name = __uri; + +#include TRACEPOINT_INCLUDE -static void __attribute__((constructor)) -TP_ID(__lttng_events_init__, TRACEPOINT_SYSTEM)(void) +/* + * Stage 7.1 of tracepoint event generation. + * + * Create events description structures. We use a weakref because + * loglevels are optional. If not declared, the event will point to the + * a loglevel that contains NULL. + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#include + +#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, \ + .name = #_provider ":" #_name, \ + .probe_callback = (void (*)(void)) &__event_probe__##_provider##___##_template,\ + .nr_fields = _TP_ARRAY_SIZE(__event_fields___##_provider##___##_template), \ + .loglevel = &__ref_loglevel___##_provider##___##_name, \ + .signature = __tp_event_signature___##_provider##___##_template, \ + .u.ext.model_emf_uri = &__ref_model_emf_uri___##_provider##___##_name, \ +}; + +#include TRACEPOINT_INCLUDE + +/* + * Stage 7.2 of tracepoint event generation. + * + * Create array of events. + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#include + +#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 +}; + + +/* + * Stage 8 of tracepoint event generation. + * + * Create a toplevel descriptor for the whole probe. + */ + +/* non-const because list head will be modified when registered. */ +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)), +}; + +/* + * 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. + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#include +static void lttng_ust_notrace __attribute__((constructor)) +_TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void); +static void +_TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void) { int ret; - ret = ltt_probe_register(&TP_ID(__probe_desc___, TRACEPOINT_SYSTEM)); + ret = lttng_probe_register(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); assert(!ret); } -static void __attribute__((destructor)) -TP_ID(__lttng_events_exit__, TRACEPOINT_SYSTEM)(void) +static void lttng_ust_notrace __attribute__((destructor)) +_TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void); +static void +_TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void) { - ltt_probe_unregister(&TP_ID(__probe_desc___, TRACEPOINT_SYSTEM)); + lttng_probe_unregister(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); } -#undef TP_ID1 -#undef TP_ID +int _TP_COMBINE_TOKENS(__tracepoint_provider_, TRACEPOINT_PROVIDER);