Reorganize tree
[libside.git] / include / side / trace.h
1 // SPDX-License-Identifier: MIT
2 /*
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 */
5
6 #ifndef _SIDE_TRACE_H
7 #define _SIDE_TRACE_H
8
9 #include <stdint.h>
10 #include <inttypes.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13 #include <side/macros.h>
14
15 /* SIDE stands for "Static Instrumentation Dynamically Enabled" */
16
17 struct side_arg_vec;
18 struct side_type_description;
19 struct side_event_field;
20
21 enum side_type {
22 SIDE_TYPE_U8,
23 SIDE_TYPE_U16,
24 SIDE_TYPE_U32,
25 SIDE_TYPE_U64,
26 SIDE_TYPE_S8,
27 SIDE_TYPE_S16,
28 SIDE_TYPE_S32,
29 SIDE_TYPE_S64,
30 SIDE_TYPE_STRING,
31 SIDE_TYPE_DYNAMIC,
32 SIDE_TYPE_STRUCT,
33 SIDE_TYPE_ARRAY,
34 SIDE_TYPE_VLA,
35 SIDE_TYPE_VLA_VISITOR,
36 //TODO:
37 //specialized array and vla for fixed-size integers (optimization)
38 //variants (discriminated unions)
39 };
40
41 enum side_loglevel {
42 SIDE_LOGLEVEL_EMERG = 0,
43 SIDE_LOGLEVEL_ALERT = 1,
44 SIDE_LOGLEVEL_CRIT = 2,
45 SIDE_LOGLEVEL_ERR = 3,
46 SIDE_LOGLEVEL_WARNING = 4,
47 SIDE_LOGLEVEL_NOTICE = 5,
48 SIDE_LOGLEVEL_INFO = 6,
49 SIDE_LOGLEVEL_DEBUG = 7,
50 };
51
52 enum side_visitor_status {
53 SIDE_VISITOR_STATUS_ERROR = -1,
54 SIDE_VISITOR_STATUS_OK = 0,
55 SIDE_VISITOR_STATUS_END = 1,
56 };
57
58 typedef enum side_visitor_status (*side_visitor_begin)(void *ctx);
59 typedef enum side_visitor_status (*side_visitor_end)(void *ctx);
60 typedef enum side_visitor_status (*side_visitor_get_next)(void *ctx, struct side_arg_vec *sav_elem);
61
62 struct side_type_description {
63 enum side_type type;
64 union {
65 struct {
66 uint32_t nr_fields;
67 const struct side_event_field *fields;
68 } side_struct;
69 struct {
70 uint32_t length;
71 const struct side_type_description *elem_type;
72 } side_array;
73 struct {
74 const struct side_type_description *elem_type;
75 } side_vla;
76 struct {
77 const struct side_type_description *elem_type;
78 side_visitor_begin begin;
79 side_visitor_end end;
80 side_visitor_get_next get_next;
81 } side_vla_visitor;
82 } u;
83 };
84
85 struct side_event_field {
86 const char *field_name;
87 struct side_type_description side_type;
88 };
89
90 struct side_event_description {
91 uint32_t version;
92 uint32_t enabled;
93 uint32_t loglevel; /* enum side_loglevel */
94 uint32_t nr_fields;
95 const char *provider_name;
96 const char *event_name;
97 const struct side_event_field *fields;
98 };
99
100 struct side_arg_vec {
101 uint32_t type; /* enum side_type */
102 union {
103 uint8_t side_u8;
104 uint16_t side_u16;
105 uint32_t side_u32;
106 uint64_t side_u64;
107 int8_t side_s8;
108 int16_t side_s16;
109 int32_t side_s32;
110 int64_t side_s64;
111 const char *string;
112 const struct side_arg_vec_description *side_struct;
113 const struct side_arg_vec_description *side_array;
114 const struct side_arg_vec_description *side_vla;
115 void *side_vla_visitor_ctx;
116 } u;
117 };
118
119 struct side_arg_vec_description {
120 const struct side_arg_vec *sav;
121 uint32_t len;
122 };
123
124 #define side_type_decl(_type) { .type = _type }
125 #define side_field(_type, _name) { .field_name = _name, .side_type = side_type_decl(_type) }
126
127 #define side_type_struct_decl(_fields) \
128 { \
129 .type = SIDE_TYPE_STRUCT, \
130 .u = { \
131 .side_struct = { \
132 .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
133 .fields = _fields, \
134 }, \
135 }, \
136 }
137 #define side_field_struct(_name, _fields) \
138 { \
139 .field_name = _name, \
140 .side_type = side_type_struct_decl(SIDE_PARAM(_fields)), \
141 }
142
143 #define side_type_array_decl(_elem_type, _length) \
144 { \
145 .type = SIDE_TYPE_ARRAY, \
146 .u = { \
147 .side_array = { \
148 .length = _length, \
149 .elem_type = _elem_type, \
150 }, \
151 }, \
152 }
153 #define side_field_array(_name, _elem_type, _length) \
154 { \
155 .field_name = _name, \
156 .side_type = side_type_array_decl(_elem_type, _length), \
157 }
158
159 #define side_type_vla_decl(_elem_type) \
160 { \
161 .type = SIDE_TYPE_VLA, \
162 .u = { \
163 .side_vla = { \
164 .elem_type = _elem_type, \
165 }, \
166 }, \
167 }
168 #define side_field_vla(_name, _elem_type) \
169 { \
170 .field_name = _name, \
171 .side_type = side_type_vla_decl(_elem_type), \
172 }
173
174 #define side_type_vla_visitor_decl(_elem_type, _begin, _end, _get_next) \
175 { \
176 .type = SIDE_TYPE_VLA_VISITOR, \
177 .u = { \
178 .side_vla_visitor = { \
179 .elem_type = _elem_type, \
180 .begin = _begin, \
181 .end = _end, \
182 .get_next = _get_next, \
183 }, \
184 }, \
185 }
186 #define side_field_vla_visitor(_name, _elem_type, _begin, _end, _get_next) \
187 { \
188 .field_name = _name, \
189 .side_type = side_type_vla_visitor_decl(_elem_type, _begin, _end, _get_next), \
190 }
191
192 #define side_vla_elem(...) \
193 SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__))
194
195 #define side_vla_visitor_elem(...) \
196 SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__))
197
198 #define side_array_elem(...) \
199 SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__))
200
201 #define side_field_list(...) \
202 SIDE_COMPOUND_LITERAL(const struct side_event_field, __VA_ARGS__)
203
204 #define side_arg_u8(val) { .type = SIDE_TYPE_U8, .u = { .side_u8 = (val) } }
205 #define side_arg_u16(val) { .type = SIDE_TYPE_U16, .u = { .side_u16 = (val) } }
206 #define side_arg_u32(val) { .type = SIDE_TYPE_U32, .u = { .side_u32 = (val) } }
207 #define side_arg_u64(val) { .type = SIDE_TYPE_U64, .u = { .side_u64 = (val) } }
208 #define side_arg_s8(val) { .type = SIDE_TYPE_S8, .u = { .side_s8 = (val) } }
209 #define side_arg_s16(val) { .type = SIDE_TYPE_S16, .u = { .side_s16 = (val) } }
210 #define side_arg_s32(val) { .type = SIDE_TYPE_S32, .u = { .side_s32 = (val) } }
211 #define side_arg_s64(val) { .type = SIDE_TYPE_S64, .u = { .side_s64 = (val) } }
212 #define side_arg_string(val) { .type = SIDE_TYPE_STRING, .u = { .string = (val) } }
213 #define side_arg_struct(_side_type) { .type = SIDE_TYPE_STRUCT, .u = { .side_struct = (_side_type) } }
214 #define side_arg_array(_side_type) { .type = SIDE_TYPE_ARRAY, .u = { .side_array = (_side_type) } }
215 #define side_arg_vla(_side_type) { .type = SIDE_TYPE_VLA, .u = { .side_vla = (_side_type) } }
216 #define side_arg_vla_visitor(_ctx) { .type = SIDE_TYPE_VLA_VISITOR, .u = { .side_vla_visitor_ctx = (_ctx) } }
217
218 #define side_arg_define_vec(_identifier, _sav) \
219 const struct side_arg_vec _identifier##_vec[] = { _sav }; \
220 const struct side_arg_vec_description _identifier = { \
221 .sav = _identifier##_vec, \
222 .len = SIDE_ARRAY_SIZE(_identifier##_vec), \
223 }
224
225 #define side_arg_list(...) __VA_ARGS__
226
227 #define side_event_cond(desc) if (side_unlikely((desc)->enabled))
228 #define side_event_call(desc, _sav) \
229 { \
230 const struct side_arg_vec side_sav[] = { _sav }; \
231 const struct side_arg_vec_description sav_desc = { \
232 .sav = side_sav, \
233 .len = SIDE_ARRAY_SIZE(side_sav), \
234 }; \
235 tracer_call(desc, &sav_desc); \
236 }
237
238 #define side_event(desc, sav) \
239 side_event_cond(desc) \
240 side_event_call(desc, SIDE_PARAM(sav)); \
241
242 #define side_define_event(_identifier, _provider, _event, _loglevel, _fields) \
243 struct side_event_description _identifier = { \
244 .version = 0, \
245 .enabled = 0, \
246 .loglevel = _loglevel, \
247 .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
248 .provider_name = _provider, \
249 .event_name = _event, \
250 .fields = _fields, \
251 }
252
253 #define side_declare_event(_identifier) \
254 struct side_event_description _identifier
255
256 #endif /* _SIDE_TRACE_H */
This page took 0.062588 seconds and 4 git commands to generate.