From 1c324e592f238f5c1d19b19faf3a95a6d9185bdf Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Fri, 18 Nov 2011 12:36:52 -0500 Subject: [PATCH] Implement ust-tracepoint-events under MIT license Signed-off-by: Mathieu Desnoyers --- include/lttng/tracepoint-event.h | 3 + ...t-reset.h => ust-tracepoint-event-reset.h} | 0 include/lttng/ust-tracepoint-event.h | 474 ++++++++++++++++++ 3 files changed, 477 insertions(+) rename include/lttng/{tracepoint-event-reset.h => ust-tracepoint-event-reset.h} (100%) diff --git a/include/lttng/tracepoint-event.h b/include/lttng/tracepoint-event.h index 176e7f3f..94b0bcb1 100644 --- a/include/lttng/tracepoint-event.h +++ b/include/lttng/tracepoint-event.h @@ -37,6 +37,9 @@ extern "C" { #define TRACEPOINT_HEADER_MULTI_READ #include TRACEPOINT_INCLUDE + +#include + #undef TRACEPOINT_HEADER_MULTI_READ #define TRACEPOINT_CREATE_PROBES diff --git a/include/lttng/tracepoint-event-reset.h b/include/lttng/ust-tracepoint-event-reset.h similarity index 100% rename from include/lttng/tracepoint-event-reset.h rename to include/lttng/ust-tracepoint-event-reset.h diff --git a/include/lttng/ust-tracepoint-event.h b/include/lttng/ust-tracepoint-event.h index e69de29b..6d1f9720 100644 --- a/include/lttng/ust-tracepoint-event.h +++ b/include/lttng/ust-tracepoint-event.h @@ -0,0 +1,474 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include + +/* + * 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 + * 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 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)) + +/* Helpers */ +#define _TP_ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + +#define _tp_max_t(type, x, y) \ + ({ \ + type __max1 = (x); \ + type __max2 = (y); \ + __max1 > __max2 ? __max1: __max2; \ + }) + +/* + * Stage 0 of tracepoint event generation. + * + * Check that each TRACEPOINT_EVENT provider argument match the + * TRACEPOINT_PROVIDER by creating dummy callbacks. + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#include + +static inline +void _TP_COMBINE_TOKENS(__tracepoint_provider_mismatch_, TRACEPOINT_PROVIDER)(void) +{ +} + +#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) \ + __tracepoint_provider_mismatch_##_provider(); + +static __attribute__((unused)) +void _TP_COMBINE_TOKENS(__tracepoint_provider_check_, TRACEPOINT_PROVIDER)(void) +{ +#include TRACEPOINT_INCLUDE +} + +/* + * Stage 1 of tracepoint event generation. + * + * Create event field type metadata section. + * Each event produce an array of fields. + */ + +/* Reset all macros within 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 \ + }; + +#include TRACEPOINT_INCLUDE + +/* + * Stage 2 of tracepoint event generation. + * + * Create probe callback prototypes. + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#include + +#undef TP_ARGS +#define TP_ARGS(args...) args + +#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. + * + * Create an array of events. + */ + +/* Reset all macros within 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 +}; + + +/* + * Stage 4 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) = { + .event_desc = _TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER), + .nr_events = _TP_ARRAY_SIZE(_TP_COMBINE_TOKENS(__event_desc___, TRACEPOINT_PROVIDER)), +}; + +/* + * Stage 5 of tracepoint event generation. + * + * Create static inline function that calculates event size. + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#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)); \ + __event_len += sizeof(_type); + +#undef ctf_float +#define ctf_float(_type, _item, _src) \ + __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) \ + __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) \ + __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)); \ + __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 TP_ARGS +#define TP_ARGS(args...) args + +#undef TP_FIELDS +#define TP_FIELDS(args...) 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)) \ +{ \ + size_t __event_len = 0; \ + unsigned int __dynamic_len_idx = 0; \ + \ + if (0) \ + (void) __dynamic_len_idx; /* don't warn if unused */ \ + _fields \ + return __event_len; \ +} + +#include TRACEPOINT_INCLUDE + +/* + * Stage 6 of tracepoint event generation. + * + * Create static inline function that calculates event payload alignment. + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#include + +#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 ctf_float +#define ctf_float(_type, _item, _src) \ + __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) \ + __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) \ + __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 TP_ARGS +#define TP_ARGS(args...) args + +#undef TP_FIELDS +#define TP_FIELDS(args...) args + +#undef TRACEPOINT_EVENT_CLASS +#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +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 + + +/* + * Stage 7 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 */ +#include + +#undef ctf_integer_ext +#define ctf_integer_ext(_type, _item, _src, _byte_order, _base) \ + { \ + _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) \ + { \ + _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) \ + 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) \ + { \ + _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));\ + } \ + lib_ring_buffer_align_ctx(&__ctx, lttng_alignof(_type)); \ + __chan->ops->event_write(&__ctx, _src, \ + sizeof(_type) * __get_dynamic_len(dest)); + +#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)); + +/* 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_ARGS +#define TP_ARGS(args...) args + +#undef TP_FIELDS +#define TP_FIELDS(args...) args + +#undef TRACEPOINT_EVENT_CLASS +#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args))\ +{ \ + struct ltt_event *__event = __tp_cb_data; \ + struct ltt_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)]; \ + int __ret; \ + \ + 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; \ + 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) \ + return; \ + _fields \ + __chan->ops->event_commit(&__ctx); \ +} + +#include TRACEPOINT_INCLUDE + +#undef __get_dynamic_len + +/* + * Stage 8 of tracepoint event generation. + * + * Register/unregister probes at module load/unload. + */ + +/* Reset all macros within TRACEPOINT_EVENT */ +#include + +static void __attribute__((constructor)) +_TP_COMBINE_TOKENS(__lttng_events_init__, TRACEPOINT_PROVIDER)(void) +{ + int ret; + + ret = ltt_probe_register(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); + assert(!ret); +} + +static void __attribute__((destructor)) +_TP_COMBINE_TOKENS(__lttng_events_exit__, TRACEPOINT_PROVIDER)(void) +{ + ltt_probe_unregister(&_TP_COMBINE_TOKENS(__probe_desc___, TRACEPOINT_PROVIDER)); +} -- 2.34.1