Add callback registration to TRACE_EVENT
[lttng-modules.git] / probes / lttng-events.h
index aef811cd5c775861730f373f43aad73fe28153eb..f8dcf85c58a7d40787f0bf30e36c19417c60217e 100644 (file)
@@ -1,31 +1,10 @@
 #include <lttng.h>
 #include <lttng-types.h>
 #include <linux/debugfs.h>
+#include <linux/ringbuffer/frontend_types.h>
+#include "../ltt-events.h"
 #include "../ltt-tracer-core.h"
 
-#if 0
-
-/* keep for a later stage (copy stage) */
-/*
- * Macros mapping tp_assign() to "=", tp_memcpy() to memcpy() and tp_strcpy() to
- * strcpy().
- */
-#undef tp_assign
-#define tp_assign(dest, src)                                           \
-       lib_ring_buffer_align_ctx(config, &ctx, sizeof(src));           \
-       lib_ring_buffer_write(config, &ctx, &src, sizeof(src));
-
-#undef tp_memcpy
-#define tp_memcpy(dest, src, len)                                      \
-       lib_ring_buffer_align_ctx(config, &ctx, sizeof(*(src)));        \
-       lib_ring_buffer_write(config, &ctx, &src, len);
-
-/* TODO */
-#undef tp_strcpy
-#define tp_strcpy(dest, src)           __assign_str(dest, src);
-
-#endif //0
-
 struct lttng_event_field {
        const char *name;
        const struct lttng_type type;
@@ -117,7 +96,7 @@ struct lttng_event_desc {
 #undef __string
 #define __string(_item, _src)                                  \
        {                                                       \
-               .name = _item,                                  \
+               .name = #_item,                                 \
                .type = {                                       \
                  .atype = atype_string,                        \
                  .name = NULL,                                 \
@@ -129,9 +108,9 @@ struct lttng_event_desc {
 #define TP_STRUCT__entry(args...) args /* Only one used in this phase */
 
 #undef DECLARE_EVENT_CLASS
-#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print)   \
-       static const struct lttng_event_field __event_fields___##_name[] = {    \
-               _tstruct                                                        \
+#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print) \
+       static const struct lttng_event_field __event_fields___##_name[] = { \
+               _tstruct                                                     \
        };
 
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
@@ -146,12 +125,12 @@ struct lttng_event_desc {
 
 #include "lttng-events-reset.h"        /* Reset all macros within TRACE_EVENT */
 
-#undef DECLARE_EVENT_CLASS
-#define DECLARE_EVENT_CLASS(_name, proto, args, tstruct, assign, print)        \
-               {                                                       \
-                       .fields = __event_fields___##_name,             \
-                       .name = #_name,                                 \
-                       .nr_fields = ARRAY_SIZE(__event_fields___##_name), \
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(_template, _name, _proto, _args)                         \
+               {                                                              \
+                       .fields = __event_fields___##_template,                \
+                       .name = #_name,                                        \
+                       .nr_fields = ARRAY_SIZE(__event_fields___##_template), \
                },
 
 #define TP_ID1(_token, _system)        _token##_system
@@ -172,10 +151,6 @@ static const struct lttng_event_desc TP_ID(__event_desc___, TRACE_SYSTEM)[] = {
 
 #define TP_ID1(_token, _system)        _token##_system
 #define TP_ID(_token, _system) TP_ID1(_token, _system)
-#define module_init_eval1(_token, _system)     module_init(_token##_system)
-#define module_init_eval(_token, _system)      module_init_eval1(_token, _system)
-#define module_exit_eval1(_token, _system)     module_exit(_token##_system)
-#define module_exit_eval(_token, _system)      module_exit_eval1(_token, _system)
 
 static void *TP_ID(__lttng_seq_start__, TRACE_SYSTEM)(struct seq_file *m,
                                                      loff_t *pos)
@@ -273,21 +248,14 @@ error:
        return ret;
 }
 
-module_init_eval(__lttng_types_init__, TRACE_SYSTEM);
-
 static void TP_ID(__lttng_types_exit__, TRACE_SYSTEM)(void)
 {
        debugfs_remove(TP_ID(__lttng_types_dentry__, TRACE_SYSTEM));
 }
 
-module_exit_eval(__lttng_types_exit__, TRACE_SYSTEM);
-
-#undef module_init_eval
-#undef module_exit_eval
 #undef TP_ID1
 #undef TP_ID
 
-
 /*
  * Stage 4 of the trace events.
  *
@@ -298,64 +266,323 @@ module_exit_eval(__lttng_types_exit__, TRACE_SYSTEM);
 
 /* Named field types must be defined in lttng-types.h */
 
+#undef __field
+#define __field(_type, _item)                                                 \
+       __event_len += lib_ring_buffer_align(__event_len, __alignof__(_type)); \
+       __event_len += sizeof(_type);
+
+#undef __field_ext
+#define __field_ext(_type, _item, _filter_type)        __field(_type, _item)
+
+#undef __array
+#define __array(_type, _item, _length)                                        \
+       __event_len += lib_ring_buffer_align(__event_len, __alignof__(_type)); \
+       __event_len += sizeof(_type) * (_length);
+
+#undef __dynamic_array
+#define __dynamic_array(_type, _item, _length)                                \
+       __event_len += lib_ring_buffer_align(__event_len, __alignof__(u32));   \
+       __event_len += sizeof(u32);                                            \
+       __event_len += lib_ring_buffer_align(__event_len, __alignof__(_type)); \
+       __event_len += sizeof(_type) * (_length);
+
+#undef __string
+#define __string(_item, _src)                                                 \
+       __event_len += __dynamic_len[__dynamic_len_idx++] = strlen(_src) + 1;
+
+#undef TP_PROTO
+#define TP_PROTO(args...) args
+
+#undef TP_STRUCT__entry
+#define TP_STRUCT__entry(args...) args
+
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print)  \
+static inline size_t __event_get_size__##_name(size_t *__dynamic_len, _proto) \
+{                                                                            \
+       size_t __event_len = 0;                                               \
+       unsigned int __dynamic_len_idx = 0;                                   \
+                                                                             \
+       if (0)                                                                \
+               (void) __dynamic_len_idx;       /* don't warn if unused */    \
+       _tstruct                                                              \
+       return __event_len;                                                   \
+}
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+
+
+/*
+ * Stage 5 of the trace events.
+ *
+ * Create static inline function that calculates event payload alignment.
+ */
+
+#include "lttng-events-reset.h"        /* Reset all macros within TRACE_EVENT */
+
+/* Named field types must be defined in lttng-types.h */
+
+#undef __field
+#define __field(_type, _item)                                            \
+       __event_align = max_t(size_t, __event_align, __alignof__(_type));
+
+#undef __field_ext
+#define __field_ext(_type, _item, _filter_type)        __field(_type, _item)
+
+#undef __array
+#define __array(_type, _item, _length)                                   \
+       __event_align = max_t(size_t, __event_align, __alignof__(_type));
+
+#undef __dynamic_array
+#define __dynamic_array(_type, _item, _length)                           \
+       __event_align = max_t(size_t, __event_align, __alignof__(u32));   \
+       __event_align = max_t(size_t, __event_align, __alignof__(_type));
+
+#undef __string
+#define __string(_item, _src)
+
+#undef TP_PROTO
+#define TP_PROTO(args...) args
+
+#undef TP_STRUCT__entry
+#define TP_STRUCT__entry(args...) args
+
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print)  \
+static inline size_t __event_get_align__##_name(_proto)                              \
+{                                                                            \
+       size_t __event_align = 1;                                             \
+       _tstruct                                                              \
+       return __event_align;                                                 \
+}
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+
+/*
+ * Stage 6 of the trace events.
+ *
+ * Create structure declaration that allows the "assign" macros to access the
+ * field types.
+ */
+
+#include "lttng-events-reset.h"        /* Reset all macros within TRACE_EVENT */
+
+/* Named field types must be defined in lttng-types.h */
+
+#undef __field
+#define __field(_type, _item)  _type   _item;
+
+#undef __field_ext
+#define __field_ext(_type, _item, _filter_type)        __field(_type, _item)
+
+#undef __array
+#define __array(_type, _item, _length) _type   _item;
+
+#undef __dynamic_array
+#define __dynamic_array(_type, _item, _length) _type   _item;
+
+#undef __string
+#define __string(_item, _src)  char _item;
+
+#undef TP_STRUCT__entry
+#define TP_STRUCT__entry(args...) args
+
+#undef DECLARE_EVENT_CLASS
+#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print)  \
+struct __event_typemap__##_name {                                            \
+       _tstruct                                                              \
+};
+
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+
+
+/*
+ * Stage 7 of the trace events.
+ *
+ * Create the probe function : call even size calculation and write event data
+ * into the buffer.
+ *
+ * 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.
+ */
+
+#include "lttng-events-reset.h"        /* Reset all macros within TRACE_EVENT */
+
 #undef __field
 #define __field(_type, _item)                                          \
-       len += lib_ring_buffer_align(len, sizeof(_type));               \
-       len += sizeof(_type);
+       goto __assign_##_item;                                          \
+__end_field_##_item:
 
 #undef __field_ext
 #define __field_ext(_type, _item, _filter_type)        __field(_type, _item)
 
 #undef __array
 #define __array(_type, _item, _length)                                 \
-       len += lib_ring_buffer_align(len, sizeof(_type));               \
-       len += sizeof(_type) * (_length);
+       goto __assign_##_item;                                          \
+__end_field_##_item:
 
 #undef __dynamic_array
 #define __dynamic_array(_type, _item, _length)                         \
-       len += lib_ring_buffer_align(len, sizeof(u32));                 \
-       len += sizeof(u32);                                             \
-       len += lib_ring_buffer_align(len, sizeof(_type));               \
-       len += sizeof(_type) * (_length);
+       goto __assign_##_item##_1;                                      \
+__end_field_##_item##_1:                                               \
+       goto __assign_##_item##_2;                                      \
+__end_field_##_item##_2:
 
 #undef __string
 #define __string(_item, _src)                                          \
-       len += dynamic_len[dynamic_len_idx++] = strlen(_src) + 1;
+       goto __assign_##_item;                                          \
+__end_field_##_item:
+
+/*
+ * Macros mapping tp_assign() to "=", tp_memcpy() to memcpy() and tp_strcpy() to
+ * strcpy().
+ */
+#undef tp_assign
+#define tp_assign(dest, src)                                           \
+__assign_##dest:                                                       \
+       {                                                               \
+               __typeof__(__typemap.dest) __tmp = (src);               \
+               lib_ring_buffer_align_ctx(&ctx, __alignof__(__tmp));    \
+               __chan->ops->event_write(&ctx, &__tmp, sizeof(__tmp));  \
+       }                                                               \
+       goto __end_field_##dest;
+
+#undef tp_memcpy
+#define tp_memcpy(dest, src, len)                                      \
+__assign_##dest:                                                       \
+       lib_ring_buffer_align_ctx(&ctx, __alignof__(__typemap.dest));   \
+       __chan->ops->event_write(&ctx, src, len);                       \
+       goto __end_field_##dest;
+
+#undef tp_memcpy_dyn
+#define tp_memcpy_dyn(dest, src, len)                                  \
+__assign_##dest##_1:                                                   \
+       {                                                               \
+               u32 __tmpl = (len);                                     \
+               lib_ring_buffer_align_ctx(&ctx, __alignof__(u32));      \
+               __chan->ops->event_write(&ctx, &__tmpl, sizeof(u32));   \
+       }                                                               \
+       goto __end_field_##dest##_1;                                    \
+__assign_##dest##_2:                                                   \
+       lib_ring_buffer_align_ctx(&ctx, __alignof__(__typemap.dest));   \
+       __chan->ops->event_write(&ctx, src, len);                       \
+       goto __end_field_##dest##_2;
+
+#undef tp_strcpy
+#define tp_strcpy(dest, src)                                           \
+       tp_memcpy(dest, src, __get_dynamic_array_len(dest))
+
+/* Named field types must be defined in lttng-types.h */
+
+#undef __get_str
+#define __get_str(field)               field
+
+#undef __get_dynamic_array
+#define __get_dynamic_array(field)     field
+
+/* Beware: this get len actually consumes the len value */
+#undef __get_dynamic_array_len
+#define __get_dynamic_array_len(field) __dynamic_len[__dynamic_len_idx++]
+
+#undef TP_PROTO
+#define TP_PROTO(args...) args
+
+#undef TP_ARGS
+#define TP_ARGS(args...) args
 
 #undef TP_STRUCT__entry
-#define TP_STRUCT__entry(args...) args /* Only one used in this phase */
+#define TP_STRUCT__entry(args...) args
+
+#undef TP_fast_assign
+#define TP_fast_assign(args...) args
 
 #undef DECLARE_EVENT_CLASS
-#define DECLARE_EVENT_CLASS(name, proto, args, tstruct, assign, print) \
-static inline size_t __event_get_size__##name(size_t *dynamic_len)     \
-{                                                                      \
-       size_t len = 0;                                                 \
-       unsigned int dynamic_len_idx = 0;                               \
-                                                                       \
-       if (0)                                                          \
-               (void) dynamic_len_idx; /* don't warn if unused */      \
-       tstruct                                                         \
-       return len;                                                     \
+#define DECLARE_EVENT_CLASS(_name, _proto, _args, _tstruct, _assign, _print)  \
+static void __event_probe__##_name(void *__data, _proto)                     \
+{                                                                            \
+       struct ltt_event *__event = __data;                                   \
+       struct ltt_channel *__chan = __event->chan;                           \
+       struct lib_ring_buffer_ctx ctx;                                       \
+       size_t __event_len, __event_align;                                    \
+       size_t __dynamic_len_idx = 0;                                         \
+       size_t __dynamic_len[ARRAY_SIZE(__event_fields___##_name)];           \
+       struct __event_typemap__##_name __typemap;                            \
+       int __ret;                                                            \
+                                                                             \
+       if (0)                                                                \
+               (void) __dynamic_len_idx;       /* don't warn if unused */    \
+       __event_len = __event_get_size__##_name(__dynamic_len, _args);        \
+       __event_align = __event_get_align__##_name(_args);                    \
+       lib_ring_buffer_ctx_init(&ctx, __chan->chan, NULL, __event_len,       \
+                                __event_align, -1);                          \
+       __ret = __chan->ops->event_reserve(&ctx);                             \
+       if (__ret < 0)                                                        \
+               return;                                                       \
+       /* Control code (field ordering) */                                   \
+       _tstruct                                                              \
+       __chan->ops->event_commit(&ctx);                                      \
+       return;                                                               \
+       /* Copy code, steered by control code */                              \
+       _assign                                                               \
 }
 
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
 
 
-#if 0
-
 /*
- * Stage 4 of the trace events.
+ * Stage 8 of the trace events.
  *
- * Create the probe function : call even size calculation and write event data
- * into the buffer.
+ * Register/unregister probes at module load/unload.
  */
 
+#include "lttng-events-reset.h"        /* Reset all macros within TRACE_EVENT */
 
+#define TP_ID1(_token, _system)        _token##_system
+#define TP_ID(_token, _system) TP_ID1(_token, _system)
+#define module_init_eval1(_token, _system)     module_init(_token##_system)
+#define module_init_eval(_token, _system)      module_init_eval1(_token, _system)
+#define module_exit_eval1(_token, _system)     module_exit(_token##_system)
+#define module_exit_eval(_token, _system)      module_exit_eval1(_token, _system)
+
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(_template, _name, _proto, _args)                         \
+       ret = ltt_probe_register(#_name, (void *) __event_probe__##_template); \
+       WARN_ON_ONCE(ret);
+
+static int TP_ID(__lttng_events_init__, TRACE_SYSTEM)(void)
+{
+       int ret = 0;
+
+       ret = TP_ID(__lttng_types_init__, TRACE_SYSTEM)();
+       if (ret)
+               return ret;
+#include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+       return ret;
+}
+
+module_init_eval(__lttng_events_init__, TRACE_SYSTEM);
+
+#undef DEFINE_EVENT
+#define DEFINE_EVENT(_template, _name, _proto, _args)                         \
+       ltt_probe_unregister(#_name);
 
+static void TP_ID(__lttng_events_exit__, TRACE_SYSTEM)(void)
+{
 #include TRACE_INCLUDE(TRACE_INCLUDE_FILE)
+       TP_ID(__lttng_types_exit__, TRACE_SYSTEM)();
+}
 
+module_exit_eval(__lttng_events_exit__, TRACE_SYSTEM);
 
+#undef module_init_eval
+#undef module_exit_eval
+#undef TP_ID1
+#undef TP_ID
 
+#if 0
 
 #include <linux/ftrace_event.h>
 
This page took 0.028825 seconds and 4 git commands to generate.