Reorganize tree
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 12 Oct 2022 11:04:29 +0000 (12:04 +0100)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 12 Oct 2022 11:04:29 +0000 (12:04 +0100)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
.gitignore
Makefile
include/side/macros.h [new file with mode: 0644]
include/side/trace.h [new file with mode: 0644]
src/Makefile [new file with mode: 0644]
src/test.c [new file with mode: 0644]
src/tracer.c [new file with mode: 0644]
src/tracer.h [new file with mode: 0644]
test.c [deleted file]

index ee4c92682341e4f8239f7875b78e55348f1b150e..3ebeca930a7fbf64f1583212640aa5848b93dd32 100644 (file)
@@ -1 +1,2 @@
-/test
+/src/test
+*.o
index 496f212ed3f7d6c15db43ca01de20c5d5ec05bfe..214d04ff20dc6b73ed8d2131a66088d08d3ee48c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,9 +1,7 @@
-all: test
+SUBDIRS := src/
 
-test: test.c
-       gcc -O2 -g -Wall -o test test.c
+all: $(SUBDIRS)
+$(SUBDIRS):
+       $(MAKE) -C $@
 
-.PHONY: clean
-
-clean:
-       rm -f test
+.PHONY: all $(SUBDIRS)
diff --git a/include/side/macros.h b/include/side/macros.h
new file mode 100644 (file)
index 0000000..7b97698
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#ifndef _SIDE_MACROS_H
+#define _SIDE_MACROS_H
+
+/* Helper macros */
+
+#define SIDE_ARRAY_SIZE(arr)   (sizeof(arr) / sizeof((arr)[0]))
+
+/*
+ * Compound literals with static storage are needed by SIDE
+ * instrumentation.
+ * Compound literals are part of the C99 and C11 standards, but not
+ * part of the C++ standards. They are supported by most C++ compilers
+ * though.
+ *
+ * Example use:
+ * static struct mystruct *var = LTTNG_UST_COMPOUND_LITERAL(struct mystruct, { 1, 2, 3 });
+ */
+#define SIDE_COMPOUND_LITERAL(type, ...)   (type[]) { __VA_ARGS__ }
+
+#define side_likely(x)         __builtin_expect(!!(x), 1)
+#define side_unlikely(x)       __builtin_expect(!!(x), 0)
+
+#define SIDE_PARAM(...)        __VA_ARGS__
+
+#endif /* _SIDE_MACROS_H */
diff --git a/include/side/trace.h b/include/side/trace.h
new file mode 100644 (file)
index 0000000..7b3875b
--- /dev/null
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#ifndef _SIDE_TRACE_H
+#define _SIDE_TRACE_H
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <side/macros.h>
+
+/* SIDE stands for "Static Instrumentation Dynamically Enabled" */
+
+struct side_arg_vec;
+struct side_type_description;
+struct side_event_field;
+
+enum side_type {
+       SIDE_TYPE_U8,
+       SIDE_TYPE_U16,
+       SIDE_TYPE_U32,
+       SIDE_TYPE_U64,
+       SIDE_TYPE_S8,
+       SIDE_TYPE_S16,
+       SIDE_TYPE_S32,
+       SIDE_TYPE_S64,
+       SIDE_TYPE_STRING,
+       SIDE_TYPE_DYNAMIC,
+       SIDE_TYPE_STRUCT,
+       SIDE_TYPE_ARRAY,
+       SIDE_TYPE_VLA,
+       SIDE_TYPE_VLA_VISITOR,
+       //TODO:
+       //specialized array and vla for fixed-size integers (optimization)
+       //variants (discriminated unions)
+};
+
+enum side_loglevel {
+       SIDE_LOGLEVEL_EMERG = 0,
+       SIDE_LOGLEVEL_ALERT = 1,
+       SIDE_LOGLEVEL_CRIT = 2,
+       SIDE_LOGLEVEL_ERR = 3,
+       SIDE_LOGLEVEL_WARNING = 4,
+       SIDE_LOGLEVEL_NOTICE = 5,
+       SIDE_LOGLEVEL_INFO = 6,
+       SIDE_LOGLEVEL_DEBUG = 7,
+};
+
+enum side_visitor_status {
+       SIDE_VISITOR_STATUS_ERROR = -1,
+       SIDE_VISITOR_STATUS_OK = 0,
+       SIDE_VISITOR_STATUS_END = 1,
+};
+
+typedef enum side_visitor_status (*side_visitor_begin)(void *ctx);
+typedef enum side_visitor_status (*side_visitor_end)(void *ctx);
+typedef enum side_visitor_status (*side_visitor_get_next)(void *ctx, struct side_arg_vec *sav_elem);
+
+struct side_type_description {
+       enum side_type type;
+       union {
+               struct {
+                       uint32_t nr_fields;
+                       const struct side_event_field *fields;
+               } side_struct;
+               struct {
+                       uint32_t length;
+                       const struct side_type_description *elem_type;
+               } side_array;
+               struct {
+                       const struct side_type_description *elem_type;
+               } side_vla;
+               struct {
+                       const struct side_type_description *elem_type;
+                       side_visitor_begin begin;
+                       side_visitor_end end;
+                       side_visitor_get_next get_next;
+               } side_vla_visitor;
+       } u;
+};
+
+struct side_event_field {
+       const char *field_name;
+       struct side_type_description side_type;
+};
+
+struct side_event_description {
+       uint32_t version;
+       uint32_t enabled;
+       uint32_t loglevel;      /* enum side_loglevel */
+       uint32_t nr_fields;
+       const char *provider_name;
+       const char *event_name;
+       const struct side_event_field *fields;
+};
+
+struct side_arg_vec {
+       uint32_t type;  /* enum side_type */
+       union {
+               uint8_t side_u8;
+               uint16_t side_u16;
+               uint32_t side_u32;
+               uint64_t side_u64;
+               int8_t side_s8;
+               int16_t side_s16;
+               int32_t side_s32;
+               int64_t side_s64;
+               const char *string;
+               const struct side_arg_vec_description *side_struct;
+               const struct side_arg_vec_description *side_array;
+               const struct side_arg_vec_description *side_vla;
+               void *side_vla_visitor_ctx;
+       } u;
+};
+
+struct side_arg_vec_description {
+       const struct side_arg_vec *sav;
+       uint32_t len;
+};
+
+#define side_type_decl(_type)                  { .type = _type }
+#define side_field(_type, _name)               { .field_name = _name, .side_type = side_type_decl(_type) }
+
+#define side_type_struct_decl(_fields) \
+       { \
+               .type = SIDE_TYPE_STRUCT, \
+               .u = { \
+                       .side_struct = { \
+                               .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
+                               .fields = _fields, \
+                       }, \
+               }, \
+       }
+#define side_field_struct(_name, _fields) \
+       { \
+               .field_name = _name, \
+               .side_type = side_type_struct_decl(SIDE_PARAM(_fields)), \
+       }
+
+#define side_type_array_decl(_elem_type, _length) \
+       { \
+               .type = SIDE_TYPE_ARRAY, \
+               .u = { \
+                       .side_array = { \
+                               .length = _length, \
+                               .elem_type = _elem_type, \
+                       }, \
+               }, \
+       }
+#define side_field_array(_name, _elem_type, _length) \
+       { \
+               .field_name = _name, \
+               .side_type = side_type_array_decl(_elem_type, _length), \
+       }
+
+#define side_type_vla_decl(_elem_type) \
+       { \
+               .type = SIDE_TYPE_VLA, \
+               .u = { \
+                       .side_vla = { \
+                               .elem_type = _elem_type, \
+                       }, \
+               }, \
+       }
+#define side_field_vla(_name, _elem_type) \
+       { \
+               .field_name = _name, \
+               .side_type = side_type_vla_decl(_elem_type), \
+       }
+
+#define side_type_vla_visitor_decl(_elem_type, _begin, _end, _get_next) \
+       { \
+               .type = SIDE_TYPE_VLA_VISITOR, \
+               .u = { \
+                       .side_vla_visitor = { \
+                               .elem_type = _elem_type, \
+                               .begin = _begin, \
+                               .end = _end, \
+                               .get_next = _get_next, \
+                       }, \
+               }, \
+       }
+#define side_field_vla_visitor(_name, _elem_type, _begin, _end, _get_next) \
+       { \
+               .field_name = _name, \
+               .side_type = side_type_vla_visitor_decl(_elem_type, _begin, _end, _get_next), \
+       }
+
+#define side_vla_elem(...) \
+       SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__))
+
+#define side_vla_visitor_elem(...) \
+       SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__))
+
+#define side_array_elem(...) \
+       SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__))
+
+#define side_field_list(...) \
+       SIDE_COMPOUND_LITERAL(const struct side_event_field, __VA_ARGS__)
+
+#define side_arg_u8(val)       { .type = SIDE_TYPE_U8, .u = { .side_u8 = (val) } }
+#define side_arg_u16(val)      { .type = SIDE_TYPE_U16, .u = { .side_u16 = (val) } }
+#define side_arg_u32(val)      { .type = SIDE_TYPE_U32, .u = { .side_u32 = (val) } }
+#define side_arg_u64(val)      { .type = SIDE_TYPE_U64, .u = { .side_u64 = (val) } }
+#define side_arg_s8(val)       { .type = SIDE_TYPE_S8, .u = { .side_s8 = (val) } }
+#define side_arg_s16(val)      { .type = SIDE_TYPE_S16, .u = { .side_s16 = (val) } }
+#define side_arg_s32(val)      { .type = SIDE_TYPE_S32, .u = { .side_s32 = (val) } }
+#define side_arg_s64(val)      { .type = SIDE_TYPE_S64, .u = { .side_s64 = (val) } }
+#define side_arg_string(val)   { .type = SIDE_TYPE_STRING, .u = { .string = (val) } }
+#define side_arg_struct(_side_type)    { .type = SIDE_TYPE_STRUCT, .u = { .side_struct = (_side_type) } }
+#define side_arg_array(_side_type)     { .type = SIDE_TYPE_ARRAY, .u = { .side_array = (_side_type) } }
+#define side_arg_vla(_side_type)       { .type = SIDE_TYPE_VLA, .u = { .side_vla = (_side_type) } }
+#define side_arg_vla_visitor(_ctx)     { .type = SIDE_TYPE_VLA_VISITOR, .u = { .side_vla_visitor_ctx = (_ctx) } }
+
+#define side_arg_define_vec(_identifier, _sav) \
+       const struct side_arg_vec _identifier##_vec[] = { _sav }; \
+       const struct side_arg_vec_description _identifier = { \
+               .sav = _identifier##_vec, \
+               .len = SIDE_ARRAY_SIZE(_identifier##_vec), \
+       }
+       
+#define side_arg_list(...)     __VA_ARGS__
+
+#define side_event_cond(desc) if (side_unlikely((desc)->enabled))
+#define side_event_call(desc, _sav) \
+       { \
+               const struct side_arg_vec side_sav[] = { _sav }; \
+               const struct side_arg_vec_description sav_desc = { \
+                       .sav = side_sav, \
+                       .len = SIDE_ARRAY_SIZE(side_sav), \
+               }; \
+               tracer_call(desc, &sav_desc); \
+       }
+
+#define side_event(desc, sav) \
+       side_event_cond(desc) \
+               side_event_call(desc, SIDE_PARAM(sav)); \
+
+#define side_define_event(_identifier, _provider, _event, _loglevel, _fields) \
+       struct side_event_description _identifier = { \
+               .version = 0, \
+               .enabled = 0, \
+               .loglevel = _loglevel, \
+               .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
+               .provider_name = _provider, \
+               .event_name = _event, \
+               .fields = _fields, \
+       }
+
+#define side_declare_event(_identifier) \
+       struct side_event_description _identifier
+
+#endif /* _SIDE_TRACE_H */
diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..24c93d2
--- /dev/null
@@ -0,0 +1,15 @@
+all: test
+
+tracer.o: tracer.c
+       gcc -O2 -g -Wall -I../include/ -c -o tracer.o tracer.c
+
+test.o: test.c
+       gcc -O2 -g -Wall -I../include/ -c -o test.o test.c
+
+test: tracer.o test.o
+       gcc -O2 -g -Wall -o test tracer.o test.o
+
+.PHONY: clean
+
+clean:
+       rm -f test
diff --git a/src/test.c b/src/test.c
new file mode 100644 (file)
index 0000000..8512882
--- /dev/null
@@ -0,0 +1,153 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <side/trace.h>
+#include "tracer.h"
+
+/* User code example */
+
+static side_define_event(my_provider_event, "myprovider", "myevent", SIDE_LOGLEVEL_DEBUG,
+       side_field_list(
+               side_field(SIDE_TYPE_U32, "abc"),
+               side_field(SIDE_TYPE_S64, "def"),
+               side_field(SIDE_TYPE_DYNAMIC, "dynamic"),
+       )
+);
+
+static
+void test_fields(void)
+{
+       uint32_t uw = 42;
+       int64_t sdw = -500;
+
+       my_provider_event.enabled = 1;
+       side_event(&my_provider_event, side_arg_list(side_arg_u32(uw), side_arg_s64(sdw), side_arg_string("zzz")));
+}
+
+static side_define_event(my_provider_event2, "myprovider", "myevent2", SIDE_LOGLEVEL_DEBUG,
+       side_field_list(
+               side_field_struct("structfield",
+                       side_field_list(
+                               side_field(SIDE_TYPE_U32, "x"),
+                               side_field(SIDE_TYPE_S64, "y"),
+                       )
+               ),
+               side_field(SIDE_TYPE_U8, "z"),
+       )
+);
+
+static
+void test_struct(void)
+{
+       my_provider_event2.enabled = 1;
+       side_event_cond(&my_provider_event2) {
+               side_arg_define_vec(mystruct, side_arg_list(side_arg_u32(21), side_arg_s64(22)));
+               side_event_call(&my_provider_event2, side_arg_list(side_arg_struct(&mystruct), side_arg_u8(55)));
+       }
+}
+
+static side_define_event(my_provider_event_array, "myprovider", "myarray", SIDE_LOGLEVEL_DEBUG,
+       side_field_list(
+               side_field_array("arr", side_array_elem(SIDE_TYPE_U32), 3),
+               side_field(SIDE_TYPE_S64, "v"),
+       )
+);
+
+static
+void test_array(void)
+{
+       my_provider_event_array.enabled = 1;
+       side_event_cond(&my_provider_event_array) {
+               side_arg_define_vec(myarray, side_arg_list(side_arg_u32(1), side_arg_u32(2), side_arg_u32(3)));
+               side_event_call(&my_provider_event_array, side_arg_list(side_arg_array(&myarray), side_arg_s64(42)));
+       }
+}
+
+static side_define_event(my_provider_event_vla, "myprovider", "myvla", SIDE_LOGLEVEL_DEBUG,
+       side_field_list(
+               side_field_vla("vla", side_vla_elem(SIDE_TYPE_U32)),
+               side_field(SIDE_TYPE_S64, "v"),
+       )
+);
+
+static
+void test_vla(void)
+{
+       my_provider_event_vla.enabled = 1;
+       side_event_cond(&my_provider_event_vla) {
+               side_arg_define_vec(myvla, side_arg_list(side_arg_u32(1), side_arg_u32(2), side_arg_u32(3)));
+               side_event_call(&my_provider_event_vla, side_arg_list(side_arg_vla(&myvla), side_arg_s64(42)));
+       }
+}
+
+struct app_visitor_ctx {
+       const uint32_t *ptr;
+       int init_pos;
+       int current_pos;
+       int end_pos;
+};
+
+enum side_visitor_status test_visitor_begin(void *_ctx)
+{
+       struct app_visitor_ctx *ctx = (struct app_visitor_ctx *) _ctx;
+       ctx->current_pos = ctx->init_pos;
+       return SIDE_VISITOR_STATUS_OK;
+}
+
+enum side_visitor_status test_visitor_end(void *_ctx)
+{
+       return SIDE_VISITOR_STATUS_OK;
+}
+
+enum side_visitor_status test_visitor_get_next(void *_ctx, struct side_arg_vec *sav_elem)
+{
+       struct app_visitor_ctx *ctx = (struct app_visitor_ctx *) _ctx;
+
+       if (ctx->current_pos >= ctx->end_pos)
+               return SIDE_VISITOR_STATUS_END;
+       sav_elem->type = SIDE_TYPE_U32;
+       sav_elem->u.side_u32 = ctx->ptr[ctx->current_pos++];
+       return SIDE_VISITOR_STATUS_OK;
+}
+
+static uint32_t testarray[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+static side_define_event(my_provider_event_vla_visitor, "myprovider", "myvlavisit", SIDE_LOGLEVEL_DEBUG,
+       side_field_list(
+               side_field_vla_visitor("vlavisit", side_vla_visitor_elem(SIDE_TYPE_U32),
+                       test_visitor_begin, test_visitor_end, test_visitor_get_next),
+               side_field(SIDE_TYPE_S64, "v"),
+       )
+);
+
+static
+void test_vla_visitor(void)
+{
+       my_provider_event_vla_visitor.enabled = 1;
+       side_event_cond(&my_provider_event_vla_visitor) {
+               struct app_visitor_ctx ctx = {
+                       .ptr = testarray,
+                       .init_pos = 0,
+                       .current_pos = 0,
+                       .end_pos = SIDE_ARRAY_SIZE(testarray),
+               };
+               side_event_call(&my_provider_event_vla_visitor, side_arg_list(side_arg_vla_visitor(&ctx), side_arg_s64(42)));
+       }
+}
+
+int main()
+{
+       test_fields();
+       test_struct();
+       test_array();
+       test_vla();
+       test_vla_visitor();
+       return 0;
+}
diff --git a/src/tracer.c b/src/tracer.c
new file mode 100644 (file)
index 0000000..0ef4245
--- /dev/null
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <side/trace.h>
+
+static
+void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
+static
+void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
+static
+void tracer_print_vla(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
+static
+void tracer_print_vla_visitor(const struct side_type_description *type_desc, void *ctx);
+
+static
+void tracer_print_type(const struct side_type_description *type_desc, const struct side_arg_vec *item)
+{
+       if (type_desc->type != SIDE_TYPE_DYNAMIC && type_desc->type != item->type) {
+               printf("ERROR: type mismatch between description and arguments\n");
+               abort();
+       }
+
+       switch (item->type) {
+       case SIDE_TYPE_U8:
+               printf("%" PRIu8, item->u.side_u8);
+               break;
+       case SIDE_TYPE_U16:
+               printf("%" PRIu16, item->u.side_u16);
+               break;
+       case SIDE_TYPE_U32:
+               printf("%" PRIu32, item->u.side_u32);
+               break;
+       case SIDE_TYPE_U64:
+               printf("%" PRIu64, item->u.side_u64);
+               break;
+       case SIDE_TYPE_S8:
+               printf("%" PRId8, item->u.side_s8);
+               break;
+       case SIDE_TYPE_S16:
+               printf("%" PRId16, item->u.side_s16);
+               break;
+       case SIDE_TYPE_S32:
+               printf("%" PRId32, item->u.side_s32);
+               break;
+       case SIDE_TYPE_S64:
+               printf("%" PRId64, item->u.side_s64);
+               break;
+       case SIDE_TYPE_STRING:
+               printf("%s", item->u.string);
+               break;
+       case SIDE_TYPE_STRUCT:
+               tracer_print_struct(type_desc, item->u.side_struct);
+               break;
+       case SIDE_TYPE_ARRAY:
+               tracer_print_array(type_desc, item->u.side_array);
+               break;
+       case SIDE_TYPE_VLA:
+               tracer_print_vla(type_desc, item->u.side_vla);
+               break;
+       case SIDE_TYPE_VLA_VISITOR:
+               tracer_print_vla_visitor(type_desc, item->u.side_vla_visitor_ctx);
+               break;
+       default:
+               printf("<UNKNOWN TYPE>");
+               abort();
+       }
+}
+
+static
+void tracer_print_field(const struct side_event_field *item_desc, const struct side_arg_vec *item)
+{
+       printf("(\"%s\", ", item_desc->field_name);
+       tracer_print_type(&item_desc->side_type, item);
+       printf(")");
+}
+
+static
+void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
+{
+       const struct side_arg_vec *sav = sav_desc->sav;
+       uint32_t side_sav_len = sav_desc->len;
+       int i;
+
+       if (type_desc->u.side_struct.nr_fields != side_sav_len) {
+               printf("ERROR: number of fields mismatch between description and arguments of structure\n");
+               abort();
+       }
+       printf("{ ");
+       for (i = 0; i < side_sav_len; i++) {
+               printf("%s", i ? ", " : "");
+               tracer_print_field(&type_desc->u.side_struct.fields[i], &sav[i]);
+       }
+       printf(" }");
+}
+
+static
+void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
+{
+       const struct side_arg_vec *sav = sav_desc->sav;
+       uint32_t side_sav_len = sav_desc->len;
+       int i;
+
+       if (type_desc->u.side_array.length != side_sav_len) {
+               printf("ERROR: length mismatch between description and arguments of array\n");
+               abort();
+       }
+       printf("[ ");
+       for (i = 0; i < side_sav_len; i++) {
+               printf("%s", i ? ", " : "");
+               tracer_print_type(type_desc->u.side_array.elem_type, &sav[i]);
+       }
+       printf(" ]");
+}
+
+static
+void tracer_print_vla(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
+{
+       const struct side_arg_vec *sav = sav_desc->sav;
+       uint32_t side_sav_len = sav_desc->len;
+       int i;
+
+       printf("[ ");
+       for (i = 0; i < side_sav_len; i++) {
+               printf("%s", i ? ", " : "");
+               tracer_print_type(type_desc->u.side_vla.elem_type, &sav[i]);
+       }
+       printf(" ]");
+}
+
+static
+void tracer_print_vla_visitor(const struct side_type_description *type_desc, void *ctx)
+{
+       enum side_visitor_status status;
+       int i;
+
+       status = type_desc->u.side_vla_visitor.begin(ctx);
+       if (status != SIDE_VISITOR_STATUS_OK) {
+               printf("ERROR: Visitor error\n");
+               abort();
+       }
+
+       printf("[ ");
+       status = SIDE_VISITOR_STATUS_OK;
+       for (i = 0; status == SIDE_VISITOR_STATUS_OK; i++) {
+               struct side_arg_vec sav_elem;
+
+               status = type_desc->u.side_vla_visitor.get_next(ctx, &sav_elem);
+               switch (status) {
+               case SIDE_VISITOR_STATUS_OK:
+                       break;
+               case SIDE_VISITOR_STATUS_ERROR:
+                       printf("ERROR: Visitor error\n");
+                       abort();
+               case SIDE_VISITOR_STATUS_END:
+                       continue;
+               }
+               printf("%s", i ? ", " : "");
+               tracer_print_type(type_desc->u.side_vla_visitor.elem_type, &sav_elem);
+       }
+       printf(" ]");
+       if (type_desc->u.side_vla_visitor.end) {
+               status = type_desc->u.side_vla_visitor.end(ctx);
+               if (status != SIDE_VISITOR_STATUS_OK) {
+                       printf("ERROR: Visitor error\n");
+                       abort();
+               }
+       }
+}
+
+void tracer_call(const struct side_event_description *desc, const struct side_arg_vec_description *sav_desc)
+{
+       const struct side_arg_vec *sav = sav_desc->sav;
+       uint32_t side_sav_len = sav_desc->len;
+       int i;
+
+       printf("provider: %s, event: %s, ", desc->provider_name, desc->event_name);
+       if (desc->nr_fields != side_sav_len) {
+               printf("ERROR: number of fields mismatch between description and arguments\n");
+               abort();
+       }
+       for (i = 0; i < side_sav_len; i++) {
+               printf("%s", i ? ", " : "");
+               tracer_print_field(&desc->fields[i], &sav[i]);
+       }
+       printf("\n");
+}
diff --git a/src/tracer.h b/src/tracer.h
new file mode 100644 (file)
index 0000000..d3ee02b
--- /dev/null
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ */
+
+#ifndef _TRACER_H
+#define _TRACER_H
+
+#include <side/trace.h>
+
+void tracer_call(const struct side_event_description *desc, const struct side_arg_vec_description *sav_desc);
+
+#endif
diff --git a/test.c b/test.c
deleted file mode 100644 (file)
index cfdc41d..0000000
--- a/test.c
+++ /dev/null
@@ -1,597 +0,0 @@
-// SPDX-License-Identifier: MIT
-/*
- * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- */
-
-#include <stdint.h>
-#include <inttypes.h>
-#include <stdlib.h>
-#include <stdio.h>
-
-/* SIDE stands for "Static Instrumentation Dynamically Enabled" */
-
-/* Helper macros */
-
-#define SIDE_ARRAY_SIZE(arr)   (sizeof(arr) / sizeof((arr)[0]))
-
-/*
- * Compound literals with static storage are needed by SIDE
- * instrumentation.
- * Compound literals are part of the C99 and C11 standards, but not
- * part of the C++ standards. They are supported by most C++ compilers
- * though.
- *
- * Example use:
- * static struct mystruct *var = LTTNG_UST_COMPOUND_LITERAL(struct mystruct, { 1, 2, 3 });
- */
-#define SIDE_COMPOUND_LITERAL(type, ...)   (type[]) { __VA_ARGS__ }
-
-#define side_likely(x)         __builtin_expect(!!(x), 1)
-#define side_unlikely(x)       __builtin_expect(!!(x), 0)
-
-struct side_arg_vec;
-struct side_type_description;
-struct side_event_field;
-
-enum side_type {
-       SIDE_TYPE_U8,
-       SIDE_TYPE_U16,
-       SIDE_TYPE_U32,
-       SIDE_TYPE_U64,
-       SIDE_TYPE_S8,
-       SIDE_TYPE_S16,
-       SIDE_TYPE_S32,
-       SIDE_TYPE_S64,
-       SIDE_TYPE_STRING,
-       SIDE_TYPE_DYNAMIC,
-       SIDE_TYPE_STRUCT,
-       SIDE_TYPE_ARRAY,
-       SIDE_TYPE_VLA,
-       SIDE_TYPE_VLA_VISITOR,
-       //TODO:
-       //specialized array and vla for fixed-size integers (optimization)
-       //variants (discriminated unions)
-};
-
-enum side_loglevel {
-       SIDE_LOGLEVEL_EMERG = 0,
-       SIDE_LOGLEVEL_ALERT = 1,
-       SIDE_LOGLEVEL_CRIT = 2,
-       SIDE_LOGLEVEL_ERR = 3,
-       SIDE_LOGLEVEL_WARNING = 4,
-       SIDE_LOGLEVEL_NOTICE = 5,
-       SIDE_LOGLEVEL_INFO = 6,
-       SIDE_LOGLEVEL_DEBUG = 7,
-};
-
-enum side_visitor_status {
-       SIDE_VISITOR_STATUS_ERROR = -1,
-       SIDE_VISITOR_STATUS_OK = 0,
-       SIDE_VISITOR_STATUS_END = 1,
-};
-
-typedef enum side_visitor_status (*side_visitor_begin)(void *ctx);
-typedef enum side_visitor_status (*side_visitor_end)(void *ctx);
-typedef enum side_visitor_status (*side_visitor_get_next)(void *ctx, struct side_arg_vec *sav_elem);
-
-struct side_type_description {
-       enum side_type type;
-       union {
-               struct {
-                       uint32_t nr_fields;
-                       const struct side_event_field *fields;
-               } side_struct;
-               struct {
-                       uint32_t length;
-                       const struct side_type_description *elem_type;
-               } side_array;
-               struct {
-                       const struct side_type_description *elem_type;
-               } side_vla;
-               struct {
-                       const struct side_type_description *elem_type;
-                       side_visitor_begin begin;
-                       side_visitor_end end;
-                       side_visitor_get_next get_next;
-               } side_vla_visitor;
-       } u;
-};
-
-struct side_event_field {
-       const char *field_name;
-       struct side_type_description side_type;
-};
-
-struct side_event_description {
-       uint32_t version;
-       uint32_t enabled;
-       uint32_t loglevel;      /* enum side_loglevel */
-       uint32_t nr_fields;
-       const char *provider_name;
-       const char *event_name;
-       const struct side_event_field *fields;
-};
-
-struct side_arg_vec {
-       uint32_t type;  /* enum side_type */
-       union {
-               uint8_t side_u8;
-               uint16_t side_u16;
-               uint32_t side_u32;
-               uint64_t side_u64;
-               int8_t side_s8;
-               int16_t side_s16;
-               int32_t side_s32;
-               int64_t side_s64;
-               const char *string;
-               const struct side_arg_vec_description *side_struct;
-               const struct side_arg_vec_description *side_array;
-               const struct side_arg_vec_description *side_vla;
-               void *side_vla_visitor_ctx;
-       } u;
-};
-
-struct side_arg_vec_description {
-       const struct side_arg_vec *sav;
-       uint32_t len;
-};
-
-/* Tracer example */
-
-static
-void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
-static
-void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
-static
-void tracer_print_vla(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
-static
-void tracer_print_vla_visitor(const struct side_type_description *type_desc, void *ctx);
-
-static
-void tracer_print_type(const struct side_type_description *type_desc, const struct side_arg_vec *item)
-{
-       if (type_desc->type != SIDE_TYPE_DYNAMIC && type_desc->type != item->type) {
-               printf("ERROR: type mismatch between description and arguments\n");
-               abort();
-       }
-
-       switch (item->type) {
-       case SIDE_TYPE_U8:
-               printf("%" PRIu8, item->u.side_u8);
-               break;
-       case SIDE_TYPE_U16:
-               printf("%" PRIu16, item->u.side_u16);
-               break;
-       case SIDE_TYPE_U32:
-               printf("%" PRIu32, item->u.side_u32);
-               break;
-       case SIDE_TYPE_U64:
-               printf("%" PRIu64, item->u.side_u64);
-               break;
-       case SIDE_TYPE_S8:
-               printf("%" PRId8, item->u.side_s8);
-               break;
-       case SIDE_TYPE_S16:
-               printf("%" PRId16, item->u.side_s16);
-               break;
-       case SIDE_TYPE_S32:
-               printf("%" PRId32, item->u.side_s32);
-               break;
-       case SIDE_TYPE_S64:
-               printf("%" PRId64, item->u.side_s64);
-               break;
-       case SIDE_TYPE_STRING:
-               printf("%s", item->u.string);
-               break;
-       case SIDE_TYPE_STRUCT:
-               tracer_print_struct(type_desc, item->u.side_struct);
-               break;
-       case SIDE_TYPE_ARRAY:
-               tracer_print_array(type_desc, item->u.side_array);
-               break;
-       case SIDE_TYPE_VLA:
-               tracer_print_vla(type_desc, item->u.side_vla);
-               break;
-       case SIDE_TYPE_VLA_VISITOR:
-               tracer_print_vla_visitor(type_desc, item->u.side_vla_visitor_ctx);
-               break;
-       default:
-               printf("<UNKNOWN TYPE>");
-               abort();
-       }
-}
-
-static
-void tracer_print_field(const struct side_event_field *item_desc, const struct side_arg_vec *item)
-{
-       printf("(\"%s\", ", item_desc->field_name);
-       tracer_print_type(&item_desc->side_type, item);
-       printf(")");
-}
-
-static
-void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
-{
-       const struct side_arg_vec *sav = sav_desc->sav;
-       uint32_t side_sav_len = sav_desc->len;
-       int i;
-
-       if (type_desc->u.side_struct.nr_fields != side_sav_len) {
-               printf("ERROR: number of fields mismatch between description and arguments of structure\n");
-               abort();
-       }
-       printf("{ ");
-       for (i = 0; i < side_sav_len; i++) {
-               printf("%s", i ? ", " : "");
-               tracer_print_field(&type_desc->u.side_struct.fields[i], &sav[i]);
-       }
-       printf(" }");
-}
-
-static
-void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
-{
-       const struct side_arg_vec *sav = sav_desc->sav;
-       uint32_t side_sav_len = sav_desc->len;
-       int i;
-
-       if (type_desc->u.side_array.length != side_sav_len) {
-               printf("ERROR: length mismatch between description and arguments of array\n");
-               abort();
-       }
-       printf("[ ");
-       for (i = 0; i < side_sav_len; i++) {
-               printf("%s", i ? ", " : "");
-               tracer_print_type(type_desc->u.side_array.elem_type, &sav[i]);
-       }
-       printf(" ]");
-}
-
-static
-void tracer_print_vla(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
-{
-       const struct side_arg_vec *sav = sav_desc->sav;
-       uint32_t side_sav_len = sav_desc->len;
-       int i;
-
-       printf("[ ");
-       for (i = 0; i < side_sav_len; i++) {
-               printf("%s", i ? ", " : "");
-               tracer_print_type(type_desc->u.side_vla.elem_type, &sav[i]);
-       }
-       printf(" ]");
-}
-
-static
-void tracer_print_vla_visitor(const struct side_type_description *type_desc, void *ctx)
-{
-       enum side_visitor_status status;
-       int i;
-
-       status = type_desc->u.side_vla_visitor.begin(ctx);
-       if (status != SIDE_VISITOR_STATUS_OK) {
-               printf("ERROR: Visitor error\n");
-               abort();
-       }
-
-       printf("[ ");
-       status = SIDE_VISITOR_STATUS_OK;
-       for (i = 0; status == SIDE_VISITOR_STATUS_OK; i++) {
-               struct side_arg_vec sav_elem;
-
-               status = type_desc->u.side_vla_visitor.get_next(ctx, &sav_elem);
-               switch (status) {
-               case SIDE_VISITOR_STATUS_OK:
-                       break;
-               case SIDE_VISITOR_STATUS_ERROR:
-                       printf("ERROR: Visitor error\n");
-                       abort();
-               case SIDE_VISITOR_STATUS_END:
-                       continue;
-               }
-               printf("%s", i ? ", " : "");
-               tracer_print_type(type_desc->u.side_vla_visitor.elem_type, &sav_elem);
-       }
-       printf(" ]");
-       if (type_desc->u.side_vla_visitor.end) {
-               status = type_desc->u.side_vla_visitor.end(ctx);
-               if (status != SIDE_VISITOR_STATUS_OK) {
-                       printf("ERROR: Visitor error\n");
-                       abort();
-               }
-       }
-}
-
-__attribute__((noinline))
-void tracer_call(const struct side_event_description *desc, const struct side_arg_vec_description *sav_desc)
-{
-       const struct side_arg_vec *sav = sav_desc->sav;
-       uint32_t side_sav_len = sav_desc->len;
-       int i;
-
-       printf("provider: %s, event: %s, ", desc->provider_name, desc->event_name);
-       if (desc->nr_fields != side_sav_len) {
-               printf("ERROR: number of fields mismatch between description and arguments\n");
-               abort();
-       }
-       for (i = 0; i < side_sav_len; i++) {
-               printf("%s", i ? ", " : "");
-               tracer_print_field(&desc->fields[i], &sav[i]);
-       }
-       printf("\n");
-}
-
-#define SIDE_PARAM(...)        __VA_ARGS__
-
-#define side_type_decl(_type)                  { .type = _type }
-#define side_field(_type, _name)               { .field_name = _name, .side_type = side_type_decl(_type) }
-
-#define side_type_struct_decl(_fields) \
-       { \
-               .type = SIDE_TYPE_STRUCT, \
-               .u = { \
-                       .side_struct = { \
-                               .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
-                               .fields = _fields, \
-                       }, \
-               }, \
-       }
-#define side_field_struct(_name, _fields) \
-       { \
-               .field_name = _name, \
-               .side_type = side_type_struct_decl(SIDE_PARAM(_fields)), \
-       }
-
-#define side_type_array_decl(_elem_type, _length) \
-       { \
-               .type = SIDE_TYPE_ARRAY, \
-               .u = { \
-                       .side_array = { \
-                               .length = _length, \
-                               .elem_type = _elem_type, \
-                       }, \
-               }, \
-       }
-#define side_field_array(_name, _elem_type, _length) \
-       { \
-               .field_name = _name, \
-               .side_type = side_type_array_decl(_elem_type, _length), \
-       }
-
-#define side_type_vla_decl(_elem_type) \
-       { \
-               .type = SIDE_TYPE_VLA, \
-               .u = { \
-                       .side_vla = { \
-                               .elem_type = _elem_type, \
-                       }, \
-               }, \
-       }
-#define side_field_vla(_name, _elem_type) \
-       { \
-               .field_name = _name, \
-               .side_type = side_type_vla_decl(_elem_type), \
-       }
-
-#define side_type_vla_visitor_decl(_elem_type, _begin, _end, _get_next) \
-       { \
-               .type = SIDE_TYPE_VLA_VISITOR, \
-               .u = { \
-                       .side_vla_visitor = { \
-                               .elem_type = _elem_type, \
-                               .begin = _begin, \
-                               .end = _end, \
-                               .get_next = _get_next, \
-                       }, \
-               }, \
-       }
-#define side_field_vla_visitor(_name, _elem_type, _begin, _end, _get_next) \
-       { \
-               .field_name = _name, \
-               .side_type = side_type_vla_visitor_decl(_elem_type, _begin, _end, _get_next), \
-       }
-
-#define side_vla_elem(...) \
-       SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__))
-
-#define side_vla_visitor_elem(...) \
-       SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__))
-
-#define side_array_elem(...) \
-       SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__))
-
-#define side_field_list(...) \
-       SIDE_COMPOUND_LITERAL(const struct side_event_field, __VA_ARGS__)
-
-#define side_arg_u8(val)       { .type = SIDE_TYPE_U8, .u = { .side_u8 = (val) } }
-#define side_arg_u16(val)      { .type = SIDE_TYPE_U16, .u = { .side_u16 = (val) } }
-#define side_arg_u32(val)      { .type = SIDE_TYPE_U32, .u = { .side_u32 = (val) } }
-#define side_arg_u64(val)      { .type = SIDE_TYPE_U64, .u = { .side_u64 = (val) } }
-#define side_arg_s8(val)       { .type = SIDE_TYPE_S8, .u = { .side_s8 = (val) } }
-#define side_arg_s16(val)      { .type = SIDE_TYPE_S16, .u = { .side_s16 = (val) } }
-#define side_arg_s32(val)      { .type = SIDE_TYPE_S32, .u = { .side_s32 = (val) } }
-#define side_arg_s64(val)      { .type = SIDE_TYPE_S64, .u = { .side_s64 = (val) } }
-#define side_arg_string(val)   { .type = SIDE_TYPE_STRING, .u = { .string = (val) } }
-#define side_arg_struct(_side_type)    { .type = SIDE_TYPE_STRUCT, .u = { .side_struct = (_side_type) } }
-#define side_arg_array(_side_type)     { .type = SIDE_TYPE_ARRAY, .u = { .side_array = (_side_type) } }
-#define side_arg_vla(_side_type)       { .type = SIDE_TYPE_VLA, .u = { .side_vla = (_side_type) } }
-#define side_arg_vla_visitor(_ctx)     { .type = SIDE_TYPE_VLA_VISITOR, .u = { .side_vla_visitor_ctx = (_ctx) } }
-
-#define side_arg_define_vec(_identifier, _sav) \
-       const struct side_arg_vec _identifier##_vec[] = { _sav }; \
-       const struct side_arg_vec_description _identifier = { \
-               .sav = _identifier##_vec, \
-               .len = SIDE_ARRAY_SIZE(_identifier##_vec), \
-       }
-       
-#define side_arg_list(...)     __VA_ARGS__
-
-#define side_event_cond(desc) if (side_unlikely((desc)->enabled))
-#define side_event_call(desc, _sav) \
-       { \
-               const struct side_arg_vec side_sav[] = { _sav }; \
-               const struct side_arg_vec_description sav_desc = { \
-                       .sav = side_sav, \
-                       .len = SIDE_ARRAY_SIZE(side_sav), \
-               }; \
-               tracer_call(desc, &sav_desc); \
-       }
-
-#define side_event(desc, sav) \
-       side_event_cond(desc) \
-               side_event_call(desc, SIDE_PARAM(sav)); \
-
-#define side_define_event(_identifier, _provider, _event, _loglevel, _fields) \
-       struct side_event_description _identifier = { \
-               .version = 0, \
-               .enabled = 0, \
-               .loglevel = _loglevel, \
-               .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
-               .provider_name = _provider, \
-               .event_name = _event, \
-               .fields = _fields, \
-       }
-
-#define side_declare_event(_identifier) \
-       struct side_event_description _identifier
-
-/* User code example */
-
-static side_define_event(my_provider_event, "myprovider", "myevent", SIDE_LOGLEVEL_DEBUG,
-       side_field_list(
-               side_field(SIDE_TYPE_U32, "abc"),
-               side_field(SIDE_TYPE_S64, "def"),
-               side_field(SIDE_TYPE_DYNAMIC, "dynamic"),
-       )
-);
-
-static
-void test_fields(void)
-{
-       uint32_t uw = 42;
-       int64_t sdw = -500;
-
-       my_provider_event.enabled = 1;
-       side_event(&my_provider_event, side_arg_list(side_arg_u32(uw), side_arg_s64(sdw), side_arg_string("zzz")));
-}
-
-static side_define_event(my_provider_event2, "myprovider", "myevent2", SIDE_LOGLEVEL_DEBUG,
-       side_field_list(
-               side_field_struct("structfield",
-                       side_field_list(
-                               side_field(SIDE_TYPE_U32, "x"),
-                               side_field(SIDE_TYPE_S64, "y"),
-                       )
-               ),
-               side_field(SIDE_TYPE_U8, "z"),
-       )
-);
-
-static
-void test_struct(void)
-{
-       my_provider_event2.enabled = 1;
-       side_event_cond(&my_provider_event2) {
-               side_arg_define_vec(mystruct, side_arg_list(side_arg_u32(21), side_arg_s64(22)));
-               side_event_call(&my_provider_event2, side_arg_list(side_arg_struct(&mystruct), side_arg_u8(55)));
-       }
-}
-
-static side_define_event(my_provider_event_array, "myprovider", "myarray", SIDE_LOGLEVEL_DEBUG,
-       side_field_list(
-               side_field_array("arr", side_array_elem(SIDE_TYPE_U32), 3),
-               side_field(SIDE_TYPE_S64, "v"),
-       )
-);
-
-static
-void test_array(void)
-{
-       my_provider_event_array.enabled = 1;
-       side_event_cond(&my_provider_event_array) {
-               side_arg_define_vec(myarray, side_arg_list(side_arg_u32(1), side_arg_u32(2), side_arg_u32(3)));
-               side_event_call(&my_provider_event_array, side_arg_list(side_arg_array(&myarray), side_arg_s64(42)));
-       }
-}
-
-static side_define_event(my_provider_event_vla, "myprovider", "myvla", SIDE_LOGLEVEL_DEBUG,
-       side_field_list(
-               side_field_vla("vla", side_vla_elem(SIDE_TYPE_U32)),
-               side_field(SIDE_TYPE_S64, "v"),
-       )
-);
-
-static
-void test_vla(void)
-{
-       my_provider_event_vla.enabled = 1;
-       side_event_cond(&my_provider_event_vla) {
-               side_arg_define_vec(myvla, side_arg_list(side_arg_u32(1), side_arg_u32(2), side_arg_u32(3)));
-               side_event_call(&my_provider_event_vla, side_arg_list(side_arg_vla(&myvla), side_arg_s64(42)));
-       }
-}
-
-struct app_visitor_ctx {
-       const uint32_t *ptr;
-       int init_pos;
-       int current_pos;
-       int end_pos;
-};
-
-enum side_visitor_status test_visitor_begin(void *_ctx)
-{
-       struct app_visitor_ctx *ctx = (struct app_visitor_ctx *) _ctx;
-       ctx->current_pos = ctx->init_pos;
-       return SIDE_VISITOR_STATUS_OK;
-}
-
-enum side_visitor_status test_visitor_end(void *_ctx)
-{
-       return SIDE_VISITOR_STATUS_OK;
-}
-
-enum side_visitor_status test_visitor_get_next(void *_ctx, struct side_arg_vec *sav_elem)
-{
-       struct app_visitor_ctx *ctx = (struct app_visitor_ctx *) _ctx;
-
-       if (ctx->current_pos >= ctx->end_pos)
-               return SIDE_VISITOR_STATUS_END;
-       sav_elem->type = SIDE_TYPE_U32;
-       sav_elem->u.side_u32 = ctx->ptr[ctx->current_pos++];
-       return SIDE_VISITOR_STATUS_OK;
-}
-
-static uint32_t testarray[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
-
-static side_define_event(my_provider_event_vla_visitor, "myprovider", "myvlavisit", SIDE_LOGLEVEL_DEBUG,
-       side_field_list(
-               side_field_vla_visitor("vlavisit", side_vla_visitor_elem(SIDE_TYPE_U32),
-                       test_visitor_begin, test_visitor_end, test_visitor_get_next),
-               side_field(SIDE_TYPE_S64, "v"),
-       )
-);
-
-static
-void test_vla_visitor(void)
-{
-       my_provider_event_vla_visitor.enabled = 1;
-       side_event_cond(&my_provider_event_vla_visitor) {
-               struct app_visitor_ctx ctx = {
-                       .ptr = testarray,
-                       .init_pos = 0,
-                       .current_pos = 0,
-                       .end_pos = SIDE_ARRAY_SIZE(testarray),
-               };
-               side_event_call(&my_provider_event_vla_visitor, side_arg_list(side_arg_vla_visitor(&ctx), side_arg_s64(42)));
-       }
-}
-
-int main()
-{
-       test_fields();
-       test_struct();
-       test_array();
-       test_vla();
-       test_vla_visitor();
-       return 0;
-}
This page took 0.036318 seconds and 4 git commands to generate.