Implement support for scatter-gather struct (integers)
authorMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 1 Nov 2022 21:21:34 +0000 (17:21 -0400)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Tue, 1 Nov 2022 21:21:34 +0000 (17:21 -0400)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
include/side/trace.h
src/test.c
src/tracer.c

index e60d29bbfc6a65ffbeae0406ccf40b0023bd8361..989810f662e5e958ba77f5bb29588d037102a540 100644 (file)
@@ -26,6 +26,7 @@ struct side_arg_dynamic_vec;
 struct side_arg_dynamic_vec_vla;
 struct side_type_description;
 struct side_event_field;
+struct side_event_field_sg;
 struct side_tracer_visitor_ctx;
 struct side_tracer_dynamic_struct_visitor_ctx;
 struct side_tracer_dynamic_vla_visitor_ctx;
@@ -55,6 +56,7 @@ enum side_type {
 
        /* Compound types */
        SIDE_TYPE_STRUCT,
+       SIDE_TYPE_STRUCT_SG,
        SIDE_TYPE_ARRAY,
        SIDE_TYPE_VLA,
        SIDE_TYPE_VLA_VISITOR,
@@ -139,6 +141,11 @@ enum side_attr_type {
        SIDE_ATTR_TYPE_STRING,
 };
 
+enum side_type_sg {
+       SIDE_TYPE_SG_UNSIGNED_INT,
+       SIDE_TYPE_SG_SIGNED_INT,
+};
+
 enum side_loglevel {
        SIDE_LOGLEVEL_EMERG = 0,
        SIDE_LOGLEVEL_ALERT = 1,
@@ -258,6 +265,35 @@ struct side_type_struct {
        const struct side_attr *attr;
 };
 
+struct side_type_sg_description {
+       uint32_t type;  /* enum side_type_sg */
+       union {
+               /* Basic types */
+               struct {
+                       uint64_t integer_offset;        /* bytes */
+                       const struct side_attr *attr;
+                       uint32_t nr_attr;
+                       uint32_t byte_order;            /* enum side_type_byte_order */
+                       uint8_t integer_size_bits;      /* bits */
+                       uint8_t offset_bits;            /* bits */
+                       uint8_t len_bits;               /* bits */
+               } side_basic;
+       } u;
+};
+
+struct side_struct_field_sg {
+       const char *field_name;
+       struct side_type_sg_description side_type;
+};
+
+/* Structure fields scatter-gather. */
+struct side_type_struct_sg {
+       uint32_t nr_fields;
+       uint32_t nr_attr;
+       const struct side_struct_field_sg *fields_sg;
+       const struct side_attr *attr;
+};
+
 struct side_type_description {
        uint32_t type;  /* enum side_type */
        union {
@@ -287,6 +323,7 @@ struct side_type_description {
                        uint32_t nr_attr;
                } side_vla_visitor;
                const struct side_type_struct *side_struct;
+               const struct side_type_struct_sg *side_struct_sg;
 
                /* Enumeration types */
                struct {
@@ -447,6 +484,7 @@ struct side_arg_vec {
                        void *p;
                        uint32_t length;
                } side_vla_fixint;
+               void *side_struct_sg_ptr;
 
                /* Dynamic type */
                struct side_arg_dynamic_vec dynamic;
@@ -682,6 +720,67 @@ struct side_tracer_dynamic_vla_visitor_ctx {
        SIDE_COMPOUND_LITERAL(const struct side_type_struct, \
                _side_type_struct_define(SIDE_PARAM(_fields), SIDE_PARAM(_attr)))
 
+/* Scatter-gather struct */
+
+#define _side_type_sg_integer(_type, _byte_order, _integer_offset, _integer_size_bits, _offset_bits, _len_bits, _attr) \
+       { \
+               .type = _type, \
+               .u = { \
+                       .side_basic = { \
+                               .attr = _attr, \
+                               .nr_attr = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
+                               .byte_order = _byte_order, \
+                               .integer_offset = _integer_offset, \
+                               .integer_size_bits = _integer_size_bits, \
+                               .offset_bits = _offset_bits, \
+                               .len_bits = _len_bits, \
+                       }, \
+               }, \
+       }
+
+#define _side_field_sg(_name, _type) \
+       { \
+               .field_name = _name, \
+               .side_type = _type, \
+       }
+
+#define side_type_sg_unsigned_integer(_integer_offset, _integer_size_bits, _offset_bits, _len_bits, _attr) \
+       _side_type_sg_integer(SIDE_TYPE_SG_UNSIGNED_INT, SIDE_TYPE_BYTE_ORDER_HOST, \
+                       _integer_offset, _integer_size_bits, _offset_bits, _len_bits, SIDE_PARAM(_attr))
+#define side_type_sg_signed_integer(_integer_offset, _integer_size_bits, _offset_bits, _len_bits, _attr) \
+       _side_type_sg_integer(SIDE_TYPE_SG_SIGNED_INT, SIDE_TYPE_BYTE_ORDER_HOST, \
+                       _integer_offset, _integer_size_bits, _offset_bits, _len_bits, SIDE_PARAM(_attr))
+
+#define side_field_sg_unsigned_integer(_name, _integer_offset, _integer_size_bits, _offset_bits, _len_bits, _attr) \
+       _side_field_sg(_name, side_type_sg_unsigned_integer(_integer_offset, _integer_size_bits, _offset_bits, _len_bits, SIDE_PARAM(_attr)))
+#define side_field_sg_signed_integer(_name, _integer_offset, _integer_size_bits, _offset_bits, _len_bits, _attr) \
+       _side_field_sg(_name, side_type_sg_signed_integer(_integer_offset, _integer_size_bits, _offset_bits, _len_bits, SIDE_PARAM(_attr)))
+
+#define side_type_struct_sg(_struct_sg) \
+       { \
+               .type = SIDE_TYPE_STRUCT_SG, \
+               .u = { \
+                       .side_struct_sg = _struct_sg, \
+               }, \
+       }
+#define side_field_struct_sg(_name, _struct_sg) \
+       _side_field(_name, side_type_struct_sg(SIDE_PARAM(_struct_sg)))
+
+#define _side_type_struct_sg_define(_fields_sg, _attr) \
+       { \
+               .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields_sg)), \
+               .nr_attr  = SIDE_ARRAY_SIZE(SIDE_PARAM(_attr)), \
+               .fields_sg = _fields_sg, \
+               .attr = _attr, \
+       }
+
+#define side_define_struct_sg(_identifier, _fields_sg, _attr) \
+       const struct side_type_struct_sg _identifier = _side_type_struct_sg_define(SIDE_PARAM(_fields_sg), SIDE_PARAM(_attr))
+
+#define side_struct_sg_literal(_fields_sg, _attr) \
+       SIDE_COMPOUND_LITERAL(const struct side_type_struct_sg, \
+               _side_type_struct_sg_define(SIDE_PARAM(_fields_sg), SIDE_PARAM(_attr)))
+
 #define side_type_array(_elem_type, _length, _attr) \
        { \
                .type = SIDE_TYPE_ARRAY, \
@@ -732,6 +831,9 @@ struct side_tracer_dynamic_vla_visitor_ctx {
 #define side_field_list(...) \
        SIDE_COMPOUND_LITERAL(const struct side_event_field, __VA_ARGS__)
 
+#define side_field_sg_list(...) \
+       SIDE_COMPOUND_LITERAL(const struct side_struct_field_sg, __VA_ARGS__)
+
 /* Static field arguments */
 
 #define side_arg_bool(_val)            { .type = SIDE_TYPE_BOOL, .u = { .side_bool = !!(_val) } }
@@ -758,6 +860,7 @@ struct side_tracer_dynamic_vla_visitor_ctx {
 
 #define side_arg_string(_val)          { .type = SIDE_TYPE_STRING, .u = { .string = (uintptr_t) (_val) } }
 #define side_arg_struct(_side_type)    { .type = SIDE_TYPE_STRUCT, .u = { .side_struct = (_side_type) } }
+#define side_arg_struct_sg(_ptr)       { .type = SIDE_TYPE_STRUCT_SG, .u = { .side_struct_sg_ptr = (_ptr) } }
 #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_app_visitor_ctx = (_ctx) } }
index 582203993b32233a45595ada6163b36d7d80e2ac..0c69fe98a8b0452191b36292d09d355069badef5 100644 (file)
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdbool.h>
+#include <stddef.h>
 
 #include <side/trace.h>
 #include "tracer.h"
@@ -1483,6 +1484,46 @@ void test_base(void)
        );
 }
 
+struct test {
+       uint32_t a;
+       uint64_t b;
+       uint8_t c;
+       int32_t d;
+       uint16_t e;
+};
+
+static side_define_struct_sg(mystructsgdef,
+       side_field_sg_list(
+               side_field_sg_unsigned_integer("a", offsetof(struct test, a), 32, 0, 32, side_attr_list()),
+               side_field_sg_signed_integer("d", offsetof(struct test, d), 32, 0, 32, side_attr_list()),
+               side_field_sg_unsigned_integer("e", offsetof(struct test, e), 16, 8, 4,
+                       side_attr_list(side_attr("std.integer.base", side_attr_u8(16)))),
+       ),
+       side_attr_list()
+);
+
+side_static_event(my_provider_event_structsg, "myprovider", "myeventstructsg", SIDE_LOGLEVEL_DEBUG,
+       side_field_list(
+               side_field_struct_sg("structsg", &mystructsgdef),
+       ),
+       side_attr_list()
+);
+
+static
+void test_struct_sg(void)
+{
+       side_event_cond(my_provider_event_structsg) {
+               struct test mystruct = {
+                       .a = 55,
+                       .b = 123,
+                       .c = 2,
+                       .d = -55,
+                       .e = 0xABCD,
+               };
+               side_event_call(my_provider_event_structsg, side_arg_list(side_arg_struct_sg(&mystruct)));
+       }
+}
+
 int main()
 {
        test_fields();
@@ -1523,5 +1564,6 @@ int main()
        test_fmt_string();
        test_endian();
        test_base();
+       test_struct_sg();
        return 0;
 }
index ad7c393a932250454aee497437630def1e2d4f2a..afa11697896761c9d15d9b41b2bde42fec641b71 100644 (file)
@@ -24,6 +24,8 @@ static struct side_tracer_handle *tracer_handle;
 static
 void tracer_print_struct(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc);
 static
+void tracer_print_struct_sg(const struct side_type_description *type_desc, void *ptr);
+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);
@@ -140,6 +142,23 @@ bool type_to_host_reverse_bo(const struct side_type_description *type_desc)
        }
 }
 
+static
+bool sg_type_to_host_reverse_bo(const struct side_type_sg_description *sg_type)
+{
+       switch (sg_type->type) {
+       case SIDE_TYPE_SG_UNSIGNED_INT:
+       case SIDE_TYPE_SG_SIGNED_INT:
+               if (sg_type->u.side_basic.byte_order != SIDE_TYPE_BYTE_ORDER_HOST)
+                       return true;
+               else
+                       return false;
+               break;
+       default:
+               fprintf(stderr, "Unexpected type\n");
+               abort();
+       }
+}
+
 static
 bool dynamic_type_to_host_reverse_bo(const struct side_arg_dynamic_vec *item)
 {
@@ -984,6 +1003,9 @@ void tracer_print_type(const struct side_type_description *type_desc, const stru
        case SIDE_TYPE_STRUCT:
                tracer_print_struct(type_desc, item->u.side_struct);
                break;
+       case SIDE_TYPE_STRUCT_SG:
+               tracer_print_struct_sg(type_desc, item->u.side_struct_sg_ptr);
+               break;
        case SIDE_TYPE_ARRAY:
                tracer_print_array(type_desc, item->u.side_array);
                break;
@@ -1058,6 +1080,302 @@ void tracer_print_struct(const struct side_type_description *type_desc, const st
        printf(" }");
 }
 
+static
+void tracer_print_sg_integer_type_header(const struct side_type_sg_description *sg_type)
+{
+       print_attributes("attr", ":", sg_type->u.side_basic.attr, sg_type->u.side_basic.nr_attr);
+       printf("%s", sg_type->u.side_basic.nr_attr ? ", " : "");
+       printf("value: ");
+}
+
+static
+void tracer_print_sg_type(const struct side_type_sg_description *sg_type, void *_ptr)
+{
+       enum tracer_display_base base = TRACER_DISPLAY_BASE_10;
+       const char *ptr = (const char *) _ptr;
+
+       switch (sg_type->type) {
+       case SIDE_TYPE_SG_UNSIGNED_INT:
+       case SIDE_TYPE_SG_SIGNED_INT:
+               base = get_attr_display_base(sg_type->u.side_basic.attr,
+                               sg_type->u.side_basic.nr_attr);
+               break;
+       default:
+               break;
+       }
+
+       printf("{ ");
+       switch (sg_type->type) {
+       case SIDE_TYPE_SG_UNSIGNED_INT:
+       {
+               tracer_print_sg_integer_type_header(sg_type);
+               switch (sg_type->u.side_basic.integer_size_bits) {
+               case 8:
+               {
+                       uint8_t v;
+
+                       memcpy(&v, ptr + sg_type->u.side_basic.integer_offset, sizeof(v));
+                       v >>= sg_type->u.side_basic.offset_bits;
+                       if (sg_type->u.side_basic.len_bits < 8)
+                               v &= (1U << sg_type->u.side_basic.len_bits) - 1;
+                       switch (base) {
+                       case TRACER_DISPLAY_BASE_2:
+                               print_integer_binary(v, sg_type->u.side_basic.len_bits);
+                               break;
+                       case TRACER_DISPLAY_BASE_8:
+                               printf("0%" PRIo8, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_10:
+                               printf("%" PRIu8, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_16:
+                               printf("0x%" PRIx8, v);
+                               break;
+                       default:
+                               abort();
+                       }
+                       break;
+               }
+               case 16:
+               {
+                       uint16_t v;
+
+                       memcpy(&v, ptr + sg_type->u.side_basic.integer_offset, sizeof(v));
+                       if (sg_type_to_host_reverse_bo(sg_type))
+                               v = side_bswap_16(v);
+                       v >>= sg_type->u.side_basic.offset_bits;
+                       if (sg_type->u.side_basic.len_bits < 16)
+                               v &= (1U << sg_type->u.side_basic.len_bits) - 1;
+                       switch (base) {
+                       case TRACER_DISPLAY_BASE_2:
+                               print_integer_binary(v, sg_type->u.side_basic.len_bits);
+                               break;
+                       case TRACER_DISPLAY_BASE_8:
+                               printf("0%" PRIo16, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_10:
+                               printf("%" PRIu16, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_16:
+                               printf("0x%" PRIx16, v);
+                               break;
+                       default:
+                               abort();
+                       }
+                       break;
+               }
+               case 32:
+               {
+                       uint32_t v;
+
+                       memcpy(&v, ptr + sg_type->u.side_basic.integer_offset, sizeof(v));
+                       if (sg_type_to_host_reverse_bo(sg_type))
+                               v = side_bswap_32(v);
+                       v >>= sg_type->u.side_basic.offset_bits;
+                       if (sg_type->u.side_basic.len_bits < 32)
+                               v &= (1U << sg_type->u.side_basic.len_bits) - 1;
+                       switch (base) {
+                       case TRACER_DISPLAY_BASE_2:
+                               print_integer_binary(v, sg_type->u.side_basic.len_bits);
+                               break;
+                       case TRACER_DISPLAY_BASE_8:
+                               printf("0%" PRIo32, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_10:
+                               printf("%" PRIu32, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_16:
+                               printf("0x%" PRIx32, v);
+                               break;
+                       default:
+                               abort();
+                       }
+                       break;
+               }
+               case 64:
+               {
+                       uint64_t v;
+
+                       memcpy(&v, ptr + sg_type->u.side_basic.integer_offset, sizeof(v));
+                       if (sg_type_to_host_reverse_bo(sg_type))
+                               v = side_bswap_64(v);
+                       v >>= sg_type->u.side_basic.offset_bits;
+                       if (sg_type->u.side_basic.len_bits < 64)
+                               v &= (1ULL << sg_type->u.side_basic.len_bits) - 1;
+                       switch (base) {
+                       case TRACER_DISPLAY_BASE_2:
+                               print_integer_binary(v, sg_type->u.side_basic.len_bits);
+                               break;
+                       case TRACER_DISPLAY_BASE_8:
+                               printf("0%" PRIo64, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_10:
+                               printf("%" PRIu64, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_16:
+                               printf("0x%" PRIx64, v);
+                               break;
+                       default:
+                               abort();
+                       }
+                       break;
+               }
+               default:
+                       fprintf(stderr, "<UNKNOWN SCATTER-GATHER INTEGER SIZE>");
+                       abort();
+               }
+               break;
+       }
+       case SIDE_TYPE_SG_SIGNED_INT:
+       {
+               tracer_print_sg_integer_type_header(sg_type);
+               switch (sg_type->u.side_basic.integer_size_bits) {
+               case 8:
+               {
+                       int8_t v;
+
+                       memcpy(&v, ptr + sg_type->u.side_basic.integer_offset, sizeof(v));
+                       v >>= sg_type->u.side_basic.offset_bits;
+                       if (sg_type->u.side_basic.len_bits < 8)
+                               v &= (1U << sg_type->u.side_basic.len_bits) - 1;
+                       switch (base) {
+                       case TRACER_DISPLAY_BASE_2:
+                               print_integer_binary(v, sg_type->u.side_basic.len_bits);
+                               break;
+                       case TRACER_DISPLAY_BASE_8:
+                               printf("0%" PRIo8, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_10:
+                               printf("%" PRId8, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_16:
+                               printf("0x%" PRIx8, v);
+                               break;
+                       default:
+                               abort();
+                       }
+                       break;
+               }
+               case 16:
+               {
+                       int16_t v;
+
+                       memcpy(&v, ptr + sg_type->u.side_basic.integer_offset, sizeof(v));
+                       if (sg_type_to_host_reverse_bo(sg_type))
+                               v = side_bswap_16(v);
+                       v >>= sg_type->u.side_basic.offset_bits;
+                       if (sg_type->u.side_basic.len_bits < 16)
+                               v &= (1U << sg_type->u.side_basic.len_bits) - 1;
+                       switch (base) {
+                       case TRACER_DISPLAY_BASE_2:
+                               print_integer_binary(v, sg_type->u.side_basic.len_bits);
+                               break;
+                       case TRACER_DISPLAY_BASE_8:
+                               printf("0%" PRIo16, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_10:
+                               printf("%" PRId16, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_16:
+                               printf("0x%" PRIx16, v);
+                               break;
+                       default:
+                               abort();
+                       }
+                       break;
+               }
+               case 32:
+               {
+                       uint32_t v;
+
+                       memcpy(&v, ptr + sg_type->u.side_basic.integer_offset, sizeof(v));
+                       if (sg_type_to_host_reverse_bo(sg_type))
+                               v = side_bswap_32(v);
+                       v >>= sg_type->u.side_basic.offset_bits;
+                       if (sg_type->u.side_basic.len_bits < 32)
+                               v &= (1U << sg_type->u.side_basic.len_bits) - 1;
+                       switch (base) {
+                       case TRACER_DISPLAY_BASE_2:
+                               print_integer_binary(v, sg_type->u.side_basic.len_bits);
+                               break;
+                       case TRACER_DISPLAY_BASE_8:
+                               printf("0%" PRIo32, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_10:
+                               printf("%" PRId32, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_16:
+                               printf("0x%" PRIx32, v);
+                               break;
+                       default:
+                               abort();
+                       }
+                       break;
+               }
+               case 64:
+               {
+                       uint64_t v;
+
+                       memcpy(&v, ptr + sg_type->u.side_basic.integer_offset, sizeof(v));
+                       if (sg_type_to_host_reverse_bo(sg_type))
+                               v = side_bswap_64(v);
+                       v >>= sg_type->u.side_basic.offset_bits;
+                       if (sg_type->u.side_basic.len_bits < 64)
+                               v &= (1ULL << sg_type->u.side_basic.len_bits) - 1;
+                       switch (base) {
+                       case TRACER_DISPLAY_BASE_2:
+                               print_integer_binary(v, sg_type->u.side_basic.len_bits);
+                               break;
+                       case TRACER_DISPLAY_BASE_8:
+                               printf("0%" PRIo64, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_10:
+                               printf("%" PRId64, v);
+                               break;
+                       case TRACER_DISPLAY_BASE_16:
+                               printf("0x%" PRIx64, v);
+                               break;
+                       default:
+                               abort();
+                       }
+                       break;
+               }
+               default:
+                       fprintf(stderr, "<UNKNOWN SCATTER-GATHER INTEGER SIZE>");
+                       abort();
+               }
+               break;
+       }
+       default:
+               fprintf(stderr, "<UNKNOWN SCATTER-GATHER TYPE>");
+               abort();
+       }
+       printf(" }");
+}
+
+static
+void tracer_print_sg_field(const struct side_struct_field_sg *field_sg, void *ptr)
+{
+       printf("%s: ", field_sg->field_name);
+       tracer_print_sg_type(&field_sg->side_type, ptr);
+}
+
+static
+void tracer_print_struct_sg(const struct side_type_description *type_desc, void *ptr)
+{
+       const struct side_type_struct_sg *struct_sg = type_desc->u.side_struct_sg;
+       int i;
+
+       print_attributes("attr", ":", struct_sg->attr, struct_sg->nr_attr);
+       printf("%s", struct_sg->nr_attr ? ", " : "");
+       printf("fields: { ");
+       for (i = 0; i < struct_sg->nr_fields; i++) {
+               printf("%s", i ? ", " : "");
+               tracer_print_sg_field(&struct_sg->fields_sg[i], ptr);
+       }
+       printf(" }");
+}
+
 static
 void tracer_print_array(const struct side_type_description *type_desc, const struct side_arg_vec_description *sav_desc)
 {
This page took 0.032026 seconds and 4 git commands to generate.