Add CTF enum type support to tracepoint event
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Sat, 9 Jan 2016 19:44:30 +0000 (14:44 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Thu, 14 Jan 2016 16:36:55 +0000 (11:36 -0500)
Derived from initial implementation by:
Geneviève Bastien <gbastien+lttng@versatic.net>

Bump UST communication protocol version to 6.1 (minor version increase)
since we're adding enumeration notification command.

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
21 files changed:
configure.ac
doc/man/lttng-ust.3
include/lttng/tracepoint.h
include/lttng/ust-abi.h
include/lttng/ust-ctl.h
include/lttng/ust-events.h
include/lttng/ust-tracepoint-event-nowrite.h
include/lttng/ust-tracepoint-event-reset.h
include/lttng/ust-tracepoint-event-write.h
include/lttng/ust-tracepoint-event.h
include/ust-comm.h
liblttng-ust-comm/lttng-ust-comm.c
liblttng-ust-ctl/ustctl.c
liblttng-ust/lttng-events.c
liblttng-ust/ust-core.c
tests/Makefile.am
tests/ctf-types/Makefile.am [new file with mode: 0644]
tests/ctf-types/README [new file with mode: 0644]
tests/ctf-types/ctf-types.c [new file with mode: 0644]
tests/ctf-types/tp.c [new file with mode: 0644]
tests/ctf-types/ust_tests_ctf_types.h [new file with mode: 0644]

index 26bf5a59c153d731fc30b7293d39f2d35cf71983..c92840bcf73785108e799e42abd081c5d0aca8d6 100644 (file)
@@ -399,6 +399,7 @@ AC_CONFIG_FILES([
        python-lttngust/lttngust/__init__.py
        tools/Makefile
        tests/Makefile
+       tests/ctf-types/Makefile
        tests/hello/Makefile
        tests/hello.cxx/Makefile
        tests/same_line_tracepoint/Makefile
index 398498913f104e6456bb87abedf38b7fc7f12e84..0455eea2810e2178dfe7c244eeeb6800d46e6106 100644 (file)
@@ -224,6 +224,17 @@ TRACEPOINT_EVENT(
                 */
                ctf_float(float, floatfield, floatarg)
                ctf_float(double, doublefield, doublearg)
+
+               /*
+                * ctf_enum: a field using a previously declared
+                * enumeration args: (provider, enum name, container
+                * type, field name, argument expression). The
+                * enumeration itself and its values must have been
+                * defined previously with the TRACEPOINT_ENUM macro,
+                * described below.
+                */
+               ctf_enum(sample_component, enumeration_name, int,
+                             enumfield, enumarg)
        )
 )
 
@@ -231,6 +242,49 @@ There can be an arbitrary number of tracepoint providers within an
 application, but they must each have their own provider name. Duplicate
 provider names are not allowed.
 
+The CTF specification also supports enumerations that can be declared
+inside a tracepoint provider and used as fields in the tracepoint. This
+shows how to specify enumerations and what they can be used for:
+
+The enumeration is a mapping between an integer, or a range of integers, and a
+string. It can be used to have a more compact trace in cases where the possible
+values for a field are limited:
+
+TRACEPOINT_ENUM(
+       /*
+        * The provider name, as described in the TRACEPOINT_EVENT macro.
+        */
+       sample_component,
+
+       /*
+        * The name of this enumeration, that will be used when using this
+        * global type in tracepoint fields.
+        */
+       enumeration_name,
+
+       /*
+        * TP_ENUM_VALUES describe the values of this enumeration and what they
+        * map to.
+        */
+       TP_ENUM_VALUES(
+               /*
+                * Maps an integer with this string value. By default, enumerations
+                * start at 0 and increment 1 for each entry.
+                */
+               ctf_enum_value(string_value)
+
+               /*
+                * Maps the string value to integers in the range 'start' to 'end'
+                * inclusively. If 'start' == 'end', then the string is mapped to
+                * a specific value.
+                * Enumeration ranges may overlap, but the behavior is
+                * implementation-defined, each trace reader will handle overlapping
+                * as it wishes.
+                */
+               ctf_enum_range(start, end, string_value)
+       )
+)
+
 .fi
 
 .SH "ASSIGNING LOGLEVEL TO EVENTS"
index e88db89242750c591909fb56ae912eb6cc670ff3..16348b86106c98e15abe58cf62b8fc11cdc43a4c 100644 (file)
@@ -430,6 +430,50 @@ __tracepoints__ptrs_destroy(void)
 
 /* The following declarations must be outside re-inclusion protection. */
 
+#ifndef TRACEPOINT_ENUM
+
+/*
+ * Tracepoint Enumerations
+ *
+ * The enumeration is a mapping between an integer, or range of integers, and
+ * a string. It can be used to have a more compact trace in cases where the
+ * possible values for a field are limited:
+ *
+ * An example:
+ *
+ * TRACEPOINT_ENUM(someproject_component, enumname,
+ *     TP_ENUM_VALUES(
+ *             ctf_enum_value("even", 0)
+ *             ctf_enum_value("uneven", 1)
+ *             ctf_enum_range("twoto4", 2, 4)
+ *             ctf_enum_value("five", 5)
+ *     )
+ * )
+ *
+ * Where "someproject_component" is the name of the component this enumeration
+ * belongs to and "enumname" identifies this enumeration. Inside the
+ * TP_ENUM_VALUES macro is the actual mapping. Each string value can map
+ * to either a single value with ctf_enum_value or a range of values
+ * with ctf_enum_range.
+ *
+ * Enumeration ranges may overlap, but the behavior is implementation-defined,
+ * each trace reader will handle overlapping as it wishes.
+ *
+ * That enumeration can then be used in a field inside the TP_FIELD macro using
+ * the following line:
+ *
+ * ctf_enum(someproject_component, enumname, enumtype, enumfield, enumval)
+ *
+ * Where "someproject_component" and "enumname" match those in the
+ * TRACEPOINT_ENUM, "enumtype" is a signed or unsigned integer type
+ * backing the enumeration, "enumfield" is the name of the field and
+ * "enumval" is the value.
+ */
+
+#define TRACEPOINT_ENUM(provider, name, values)
+
+#endif /* #ifndef TRACEPOINT_ENUM */
+
 #ifndef TRACEPOINT_EVENT
 
 /*
@@ -453,6 +497,9 @@ __tracepoints__ptrs_destroy(void)
  *         * Integer, printed with 0x base 16 * 
  *         ctf_integer_hex(unsigned long, field_d, arg1)
  *
+ *         * Enumeration *
+ *         ctf_enum(someproject_component, enum_name, int, field_e, arg0)
+ *
  *         * 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)
index 232a9b90069c7af844a3e88b16d5128e37aa4a15..6ea64c8708e6fb2b36e3ee6c99274586c97d18e2 100644 (file)
@@ -43,7 +43,7 @@
 
 /* Version for ABI between liblttng-ust, sessiond, consumerd */
 #define LTTNG_UST_ABI_MAJOR_VERSION            6
-#define LTTNG_UST_ABI_MINOR_VERSION            0
+#define LTTNG_UST_ABI_MINOR_VERSION            1
 
 enum lttng_ust_instrumentation {
        LTTNG_UST_TRACEPOINT            = 0,
index 78e0cf727feb1a91c150c2a5b308bd8d3750c710..7a5f969eecd4ebd0fe50a0715e5d5e273dbbcbaf 100644 (file)
@@ -255,6 +255,7 @@ enum ustctl_socket_type {
 enum ustctl_notify_cmd {
        USTCTL_NOTIFY_CMD_EVENT = 0,
        USTCTL_NOTIFY_CMD_CHANNEL = 1,
+       USTCTL_NOTIFY_CMD_ENUM = 2,
 };
 
 enum ustctl_channel_header {
@@ -302,9 +303,21 @@ struct ustctl_float_type {
        char padding[USTCTL_UST_FLOAT_TYPE_PADDING];
 } LTTNG_PACKED;
 
+#define USTCTL_UST_ENUM_ENTRY_PADDING  32
+struct ustctl_enum_entry {
+       uint64_t start, end;            /* start and end are inclusive */
+       char string[LTTNG_UST_SYM_NAME_LEN];
+       char padding[USTCTL_UST_ENUM_ENTRY_PADDING];
+};
+
 #define USTCTL_UST_BASIC_TYPE_PADDING  296
 union _ustctl_basic_type {
        struct ustctl_integer_type integer;
+       struct {
+               char name[LTTNG_UST_SYM_NAME_LEN];
+               struct ustctl_integer_type container_type;
+               uint64_t id;    /* enum ID in sessiond. */
+       } enumeration;
        struct {
                enum ustctl_string_encodings encoding;
        } string;
@@ -403,6 +416,22 @@ int ustctl_reply_register_event(int sock,
        uint32_t id,                    /* event id (input) */
        int ret_code);                  /* return code. 0 ok, negative error */
 
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ */
+int ustctl_recv_register_enum(int sock,
+       int *session_objd,
+       char *enum_name,
+       struct ustctl_enum_entry **entries,
+       size_t *nr_entries);
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_reply_register_enum(int sock,
+       uint64_t id,                    /* enum id (input) */
+       int ret_code);
+
 /*
  * Returns 0 on success, negative UST or system error value on error.
  */
index b34c9d1ba696d19615a366e1e98ebb5273d51124..f7cbc1a6dd27c972f6ec195442c7c0bd8913de08 100644 (file)
@@ -176,7 +176,8 @@ struct lttng_float_type {
 union _lttng_basic_type {
        struct lttng_integer_type integer;
        struct {
-               const char *name;
+               const struct lttng_enum_desc *desc;     /* Enumeration mapping */
+               struct lttng_integer_type container_type;
        } enumeration;
        struct {
                enum lttng_string_encodings encoding;
@@ -210,11 +211,10 @@ struct lttng_type {
 };
 
 #define LTTNG_UST_ENUM_TYPE_PADDING    24
-struct lttng_enum {
+struct lttng_enum_desc {
        const char *name;
-       struct lttng_type container_type;
        const struct lttng_enum_entry *entries;
-       unsigned int len;
+       unsigned int nr_entries;
        char padding[LTTNG_UST_ENUM_TYPE_PADDING];
 };
 
@@ -422,6 +422,14 @@ struct lttng_event {
        int registered;                 /* has reg'd tracepoint probe */
 };
 
+struct lttng_enum {
+       const struct lttng_enum_desc *desc;
+       struct lttng_session *session;
+       struct cds_list_head node;      /* Enum list in session */
+       struct cds_hlist_node hlist;    /* Session ht of enums */
+       uint64_t id;                    /* Enumeration ID in sessiond */
+};
+
 struct channel;
 struct lttng_ust_shm_handle;
 
@@ -506,6 +514,13 @@ struct lttng_ust_event_ht {
        struct cds_hlist_head table[LTTNG_UST_EVENT_HT_SIZE];
 };
 
+#define LTTNG_UST_ENUM_HT_BITS         12
+#define LTTNG_UST_ENUM_HT_SIZE         (1U << LTTNG_UST_ENUM_HT_BITS)
+
+struct lttng_ust_enum_ht {
+       struct cds_hlist_head table[LTTNG_UST_ENUM_HT_SIZE];
+};
+
 /*
  * IMPORTANT: this structure is part of the ABI between the probe and
  * UST. Fields need to be only added at the end, never reordered, never
@@ -532,6 +547,10 @@ struct lttng_session {
 
        /* New UST 2.4 */
        int statedump_pending:1;
+
+       /* New UST 2.8 */
+       struct lttng_ust_enum_ht enums_ht;      /* ht of enumerations */
+       struct cds_list_head enums_head;
 };
 
 struct lttng_transport {
@@ -657,6 +676,8 @@ int lttng_session_active(void);
 typedef int (*t_statedump_func_ptr)(struct lttng_session *session);
 void lttng_handle_pending_statedump(void *owner);
 struct cds_list_head *_lttng_get_sessions(void);
+struct lttng_enum *lttng_ust_enum_get(struct lttng_session *session,
+               const char *enum_name);
 
 #ifdef __cplusplus
 }
index e87f31e31cb33011ebd047ac7c7c81151541676c..8cb142b2e7ed629b7c81cdada445cfff4eeaad3d 100644 (file)
@@ -54,3 +54,7 @@
 #undef ctf_string_nowrite
 #define ctf_string_nowrite(_item, _src)                                \
        _ctf_string(_item, _src, 1)
+
+#undef ctf_enum_nowrite
+#define ctf_enum_nowrite(_provider, _name, _type, _item, _src)         \
+       _ctf_enum(_provider, _name, _type, _item, _src, 1)
index f5981f84468656bbea9bc8a5bf3855eb78c7a592..c187061ca67da80a38ec2e6cfb409a09458a2af2 100644 (file)
@@ -28,6 +28,9 @@
 #undef TRACEPOINT_EVENT_INSTANCE
 #define TRACEPOINT_EVENT_INSTANCE(_provider, _template, _name, _args)
 
+#undef TRACEPOINT_ENUM
+#define TRACEPOINT_ENUM(_provider, _name, _values)
+
 #undef TP_ARGS
 #define TP_ARGS(...)
 
@@ -61,6 +64,9 @@
 #undef _ctf_string
 #define _ctf_string(_item, _src, _nowrite)
 
+#undef _ctf_enum
+#define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite)
+
 /* "write" */
 #undef ctf_integer
 #define ctf_integer(_type, _item, _src)
@@ -92,6 +98,9 @@
 #undef ctf_string
 #define ctf_string(_item, _src)
 
+#undef ctf_enum
+#define ctf_enum(_provider, _name, _type, _item, _src)
+
 /* "nowrite" */
 #undef ctf_integer_nowrite
 #define ctf_integer_nowrite(_type, _item, _src)
 
 #undef ctf_string_nowrite
 #define ctf_string_nowrite(_item, _src)
+
+#undef ctf_enum_nowrite
+#define ctf_enum_nowrite(_provider, _name, _type, _item, _src)
index 86c6adc6cea208233686ad1bf4f97a5d702ab037..444702fceab6a61f4edc200d2651240c9110f6c1 100644 (file)
@@ -66,3 +66,7 @@
 #undef ctf_string
 #define ctf_string(_item, _src)                                        \
        _ctf_string(_item, _src, 0)
+
+#undef ctf_enum
+#define ctf_enum(_provider, _name, _type, _item, _src)                 \
+       _ctf_enum(_provider, _name, _type, _item, _src, 0)
index d9aa6ce6bdb8f8496b7b7a1dc41facf20ca6a169..aa8b50f86e5a44aa055a72f3e89e46772efe8c10 100644 (file)
@@ -117,6 +117,35 @@ static const char                                                  \
 
 #include TRACEPOINT_INCLUDE
 
+/*
+ * Stage 0.9 of tracepoint event generation
+ *
+ * Unfolding the enums
+ */
+#include <lttng/ust-tracepoint-event-reset.h>
+
+/* Enumeration entry (single value) */
+#undef ctf_enum_value
+#define ctf_enum_value(_string, _value)                                        \
+       { _value, _value, _string },
+
+/* Enumeration entry (range) */
+#undef ctf_enum_range
+#define ctf_enum_range(_string, _range_start, _range_end)              \
+       { _range_start, _range_end, _string },
+
+#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                                                 \
+       };
+
+#include TRACEPOINT_INCLUDE
+
 /*
  * Stage 1 of tracepoint event generation.
  *
@@ -200,6 +229,31 @@ static const char                                                  \
          .nowrite = _nowrite,                                  \
        },
 
+#undef _ctf_enum
+#define _ctf_enum(_provider, _name, _type, _item, _src, _nowrite) \
+       {                                                       \
+               .name = #_item,                                 \
+               .type = {                                       \
+                       .atype = atype_enum,                    \
+                       .u = {                                  \
+                               .basic = {                      \
+                                       .enumeration = {        \
+                                               .desc = &__enum_##_provider##_##_name, \
+                                               .container_type = { \
+                                                       .size = sizeof(_type) * CHAR_BIT, \
+                                                       .alignment = lttng_alignof(_type) * CHAR_BIT, \
+                                                       .signedness = lttng_is_signed_type(_type), \
+                                                       .reverse_byte_order = 0, \
+                                                       .base = 10, \
+                                                       .encoding = lttng_encode_none, \
+                                               },              \
+                                       },                      \
+                                },                             \
+                       },                                      \
+               },                                              \
+               .nowrite = _nowrite,                            \
+       },
+
 #undef TP_FIELDS
 #define TP_FIELDS(...) __VA_ARGS__     /* Only one used in this phase */
 
@@ -209,6 +263,14 @@ static const char                                                  \
                _fields                                                                      \
        };
 
+#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),     \
+       };
+
 #include TRACEPOINT_INCLUDE
 
 /*
@@ -230,7 +292,7 @@ static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args));
 #include TRACEPOINT_INCLUDE
 
 /*
- * Stage 3 of tracepoint event generation.
+ * Stage 3.0 of tracepoint event generation.
  *
  * Create static inline function that calculates event size.
  */
@@ -268,6 +330,10 @@ static void __event_probe__##_provider##___##_name(_TP_ARGS_DATA_PROTO(_args));
 #define _ctf_string(_item, _src, _nowrite)                                    \
        __event_len += __dynamic_len[__dynamic_len_idx++] = strlen(_src) + 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__
 
@@ -410,6 +476,10 @@ size_t __event_get_size__##_provider##___##_name(size_t *__dynamic_len, _TP_ARGS
                __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__
 
@@ -427,8 +497,6 @@ void __event_prepare_filter_stack__##_provider##___##_name(char *__stack_data,\
 
 #include TRACEPOINT_INCLUDE
 
-
-
 /*
  * Stage 4 of tracepoint event generation.
  *
@@ -460,6 +528,10 @@ void __event_prepare_filter_stack__##_provider##___##_name(char *__stack_data,\
 #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__
 
@@ -544,6 +616,10 @@ size_t __event_get_align__##_provider##___##_name(_TP_ARGS_PROTO(_args))      \
                __chan->ops->event_write(&__ctx, _src,                  \
                        __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
 #define __get_dynamic_len(field)       __stackvar.__dynamic_len[__dynamic_len_idx++]
@@ -726,7 +802,11 @@ const struct lttng_event_desc __event_desc___##_provider##_##_name = {            \
        .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 } }, \
+       .u = {                                                                 \
+           .ext = {                                                           \
+                 .model_emf_uri = &__ref_model_emf_uri___##_provider##___##_name, \
+               },                                                             \
+       },                                                                     \
 };
 
 #include TRACEPOINT_INCLUDE
index b9bbb39bbbeeea702d045e818096b5a188960417..efebbb2a73f830eb5f86adb6c247c528ce89ab19 100644 (file)
@@ -31,6 +31,7 @@
 #include <lttng/ust-abi.h>
 #include <lttng/ust-error.h>
 #include <lttng/ust-compiler.h>
+#include <lttng/ust-ctl.h>
 #include <config.h>
 
 /*
@@ -50,6 +51,9 @@
 
 struct lttng_event_field;
 struct lttng_ctx_field;
+struct lttng_enum_entry;
+struct lttng_integer_type;
+struct lttng_session;
 
 struct ustctl_reg_msg {
        uint32_t magic;
@@ -147,6 +151,22 @@ struct ustcomm_notify_event_reply {
        char padding[USTCOMM_NOTIFY_EVENT_REPLY_PADDING];
 } LTTNG_PACKED;
 
+#define USTCOMM_NOTIFY_ENUM_MSG_PADDING                32
+struct ustcomm_notify_enum_msg {
+       uint32_t session_objd;
+       char enum_name[LTTNG_UST_SYM_NAME_LEN];
+       uint32_t entries_len;
+       char padding[USTCOMM_NOTIFY_ENUM_MSG_PADDING];
+       /* followed by enum entries */
+} LTTNG_PACKED;
+
+#define USTCOMM_NOTIFY_EVENT_REPLY_PADDING     32
+struct ustcomm_notify_enum_reply {
+       int32_t ret_code;       /* 0: ok, negative: error code */
+       uint64_t enum_id;
+       char padding[USTCOMM_NOTIFY_EVENT_REPLY_PADDING];
+} LTTNG_PACKED;
+
 #define USTCOMM_NOTIFY_CHANNEL_MSG_PADDING     32
 struct ustcomm_notify_channel_msg {
        uint32_t session_objd;
@@ -213,6 +233,7 @@ int ustcomm_send_reg_msg(int sock,
  * Returns -EPIPE or -ECONNRESET if other end has hung up.
  */
 int ustcomm_register_event(int sock,
+       struct lttng_session *session,
        int session_objd,               /* session descriptor */
        int channel_objd,               /* channel descriptor */
        const char *event_name,         /* event name (input) */
@@ -223,6 +244,17 @@ int ustcomm_register_event(int sock,
        const char *model_emf_uri,
        uint32_t *id);                  /* event id (output) */
 
+/*
+ * Returns 0 on success, negative error value on error.
+ * Returns -EPIPE or -ECONNRESET if other end has hung up.
+ */
+int ustcomm_register_enum(int sock,
+       int session_objd,               /* session descriptor */
+       const char *enum_name,          /* enum name (input) */
+       size_t nr_entries,              /* entries */
+       const struct lttng_enum_entry *entries,
+       uint64_t *id);                  /* enum id (output) */
+
 /*
  * Returns 0 on success, negative error value on error.
  * Returns -EPIPE or -ECONNRESET if other end has hung up.
index d213770f7a25f69059810d14d5f12569636cba2b..42c9ddb2eae152d88acdba3e177ab9482b4426e8 100644 (file)
@@ -697,7 +697,22 @@ int serialize_string_encoding(enum ustctl_string_encodings *ue,
 }
 
 static
-int serialize_basic_type(enum ustctl_abstract_types *uatype,
+int serialize_integer_type(struct ustctl_integer_type *uit,
+               const struct lttng_integer_type *lit)
+{
+       uit->size = lit->size;
+       uit->signedness = lit->signedness;
+       uit->reverse_byte_order = lit->reverse_byte_order;
+       uit->base = lit->base;
+       if (serialize_string_encoding(&uit->encoding, lit->encoding))
+               return -EINVAL;
+       uit->alignment = lit->alignment;
+       return 0;
+}
+
+static
+int serialize_basic_type(struct lttng_session *session,
+               enum ustctl_abstract_types *uatype,
                enum lttng_abstract_types atype,
                union _ustctl_basic_type *ubt,
                const union _lttng_basic_type *lbt)
@@ -705,18 +720,8 @@ int serialize_basic_type(enum ustctl_abstract_types *uatype,
        switch (atype) {
        case atype_integer:
        {
-               struct ustctl_integer_type *uit;
-               const struct lttng_integer_type *lit;
-
-               uit = &ubt->integer;
-               lit = &lbt->integer;
-               uit->size = lit->size;
-               uit->signedness = lit->signedness;
-               uit->reverse_byte_order = lit->reverse_byte_order;
-               uit->base = lit->base;
-               if (serialize_string_encoding(&uit->encoding, lit->encoding))
+               if (serialize_integer_type(&ubt->integer, &lbt->integer))
                        return -EINVAL;
-               uit->alignment = lit->alignment;
                *uatype = ustctl_atype_integer;
                break;
        }
@@ -743,6 +748,27 @@ int serialize_basic_type(enum ustctl_abstract_types *uatype,
                break;
        }
        case atype_enum:
+       {
+               strncpy(ubt->enumeration.name, lbt->enumeration.desc->name,
+                               LTTNG_UST_SYM_NAME_LEN);
+               ubt->enumeration.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+               if (serialize_integer_type(&ubt->enumeration.container_type,
+                               &lbt->enumeration.container_type))
+                       return -EINVAL;
+               if (session) {
+                       const struct lttng_enum *_enum;
+
+                       _enum = lttng_ust_enum_get(session,
+                                       lbt->enumeration.desc->name);
+                       if (!_enum)
+                               return -EINVAL;
+                       ubt->enumeration.id = _enum->id;
+               } else {
+                       ubt->enumeration.id = -1ULL;
+               }
+               *uatype = ustctl_atype_enum;
+               break;
+       }
        case atype_array:
        case atype_sequence:
        default:
@@ -752,7 +778,8 @@ int serialize_basic_type(enum ustctl_abstract_types *uatype,
 }
 
 static
-int serialize_one_type(struct ustctl_type *ut, const struct lttng_type *lt)
+int serialize_one_type(struct lttng_session *session,
+               struct ustctl_type *ut, const struct lttng_type *lt)
 {
        int ret;
 
@@ -760,7 +787,8 @@ int serialize_one_type(struct ustctl_type *ut, const struct lttng_type *lt)
        case atype_integer:
        case atype_float:
        case atype_string:
-               ret = serialize_basic_type(&ut->atype, lt->atype,
+       case atype_enum:
+               ret = serialize_basic_type(session, &ut->atype, lt->atype,
                        &ut->u.basic, &lt->u.basic);
                if (ret)
                        return ret;
@@ -774,7 +802,7 @@ int serialize_one_type(struct ustctl_type *ut, const struct lttng_type *lt)
                ubt = &ut->u.array.elem_type;
                lbt = &lt->u.array.elem_type;
                ut->u.array.length = lt->u.array.length;
-               ret = serialize_basic_type(&ubt->atype, lbt->atype,
+               ret = serialize_basic_type(session, &ubt->atype, lbt->atype,
                        &ubt->u.basic, &lbt->u.basic);
                if (ret)
                        return -EINVAL;
@@ -789,20 +817,19 @@ int serialize_one_type(struct ustctl_type *ut, const struct lttng_type *lt)
 
                ubt = &ut->u.sequence.length_type;
                lbt = &lt->u.sequence.length_type;
-               ret = serialize_basic_type(&ubt->atype, lbt->atype,
+               ret = serialize_basic_type(session, &ubt->atype, lbt->atype,
                        &ubt->u.basic, &lbt->u.basic);
                if (ret)
                        return -EINVAL;
                ubt = &ut->u.sequence.elem_type;
                lbt = &lt->u.sequence.elem_type;
-               ret = serialize_basic_type(&ubt->atype, lbt->atype,
+               ret = serialize_basic_type(session, &ubt->atype, lbt->atype,
                        &ubt->u.basic, &lbt->u.basic);
                if (ret)
                        return -EINVAL;
                ut->atype = ustctl_atype_sequence;
                break;
        }
-       case atype_enum:
        default:
                return -EINVAL;
        }
@@ -810,7 +837,8 @@ int serialize_one_type(struct ustctl_type *ut, const struct lttng_type *lt)
 }
 
 static
-int serialize_fields(size_t *_nr_write_fields,
+int serialize_fields(struct lttng_session *session,
+               size_t *_nr_write_fields,
                struct ustctl_field **ustctl_fields,
                size_t nr_fields,
                const struct lttng_event_field *lttng_fields)
@@ -835,7 +863,7 @@ int serialize_fields(size_t *_nr_write_fields,
                        continue;
                strncpy(f->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
                f->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
-               ret = serialize_one_type(&f->type, &lf->type);
+               ret = serialize_one_type(session, &f->type, &lf->type);
                if (ret)
                        goto error_type;
                nr_write_fields++;
@@ -850,6 +878,34 @@ error_type:
        return ret;
 }
 
+static
+int serialize_entries(struct ustctl_enum_entry **_entries,
+               size_t nr_entries,
+               const struct lttng_enum_entry *lttng_entries)
+{
+       struct ustctl_enum_entry *entries;
+       int i;
+
+       /* Serialize the entries */
+       entries = zmalloc(nr_entries * sizeof(*entries));
+       if (!entries)
+               return -ENOMEM;
+       for (i = 0; i < nr_entries; i++) {
+               struct ustctl_enum_entry *uentry;
+               const struct lttng_enum_entry *lentry;
+
+               uentry = &entries[i];
+               lentry = &lttng_entries[i];
+
+               uentry->start = lentry->start;
+               uentry->end = lentry->end;
+               strncpy(uentry->string, lentry->string, LTTNG_UST_SYM_NAME_LEN);
+               uentry->string[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+       }
+       *_entries = entries;
+       return 0;
+}
+
 static
 int serialize_ctx_fields(size_t *_nr_write_fields,
                struct ustctl_field **ustctl_fields,
@@ -876,7 +932,7 @@ int serialize_ctx_fields(size_t *_nr_write_fields,
                        continue;
                strncpy(f->name, lf->name, LTTNG_UST_SYM_NAME_LEN);
                f->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
-               ret = serialize_one_type(&f->type, &lf->type);
+               ret = serialize_one_type(NULL, &f->type, &lf->type);
                if (ret)
                        goto error_type;
                nr_write_fields++;
@@ -895,6 +951,7 @@ error_type:
  * Returns 0 on success, negative error value on error.
  */
 int ustcomm_register_event(int sock,
+       struct lttng_session *session,
        int session_objd,               /* session descriptor */
        int channel_objd,               /* channel descriptor */
        const char *event_name,         /* event name (input) */
@@ -931,7 +988,7 @@ int ustcomm_register_event(int sock,
 
        /* Calculate fields len, serialize fields. */
        if (nr_fields > 0) {
-               ret = serialize_fields(&nr_write_fields, &fields,
+               ret = serialize_fields(session, &nr_write_fields, &fields,
                                nr_fields, lttng_fields);
                if (ret)
                        return ret;
@@ -945,14 +1002,15 @@ int ustcomm_register_event(int sock,
                model_emf_uri_len = 0;
        }
        msg.m.model_emf_uri_len = model_emf_uri_len;
+
        len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
        if (len > 0 && len != sizeof(msg)) {
-               free(fields);
-               return -EIO;
+               ret = -EIO;
+               goto error_fields;
        }
        if (len < 0) {
-               free(fields);
-               return len;
+               ret = len;
+               goto error_fields;
        }
 
        /* send signature */
@@ -971,10 +1029,12 @@ int ustcomm_register_event(int sock,
                len = ustcomm_send_unix_sock(sock, fields, fields_len);
                free(fields);
                if (len > 0 && len != fields_len) {
-                       return -EIO;
+                       ret = -EIO;
+                       goto error_fields;
                }
                if (len < 0) {
-                       return len;
+                       ret = len;
+                       goto error_fields;
                }
        } else {
                free(fields);
@@ -984,10 +1044,14 @@ int ustcomm_register_event(int sock,
                /* send model_emf_uri */
                len = ustcomm_send_unix_sock(sock, model_emf_uri,
                                model_emf_uri_len);
-               if (len > 0 && len != model_emf_uri_len)
-                       return -EIO;
-               if (len < 0)
-                       return len;
+               if (len > 0 && len != model_emf_uri_len) {
+                       ret = -EIO;
+                       goto error_fields;
+               }
+               if (len < 0) {
+                       ret = len;
+                       goto error_fields;
+               }
        }
 
        /* receive reply */
@@ -1021,6 +1085,114 @@ int ustcomm_register_event(int sock,
                        return len;
                }
        }
+
+error_fields:
+       free(fields);
+       return ret;
+}
+
+/*
+ * Returns 0 on success, negative error value on error.
+ * Returns -EPIPE or -ECONNRESET if other end has hung up.
+ */
+int ustcomm_register_enum(int sock,
+       int session_objd,               /* session descriptor */
+       const char *enum_name,          /* enum name (input) */
+       size_t nr_entries,              /* entries */
+       const struct lttng_enum_entry *lttng_entries,
+       uint64_t *id)
+{
+       ssize_t len;
+       struct {
+               struct ustcomm_notify_hdr header;
+               struct ustcomm_notify_enum_msg m;
+       } msg;
+       struct {
+               struct ustcomm_notify_hdr header;
+               struct ustcomm_notify_enum_reply r;
+       } reply;
+       size_t entries_len;
+       struct ustctl_enum_entry *entries = NULL;
+       int ret;
+
+       memset(&msg, 0, sizeof(msg));
+       msg.header.notify_cmd = USTCTL_NOTIFY_CMD_ENUM;
+       msg.m.session_objd = session_objd;
+       strncpy(msg.m.enum_name, enum_name, LTTNG_UST_SYM_NAME_LEN);
+       msg.m.enum_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+
+       /* Calculate entries len, serialize entries. */
+       if (nr_entries > 0) {
+               ret = serialize_entries(&entries,
+                               nr_entries, lttng_entries);
+               if (ret)
+                       return ret;
+       }
+
+       entries_len = sizeof(*entries) * nr_entries;
+       msg.m.entries_len = entries_len;
+
+       len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
+       if (len > 0 && len != sizeof(msg)) {
+               ret = -EIO;
+               goto error_entries;
+       }
+       if (len < 0) {
+               ret = len;
+               goto error_entries;
+       }
+
+       /* send entries */
+       if (entries_len > 0) {
+               len = ustcomm_send_unix_sock(sock, entries, entries_len);
+               if (len > 0 && len != entries_len) {
+                       ret = -EIO;
+                       goto error_entries;
+               }
+               if (len < 0) {
+                       ret = len;
+                       goto error_entries;
+               }
+       }
+       free(entries);
+       entries = NULL;
+
+       /* receive reply */
+       len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
+       switch (len) {
+       case 0: /* orderly shutdown */
+               return -EPIPE;
+       case sizeof(reply):
+               if (reply.header.notify_cmd != msg.header.notify_cmd) {
+                       ERR("Unexpected result message command "
+                               "expected: %u vs received: %u\n",
+                               msg.header.notify_cmd, reply.header.notify_cmd);
+                       return -EINVAL;
+               }
+               if (reply.r.ret_code > 0)
+                       return -EINVAL;
+               if (reply.r.ret_code < 0)
+                       return reply.r.ret_code;
+               *id = reply.r.enum_id;
+               DBG("Sent register enum notification for name \"%s\": ret_code %d\n",
+                       enum_name, reply.r.ret_code);
+               return 0;
+       default:
+               if (len < 0) {
+                       /* Transport level error */
+                       if (errno == EPIPE || errno == ECONNRESET)
+                               len = -errno;
+                       return len;
+               } else {
+                       ERR("incorrect message size: %zd\n", len);
+                       return len;
+               }
+       }
+       return ret;
+
+error_entries:
+       free(entries);
+       return ret;
 }
 
 /*
index 6b6f295b38bd81ff4ce3e26ad47f7ea37c351fc0..75b32fe527c8fa9d32af7c9f0be501ddb892045d 100644 (file)
@@ -1759,6 +1759,9 @@ int ustctl_recv_notify(int sock, enum ustctl_notify_cmd *notify_cmd)
        case 1:
                *notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL;
                break;
+       case 2:
+               *notify_cmd = USTCTL_NOTIFY_CMD_ENUM;
+               break;
        default:
                return -EINVAL;
        }
@@ -1911,6 +1914,90 @@ int ustctl_reply_register_event(int sock,
        return 0;
 }
 
+/*
+ * Returns 0 on success, negative UST or system error value on error.
+ */
+int ustctl_recv_register_enum(int sock,
+       int *session_objd,
+       char *enum_name,
+       struct ustctl_enum_entry **entries,
+       size_t *nr_entries)
+{
+       ssize_t len;
+       struct ustcomm_notify_enum_msg msg;
+       size_t entries_len;
+       struct ustctl_enum_entry *a_entries = NULL;
+
+       len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg));
+       if (len > 0 && len != sizeof(msg))
+               return -EIO;
+       if (len == 0)
+               return -EPIPE;
+       if (len < 0)
+               return len;
+
+       *session_objd = msg.session_objd;
+       strncpy(enum_name, msg.enum_name, LTTNG_UST_SYM_NAME_LEN);
+       enum_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+       entries_len = msg.entries_len;
+
+       if (entries_len % sizeof(*a_entries) != 0) {
+               return -EINVAL;
+       }
+
+       /* recv entries */
+       if (entries_len) {
+               a_entries = zmalloc(entries_len);
+               if (!a_entries)
+                       return -ENOMEM;
+               len = ustcomm_recv_unix_sock(sock, a_entries, entries_len);
+               if (len > 0 && len != entries_len) {
+                       len = -EIO;
+                       goto entries_error;
+               }
+               if (len == 0) {
+                       len = -EPIPE;
+                       goto entries_error;
+               }
+               if (len < 0) {
+                       goto entries_error;
+               }
+       }
+       *nr_entries = entries_len / sizeof(*a_entries);
+       *entries = a_entries;
+
+       return 0;
+
+entries_error:
+       free(a_entries);
+       return len;
+}
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_reply_register_enum(int sock,
+       uint64_t id,
+       int ret_code)
+{
+       ssize_t len;
+       struct {
+               struct ustcomm_notify_hdr header;
+               struct ustcomm_notify_enum_reply r;
+       } reply;
+
+       memset(&reply, 0, sizeof(reply));
+       reply.header.notify_cmd = USTCTL_NOTIFY_CMD_ENUM;
+       reply.r.ret_code = ret_code;
+       reply.r.enum_id = id;
+       len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply));
+       if (len > 0 && len != sizeof(reply))
+               return -EIO;
+       if (len < 0)
+               return len;
+       return 0;
+}
+
 /*
  * Returns 0 on success, negative UST or system error value on error.
  */
index 25b4962583a833811014cf50558f46ea4a5aa7e3..eb85b50d24e4e09ec128cf0ebd8f407e8f293623 100644 (file)
@@ -72,6 +72,7 @@ struct cds_list_head *_lttng_get_sessions(void)
 }
 
 static void _lttng_event_destroy(struct lttng_event *event);
+static void _lttng_enum_destroy(struct lttng_enum *_enum);
 
 static
 void lttng_session_lazy_sync_enablers(struct lttng_session *session);
@@ -139,9 +140,12 @@ struct lttng_session *lttng_session_create(void)
                return NULL;
        CDS_INIT_LIST_HEAD(&session->chan_head);
        CDS_INIT_LIST_HEAD(&session->events_head);
+       CDS_INIT_LIST_HEAD(&session->enums_head);
        CDS_INIT_LIST_HEAD(&session->enablers_head);
        for (i = 0; i < LTTNG_UST_EVENT_HT_SIZE; i++)
                CDS_INIT_HLIST_HEAD(&session->events_ht.table[i]);
+       for (i = 0; i < LTTNG_UST_ENUM_HT_SIZE; i++)
+               CDS_INIT_HLIST_HEAD(&session->enums_ht.table[i]);
        cds_list_add(&session->node, &sessions);
        return session;
 }
@@ -212,6 +216,7 @@ void lttng_session_destroy(struct lttng_session *session)
 {
        struct lttng_channel *chan, *tmpchan;
        struct lttng_event *event, *tmpevent;
+       struct lttng_enum *_enum, *tmp_enum;
        struct lttng_enabler *enabler, *tmpenabler;
 
        CMM_ACCESS_ONCE(session->active) = 0;
@@ -225,6 +230,9 @@ void lttng_session_destroy(struct lttng_session *session)
        cds_list_for_each_entry_safe(event, tmpevent,
                        &session->events_head, node)
                _lttng_event_destroy(event);
+       cds_list_for_each_entry_safe(_enum, tmp_enum,
+                       &session->enums_head, node)
+               _lttng_enum_destroy(_enum);
        cds_list_for_each_entry_safe(chan, tmpchan, &session->chan_head, node)
                _lttng_channel_unmap(chan);
        cds_list_del(&session->node);
@@ -350,6 +358,101 @@ end:
        return ret;
 }
 
+static
+int lttng_enum_create(const struct lttng_enum_desc *desc,
+               struct lttng_session *session)
+{
+       const char *enum_name = desc->name;
+       struct lttng_enum *_enum;
+       struct cds_hlist_head *head;
+       struct cds_hlist_node *node;
+       int ret = 0;
+       size_t name_len = strlen(enum_name);
+       uint32_t hash;
+       int notify_socket;
+
+       hash = jhash(enum_name, name_len, 0);
+       head = &session->enums_ht.table[hash & (LTTNG_UST_ENUM_HT_SIZE - 1)];
+       cds_hlist_for_each_entry(_enum, node, head, hlist) {
+               assert(_enum->desc);
+               if (!strncmp(_enum->desc->name, desc->name,
+                               LTTNG_UST_SYM_NAME_LEN - 1)) {
+                       ret = -EEXIST;
+                       goto exist;
+               }
+       }
+
+       notify_socket = lttng_get_notify_socket(session->owner);
+       if (notify_socket < 0) {
+               ret = notify_socket;
+               goto socket_error;
+       }
+
+       _enum = zmalloc(sizeof(*_enum));
+       if (!_enum) {
+               ret = -ENOMEM;
+               goto cache_error;
+       }
+       _enum->session = session;
+       _enum->desc = desc;
+
+       ret = ustcomm_register_enum(notify_socket,
+               session->objd,
+               enum_name,
+               desc->nr_entries,
+               desc->entries,
+               &_enum->id);
+       if (ret < 0) {
+               DBG("Error (%d) registering enumeration to sessiond", ret);
+               goto sessiond_register_error;
+       }
+       cds_list_add(&_enum->node, &session->enums_head);
+       cds_hlist_add_head(&_enum->hlist, head);
+       return 0;
+
+sessiond_register_error:
+       free(_enum);
+cache_error:
+socket_error:
+exist:
+       return ret;
+}
+
+static
+int lttng_event_create_all_enums(const struct lttng_event_desc *desc,
+               struct lttng_session *session)
+{
+       unsigned int nr_fields, i;
+       const struct lttng_event_field *fields;
+
+       /* For each field, ensure enum is part of the session. */
+       nr_fields = desc->nr_fields;
+       fields = desc->fields;
+       for (i = 0; i < nr_fields; i++) {
+               const struct lttng_type *type = &fields[i].type;
+
+               switch (type->atype) {
+               case atype_enum:
+               {
+                       const struct lttng_enum_desc *enum_desc;
+                       int ret;
+
+                       enum_desc = type->u.basic.enumeration.desc;
+                       ret = lttng_enum_create(enum_desc, session);
+                       if (ret && ret != -EEXIST) {
+                               DBG("Unable to create enum error: (%d)", ret);
+                               return ret;
+                       }
+                       break;
+               }
+               default:
+                       /* TODO: nested types when they become supported. */
+                       continue;
+               }
+       }
+       return 0;
+}
+
 /*
  * Supports event creation while tracing session is active.
  */
@@ -386,6 +489,12 @@ int lttng_event_create(const struct lttng_event_desc *desc,
                goto socket_error;
        }
 
+       ret = lttng_event_create_all_enums(desc, session);
+       if (ret < 0) {
+               DBG("Error (%d) adding enum to session", ret);
+               goto create_enum_error;
+       }
+
        /*
         * Check if loglevel match. Refuse to connect event if not.
         */
@@ -414,6 +523,7 @@ int lttng_event_create(const struct lttng_event_desc *desc,
 
        /* Fetch event ID from sessiond */
        ret = ustcomm_register_event(notify_socket,
+               session,
                session->objd,
                chan->objd,
                event_name,
@@ -437,6 +547,7 @@ int lttng_event_create(const struct lttng_event_desc *desc,
 sessiond_register_error:
        free(event);
 cache_error:
+create_enum_error:
 socket_error:
 exist:
        return ret;
@@ -719,6 +830,13 @@ void _lttng_event_destroy(struct lttng_event *event)
        free(event);
 }
 
+static
+void _lttng_enum_destroy(struct lttng_enum *_enum)
+{
+       cds_list_del(&_enum->node);
+       free(_enum);
+}
+
 void lttng_ust_events_exit(void)
 {
        struct lttng_session *session, *tmpsession;
index 60cdbfa91a2c876f5d5ae05db7a6ceae2a065df6..60751dc32a9aa56058e1452f3e9ddec4a395981b 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdlib.h>
 #include <lttng/ust-events.h>
 #include <usterr-signal-safe.h>
+#include "jhash.h"
 
 static CDS_LIST_HEAD(lttng_transport_list);
 
@@ -56,3 +57,26 @@ void lttng_transport_unregister(struct lttng_transport *transport)
 {
        cds_list_del(&transport->node);
 }
+
+/*
+ * Needed by comm layer.
+ */
+struct lttng_enum *lttng_ust_enum_get(struct lttng_session *session,
+               const char *enum_name)
+{
+       struct lttng_enum *_enum;
+       struct cds_hlist_head *head;
+       struct cds_hlist_node *node;
+       size_t name_len = strlen(enum_name);
+       uint32_t hash;
+
+       hash = jhash(enum_name, name_len, 0);
+       head = &session->enums_ht.table[hash & (LTTNG_UST_ENUM_HT_SIZE - 1)];
+       cds_hlist_for_each_entry(_enum, node, head, hlist) {
+               assert(_enum->desc);
+               if (!strncmp(_enum->desc->name, enum_name,
+                               LTTNG_UST_SYM_NAME_LEN - 1))
+                       return _enum;
+       }
+       return NULL;
+}
index 3d7ceeb9d9cb874f1f8215a4f355c9af16b9dcf3..be300c86e0443c531754fdd6e44358f79993b655 100644 (file)
@@ -1,4 +1,5 @@
-SUBDIRS = utils hello same_line_tracepoint snprintf benchmark ust-elf
+SUBDIRS = utils hello same_line_tracepoint snprintf benchmark ust-elf \
+               ctf-types
 
 if CXX_WORKS
 SUBDIRS += hello.cxx
diff --git a/tests/ctf-types/Makefile.am b/tests/ctf-types/Makefile.am
new file mode 100644 (file)
index 0000000..366870e
--- /dev/null
@@ -0,0 +1,13 @@
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include -Wsystem-headers
+
+noinst_PROGRAMS = ctf-types
+ctf_types_SOURCES = ctf-types.c tp.c ust_tests_ctf_types.h
+ctf_types_LDADD = $(top_builddir)/liblttng-ust/liblttng-ust.la
+ctf_types_CFLAGS = -Werror=old-style-definition
+
+if LTTNG_UST_BUILD_WITH_LIBDL
+ctf_types_LDADD += -ldl
+endif
+if LTTNG_UST_BUILD_WITH_LIBC_DL
+ctf_types_LDADD += -lc
+endif
diff --git a/tests/ctf-types/README b/tests/ctf-types/README
new file mode 100644 (file)
index 0000000..0198653
--- /dev/null
@@ -0,0 +1,3 @@
+This is a "hello world" application used to verify that an instrumented program
+with tracepoints using type declarations in CTF metadata can be built
+successfully.
diff --git a/tests/ctf-types/ctf-types.c b/tests/ctf-types/ctf-types.c
new file mode 100644 (file)
index 0000000..006976a
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014  Geneviève Bastien <gbastien@versatic.net>
+ *
+ * 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.
+ *
+ * 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
+ */
+
+#include <unistd.h>
+
+#define TRACEPOINT_DEFINE
+#include "ust_tests_ctf_types.h"
+
+int main(int argc, char **argv)
+{
+       int i;
+       int delay = 0;
+
+       if (argc == 2)
+               delay = atoi(argv[1]);
+
+       fprintf(stderr, "Hello, World!\n");
+
+       sleep(delay);
+
+       fprintf(stderr, "Tracing... ");
+       for (i = 0; i < 100; i++) {
+               tracepoint(ust_tests_ctf_types, tptest, i, i % 6,
+                       i % 21);
+       }
+
+       for (i = 0; i < 10; i++) {
+               tracepoint(ust_tests_ctf_types, tptest_bis, i, i % 6);
+       }
+       fprintf(stderr, " done.\n");
+       return 0;
+}
diff --git a/tests/ctf-types/tp.c b/tests/ctf-types/tp.c
new file mode 100644 (file)
index 0000000..6a33fca
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * tp.c
+ *
+ * Copyright (c) 2014 Geneviève Bastien <gbastien@versatic.net>
+ *
+ * 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.
+ */
+
+#define TRACEPOINT_CREATE_PROBES
+#include "ust_tests_ctf_types.h"
diff --git a/tests/ctf-types/ust_tests_ctf_types.h b/tests/ctf-types/ust_tests_ctf_types.h
new file mode 100644 (file)
index 0000000..e789cbe
--- /dev/null
@@ -0,0 +1,83 @@
+#undef TRACEPOINT_PROVIDER
+#define TRACEPOINT_PROVIDER ust_tests_ctf_types
+
+#if !defined(_TRACEPOINT_UST_TESTS_CTF_TYPES_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
+#define _TRACEPOINT_UST_TESTS_CTF_TYPES_H
+
+/*
+ * Copyright (C) 2014 Geneviève Bastien <gbastien@versatic.net>
+ *
+ * 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.
+ */
+
+#include <lttng/tracepoint.h>
+
+TRACEPOINT_ENUM(ust_tests_ctf_types, testenum,
+       TP_ENUM_VALUES(
+               ctf_enum_value("even", 0)
+               ctf_enum_value("uneven", 1)
+               ctf_enum_range("twoto4", 2, 4)
+               ctf_enum_value("five\"extra\\test", 5)
+       )
+)
+
+TRACEPOINT_ENUM(ust_tests_ctf_types, testenum2,
+       TP_ENUM_VALUES(
+               ctf_enum_value("zero", 0)
+               ctf_enum_value("five", 5)
+               ctf_enum_range("ten_to_twenty", 10, 20)
+       )
+)
+
+/*
+ * Enumeration field is used twice to make sure the type declaration
+ * is entered only once in the metadata file.
+ */
+TRACEPOINT_EVENT(ust_tests_ctf_types, tptest,
+       TP_ARGS(int, anint, int, enumval, int, enumval2),
+       TP_FIELDS(
+               ctf_integer(int, intfield, anint)
+               ctf_enum(ust_tests_ctf_types, testenum, int, enumfield, enumval)
+               ctf_enum(ust_tests_ctf_types, testenum, long long,
+                               enumfield_bis, enumval)
+               ctf_enum(ust_tests_ctf_types, testenum2, unsigned int,
+                               enumfield_third, enumval2)
+       )
+)
+
+/*
+ * Another tracepoint using the types to make sure each type is entered
+ * only once in the metadata file.
+ */
+TRACEPOINT_EVENT(ust_tests_ctf_types, tptest_bis,
+       TP_ARGS(int, anint, int, enumval),
+       TP_FIELDS(
+               ctf_integer(int, intfield, anint)
+               ctf_enum(ust_tests_ctf_types, testenum, unsigned char,
+                       enumfield, enumval)
+       )
+)
+
+#endif /* _TRACEPOINT_UST_TESTS_CTF_TYPES_H */
+
+#undef TRACEPOINT_INCLUDE
+#define TRACEPOINT_INCLUDE "./ust_tests_ctf_types.h"
+
+/* This part must be outside ifdef protection */
+#include <lttng/tracepoint-event.h>
This page took 0.045253 seconds and 4 git commands to generate.