From mboxrd@z Thu Jan 1 00:00:00 1970 From: gbastien+lttng@versatic.net (=?UTF-8?q?Genevi=C3=A8ve=20Bastien?=) Date: Wed, 26 Mar 2014 10:47:10 -0400 Subject: [lttng-dev] [RFC Patch Ust 3/5] Add the macros to generate the data structures for CTF global structures In-Reply-To: <1395845232-17669-1-git-send-email-gbastien+lttng@versatic.net> References: <1395845232-17669-1-git-send-email-gbastien+lttng@versatic.net> Message-ID: <1395845232-17669-4-git-send-email-gbastien+lttng@versatic.net> The structure global type is very similar to an event, and thus reuse most of the macros for the event fields. Signed-off-by: Genevi?ve Bastien --- include/lttng/tracepoint.h | 67 ++++++++++++++ include/lttng/ust-tracepoint-event-nowrite.h | 4 + include/lttng/ust-tracepoint-event-reset.h | 12 +++ include/lttng/ust-tracepoint-event-write.h | 4 + include/lttng/ust-tracepoint-event.h | 128 ++++++++++++++++++++++++++- 5 files changed, 211 insertions(+), 4 deletions(-) diff --git a/include/lttng/tracepoint.h b/include/lttng/tracepoint.h index 27aa01c..4b2e85f 100644 --- a/include/lttng/tracepoint.h +++ b/include/lttng/tracepoint.h @@ -466,6 +466,70 @@ __tracepoints__ptrs_destroy(void) #endif /* #ifndef TRACEPOINT_ENUM */ +#ifndef TRACEPOINT_STRUCT + +/* + * Tracepoint Structures + * + * Structures are compound types used to group fields together. These types + * can be reused by different tracepoints. + * + * An example: + * + * TRACEPOINT_STRUCT(someproject_component, structname, + * + * * TP_ARGS takes from 0 to 10 "type, field_name" pairs * + * + * TP_ARGS(int, arg0, void *, arg1, char *, string, size_t, strlen, + * long *, arg4, size_t, arg4_len), + * + * * TP_FIELDS describes the structure payload layout in the trace * + * + * TP_FIELDS( + * * Integer, printed in base 10 * + * ctf_integer(int, field_a, arg0) + * + * * Integer, printed with 0x base 16 * + * ctf_integer_hex(unsigned long, field_d, arg1) + * + * * Enumeration * + * ctf_enum(component, name, field_e, arg) + * + * * Array Sequence, printed as UTF8-encoded array of bytes * + * ctf_array_text(char, field_b, string, FIXED_LEN) + * ctf_sequence_text(char, field_c, string, size_t, strlen) + * + * * String, printed as UTF8-encoded string * + * ctf_string(field_e, string) + * + * * Array sequence of signed integer values * + * ctf_array(long, field_f, arg4, FIXED_LEN4) + * ctf_sequence(long, field_g, arg4, size_t, arg4_len) + * + * * Structures * + * ctf_struct(component, struct_name, field_s, args...) + * ) + * ) + * + * Where "someproject_component" is the name of the component this structure + * belongs to and "structname" identifies this structure. The arguments and + * fields described after are the same as for an event. See the event + * documentation for more information. + * + * That structure can then be used in a field inside the TP_FIELD macro, either + * in another structure or in an event using the following line: + * + * ctf_struct(someproject_component, structname, field, arguments...) + * + * Where "someproject_component" and "structname" match those in the + * TRACEPOINT_STRUCT, "field" is the name of the field and the arguments + * correspond to what the TRACEPOINT_STRUCT receives. + */ + +#define TRACEPOINT_STRUCT(provider, name, args, fields) + +#endif /* #ifndef TRACEPOINT_STRUCT */ + #ifndef TRACEPOINT_EVENT /* @@ -502,6 +566,9 @@ __tracepoints__ptrs_destroy(void) * * Array sequence of signed integer values * * ctf_array(long, field_f, arg4, FIXED_LEN4) * ctf_sequence(long, field_g, arg4, size_t, arg4_len) + * + * * Structures * + * ctf_struct(component, struct_name, field_s, args...) * ) * ) * diff --git a/include/lttng/ust-tracepoint-event-nowrite.h b/include/lttng/ust-tracepoint-event-nowrite.h index 7f5b1d9..68efb73 100644 --- a/include/lttng/ust-tracepoint-event-nowrite.h +++ b/include/lttng/ust-tracepoint-event-nowrite.h @@ -53,3 +53,7 @@ #undef ctf_enum_nowrite #define ctf_enum_nowrite(_provider, _name, _item, _src) \ _ctf_enum(_provider, _name, _item, _src, 1) + +#undef ctf_struct_nowrite +#define ctf_struct_nowrite(_provider, _name, _item, _src...) \ + _ctf_struct(_provider, _name, _item, 1, _src) diff --git a/include/lttng/ust-tracepoint-event-reset.h b/include/lttng/ust-tracepoint-event-reset.h index 4b795c9..6342d25 100644 --- a/include/lttng/ust-tracepoint-event-reset.h +++ b/include/lttng/ust-tracepoint-event-reset.h @@ -31,6 +31,9 @@ #undef TRACEPOINT_ENUM #define TRACEPOINT_ENUM(_provider, _name, _type, _values) +#undef TRACEPOINT_STRUCT +#define TRACEPOINT_STRUCT(_provider, _name, _args, _fields) + #undef TP_ARGS #define TP_ARGS(...) @@ -67,6 +70,9 @@ #undef _ctf_enum #define _ctf_enum(_provider, _name, _item, _src, _nowrite) +#undef _ctf_struct +#define _ctf_struct(_provider, _name, _item, _nowrite, _src...) + #undef ctf_enum_integer #define ctf_enum_integer(_type) @@ -104,6 +110,9 @@ #undef ctf_enum #define ctf_enum(_provider, _name, _item, _src) +#undef ctf_struct +#define ctf_struct(_provider, _name, _item, _src...) + /* "nowrite" */ #undef ctf_integer_nowrite #define ctf_integer_nowrite(_type, _item, _src) @@ -128,3 +137,6 @@ #undef ctf_enum_nowrite #define ctf_enum_nowrite(_provider, _name, _item, _src) + +#undef ctf_struct_nowrite +#define ctf_struct_nowrite(_provider, _name, _item, _src...) diff --git a/include/lttng/ust-tracepoint-event-write.h b/include/lttng/ust-tracepoint-event-write.h index 7dd06ed..4844a72 100644 --- a/include/lttng/ust-tracepoint-event-write.h +++ b/include/lttng/ust-tracepoint-event-write.h @@ -65,3 +65,7 @@ #undef ctf_enum #define ctf_enum(_provider, _name, _item, _src) \ _ctf_enum(_provider, _name, _item, _src, 0) + +#undef ctf_struct +#define ctf_struct(_provider, _name, _item, _src...) \ + _ctf_struct(_provider, _name, _item, 0, _src) diff --git a/include/lttng/ust-tracepoint-event.h b/include/lttng/ust-tracepoint-event.h index c75ed73..9c351a3 100644 --- a/include/lttng/ust-tracepoint-event.h +++ b/include/lttng/ust-tracepoint-event.h @@ -255,6 +255,21 @@ static const char \ .encoding = lttng_encode_none, \ } +#undef _ctf_struct +#define _ctf_struct(_provider, _name, _item, _nowrite, _src...) \ + { \ + .name = #_item, \ + .type = { \ + .atype = atype_structure, \ + .u = { \ + .structure = { \ + .name = #_provider "_" #_name, \ + }, \ + }, \ + }, \ + .nowrite = _nowrite, \ + } + #undef TP_FIELDS #define TP_FIELDS(...) __VA_ARGS__ /* Only one used in this phase */ @@ -273,6 +288,13 @@ static const char \ .len = _TP_ARRAY_SIZE(__enum_values__##_provider##_##_name), \ }; +#undef TRACEPOINT_STRUCT +#define TRACEPOINT_STRUCT(_provider, _name, _args, _fields) \ + static const struct lttng_event_field __struct_fields___##_provider##___##_name[] = { \ + _fields \ + }; + + #include TRACEPOINT_INCLUDE /* @@ -296,6 +318,16 @@ static const char \ }, \ }, +#undef _ctf_struct +#define _ctf_struct(_provider, _name, _item, _nowrite, _src...) \ + { \ + .mtype = mtype_structure, \ + .nowrite = _nowrite, \ + .u = { \ + .ctf_structure = &__structure_##_provider##_##_name \ + }, \ + } + #undef TP_FIELDS #define TP_FIELDS(...) __VA_ARGS__ /* Only one used in this phase */ @@ -305,6 +337,19 @@ static const char \ _fields \ }; +#undef TRACEPOINT_STRUCT +#define TRACEPOINT_STRUCT(_provider, _name, _args, _fields) \ + static const struct lttng_global_type_decl __global_types_for_struct___##_provider##___##_name[] = { \ + _fields \ + }; \ + static const struct lttng_structure __structure_##_provider##_##_name = { \ + .name = #_provider "_" #_name, \ + .nr_fields = _TP_ARRAY_SIZE(__struct_fields___##_provider##___##_name), \ + .fields = __struct_fields___##_provider##___##_name, \ + .nr_global_type_decl = _TP_ARRAY_SIZE(__global_types_for_struct___##_provider##___##_name), \ + .global_type_decl = __global_types_for_struct___##_provider##___##_name, \ + }; + #include TRACEPOINT_INCLUDE /* @@ -372,6 +417,10 @@ static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)); #define ctf_enum_integer(_type) \ _type +#undef _ctf_struct +#define _ctf_struct(_provider, _name, _item, _nowrite, _src...) \ + __event_len += __struct_get_size__##_provider##___##_name(__dynamic_len, __dynamic_len_idx, _src); + #undef TP_ARGS #define TP_ARGS(...) __VA_ARGS__ @@ -405,6 +454,17 @@ size_t __enum_get_size__##_provider##___##_name(size_t __event_len) \ return __enum_len; \ } +#undef TRACEPOINT_STRUCT +#define TRACEPOINT_STRUCT(_provider, _name, _args, _fields) \ +static inline \ +size_t __struct_get_size__##_provider##___##_name(size_t *__dynamic_len,\ + unsigned int __dynamic_len_idx, _TP_ARGS_PROTO(_args)) \ +{ \ + size_t __event_len = 0; \ + _fields \ + return __event_len; \ +} + #include TRACEPOINT_INCLUDE /* @@ -638,6 +698,10 @@ void __event_prepare_filter_stack__##_provider##___##_name(char *__stack_data,\ #define _ctf_enum(_provider, _name, _item, _src, _nowrite) \ __event_align = _tp_max_t(size_t, __event_align, __enum_get_align__##_provider##___##_name()); +#undef _ctf_struct +#define _ctf_struct(_provider, _name, _item, _nowrite, _src...) \ + __event_align = _tp_max_t(size_t, __event_align, __struct_get_align__##_provider##___##_name(_src)); + #undef TP_ARGS #define TP_ARGS(...) __VA_ARGS__ @@ -664,8 +728,43 @@ size_t __enum_get_align__##_provider##___##_name(void) \ return lttng_alignof(_type); \ } +#undef TRACEPOINT_STRUCT +#define TRACEPOINT_STRUCT(_provider, _name, _args, _fields) \ +static inline \ +size_t __struct_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args))\ +{ \ + size_t __event_align = 1; \ + _fields \ + return __event_align; \ +} + #include TRACEPOINT_INCLUDE +/* + * State 4.9 of tracepoint event generation + * + * Get the maximum field count from event fields recursively + */ +/* Reset all macros within TRACEPOINT_EVENT */ +#include +#include + +#undef _ctf_struct +#define _ctf_struct(_provider, _name, _item, _nowrite, _src...) \ + + __struct_event_count___##_provider##___##_name + +#undef TRACEPOINT_STRUCT +#define TRACEPOINT_STRUCT(_provider, _name, _args, _fields) \ +static const size_t __struct_field_count___##_provider##___##_name = \ + _TP_ARRAY_SIZE(__struct_fields___##_provider##___##_name) _fields; + +#undef TRACEPOINT_EVENT_CLASS +#define TRACEPOINT_EVENT_CLASS(_provider, _name, _args, _fields) \ +static const size_t __event_field_count___##_provider##___##_name = \ + _TP_ARRAY_SIZE(__event_fields___##_provider##___##_name) _fields; + + +#include TRACEPOINT_INCLUDE /* * Stage 5 of tracepoint event generation. @@ -703,7 +802,7 @@ size_t __enum_get_align__##_provider##___##_name(void) \ #define _ctf_sequence_encoded(_type, _item, _src, _length_type, \ _src_length, _encoding, _nowrite) \ { \ - _length_type __tmpl = __stackvar.__dynamic_len[__dynamic_len_idx]; \ + _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));\ } \ @@ -790,9 +889,13 @@ size_t __enum_get_align__##_provider##___##_name(void) \ } \ } +#undef _ctf_struct +#define _ctf_struct(_provider, _name, _item, _nowrite, _src...) \ + __struct_probe__##_provider##___##_name(__chan, __ctx, __dynamic_len_idx, __dynamic_len, _src); + /* Beware: this get len actually consumes the len value */ #undef __get_dynamic_len -#define __get_dynamic_len(field) __stackvar.__dynamic_len[__dynamic_len_idx++] +#define __get_dynamic_len(field) __dynamic_len[__dynamic_len_idx++] #undef TP_ARGS #define TP_ARGS(...) __VA_ARGS__ @@ -801,6 +904,22 @@ size_t __enum_get_align__##_provider##___##_name(void) \ #define TP_FIELDS(...) __VA_ARGS__ /* + * Probe for structures will call this method + */ +#undef TRACEPOINT_STRUCT +#define TRACEPOINT_STRUCT(_provider, _name, _args, _fields) \ +static inline \ +void __struct_probe__##_provider##___##_name(struct lttng_channel *__chan, \ + struct lttng_ust_lib_ring_buffer_ctx __ctx, size_t __dynamic_len_idx, \ + size_t *__dynamic_len, _TP_ARGS_PROTO(_args)) \ +{ \ + if (0) { \ + (void) __dynamic_len; \ + } \ + _fields \ +} + +/* * 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. @@ -832,9 +951,10 @@ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \ size_t __event_len, __event_align; \ size_t __dynamic_len_idx = 0; \ union { \ - size_t __dynamic_len[_TP_ARRAY_SIZE(__event_fields___##_provider##___##_name)]; \ + size_t __dynamic_len[__event_field_count___##_provider##___##_name]; \ char __filter_stack_data[2 * sizeof(unsigned long) * _TP_ARRAY_SIZE(__event_fields___##_provider##___##_name)]; \ } __stackvar; \ + size_t *__dynamic_len = __stackvar.__dynamic_len; \ int __ret; \ \ if (0) \ @@ -863,7 +983,7 @@ void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args)) \ if (caa_likely(!__filter_record)) \ return; \ } \ - __event_len = __event_get_size__##_provider##___##_name(__stackvar.__dynamic_len, \ + __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, \ -- 1.9.1