side_field: reverse order of parameters
[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_arg_vec_description;
19 struct side_arg_dynamic_vec;
20 struct side_arg_dynamic_vec_vla;
21 struct side_type_description;
22 struct side_event_field;
23 struct side_tracer_visitor_ctx;
24 struct side_tracer_dynamic_struct_visitor_ctx;
25 struct side_tracer_dynamic_vla_visitor_ctx;
26
27 enum side_type {
28 SIDE_TYPE_U8,
29 SIDE_TYPE_U16,
30 SIDE_TYPE_U32,
31 SIDE_TYPE_U64,
32 SIDE_TYPE_S8,
33 SIDE_TYPE_S16,
34 SIDE_TYPE_S32,
35 SIDE_TYPE_S64,
36
37 SIDE_TYPE_STRING,
38
39 SIDE_TYPE_STRUCT,
40 SIDE_TYPE_ARRAY,
41 SIDE_TYPE_VLA,
42 SIDE_TYPE_VLA_VISITOR,
43
44 SIDE_TYPE_ARRAY_U8,
45 SIDE_TYPE_ARRAY_U16,
46 SIDE_TYPE_ARRAY_U32,
47 SIDE_TYPE_ARRAY_U64,
48 SIDE_TYPE_ARRAY_S8,
49 SIDE_TYPE_ARRAY_S16,
50 SIDE_TYPE_ARRAY_S32,
51 SIDE_TYPE_ARRAY_S64,
52
53 SIDE_TYPE_VLA_U8,
54 SIDE_TYPE_VLA_U16,
55 SIDE_TYPE_VLA_U32,
56 SIDE_TYPE_VLA_U64,
57 SIDE_TYPE_VLA_S8,
58 SIDE_TYPE_VLA_S16,
59 SIDE_TYPE_VLA_S32,
60 SIDE_TYPE_VLA_S64,
61
62 SIDE_TYPE_DYNAMIC,
63 };
64
65 enum side_dynamic_type {
66 SIDE_DYNAMIC_TYPE_NULL,
67
68 SIDE_DYNAMIC_TYPE_U8,
69 SIDE_DYNAMIC_TYPE_U16,
70 SIDE_DYNAMIC_TYPE_U32,
71 SIDE_DYNAMIC_TYPE_U64,
72 SIDE_DYNAMIC_TYPE_S8,
73 SIDE_DYNAMIC_TYPE_S16,
74 SIDE_DYNAMIC_TYPE_S32,
75 SIDE_DYNAMIC_TYPE_S64,
76
77 SIDE_DYNAMIC_TYPE_STRING,
78
79 SIDE_DYNAMIC_TYPE_STRUCT,
80 SIDE_DYNAMIC_TYPE_STRUCT_VISITOR,
81
82 SIDE_DYNAMIC_TYPE_VLA,
83 SIDE_DYNAMIC_TYPE_VLA_VISITOR,
84 };
85
86 enum side_loglevel {
87 SIDE_LOGLEVEL_EMERG = 0,
88 SIDE_LOGLEVEL_ALERT = 1,
89 SIDE_LOGLEVEL_CRIT = 2,
90 SIDE_LOGLEVEL_ERR = 3,
91 SIDE_LOGLEVEL_WARNING = 4,
92 SIDE_LOGLEVEL_NOTICE = 5,
93 SIDE_LOGLEVEL_INFO = 6,
94 SIDE_LOGLEVEL_DEBUG = 7,
95 };
96
97 enum side_visitor_status {
98 SIDE_VISITOR_STATUS_OK = 0,
99 SIDE_VISITOR_STATUS_ERROR = -1,
100 };
101
102 typedef enum side_visitor_status (*side_visitor)(const struct side_tracer_visitor_ctx *tracer_ctx,
103 void *app_ctx);
104 typedef enum side_visitor_status (*side_dynamic_struct_visitor)(const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx,
105 void *app_ctx);
106 typedef enum side_visitor_status (*side_dynamic_vla_visitor)(const struct side_tracer_dynamic_vla_visitor_ctx *tracer_ctx,
107 void *app_ctx);
108
109 struct side_type_description {
110 enum side_type type;
111 //TODO: we should add something like a list of user attributes (namespaced strings)
112 union {
113 struct {
114 uint32_t nr_fields;
115 const struct side_event_field *fields;
116 } side_struct;
117 struct {
118 uint32_t length;
119 const struct side_type_description *elem_type;
120 } side_array;
121 struct {
122 const struct side_type_description *elem_type;
123 } side_vla;
124 struct {
125 const struct side_type_description *elem_type;
126 side_visitor visitor;
127 } side_vla_visitor;
128 } u;
129 };
130
131 struct side_event_field {
132 const char *field_name;
133 struct side_type_description side_type;
134 };
135
136 struct side_event_description {
137 uint32_t version;
138 uint32_t enabled;
139 uint32_t loglevel; /* enum side_loglevel */
140 uint32_t nr_fields;
141 const char *provider_name;
142 const char *event_name;
143 const struct side_event_field *fields;
144 };
145
146 struct side_arg_dynamic_vec_vla {
147 const struct side_arg_dynamic_vec *sav;
148 uint32_t len;
149 };
150
151 struct side_arg_dynamic_vec {
152 uint32_t type; /* enum side_dynamic_type */
153 union {
154 uint8_t side_u8;
155 uint16_t side_u16;
156 uint32_t side_u32;
157 uint64_t side_u64;
158 int8_t side_s8;
159 int16_t side_s16;
160 int32_t side_s32;
161 int64_t side_s64;
162
163 const char *string;
164
165 const struct side_arg_dynamic_event_struct *side_dynamic_struct;
166 struct {
167 void *app_dynamic_visitor_ctx;
168 side_dynamic_struct_visitor visitor;
169 } side_dynamic_struct_visitor;
170
171 const struct side_arg_dynamic_vec_vla *side_dynamic_vla;
172 struct {
173 void *app_dynamic_visitor_ctx;
174 side_dynamic_vla_visitor visitor;
175 } side_dynamic_vla_visitor;
176 } u;
177 };
178
179 struct side_arg_dynamic_event_field {
180 const char *field_name;
181 const struct side_arg_dynamic_vec elem;
182 //TODO: we should add something like a list of user attributes (namespaced strings)
183 };
184
185 struct side_arg_dynamic_event_struct {
186 const struct side_arg_dynamic_event_field *fields;
187 uint32_t len;
188 };
189
190 struct side_arg_vec {
191 uint32_t type; /* enum side_type */
192 union {
193 uint8_t side_u8;
194 uint16_t side_u16;
195 uint32_t side_u32;
196 uint64_t side_u64;
197 int8_t side_s8;
198 int16_t side_s16;
199 int32_t side_s32;
200 int64_t side_s64;
201
202 const char *string;
203 const struct side_arg_vec_description *side_struct;
204 const struct side_arg_vec_description *side_array;
205 const struct side_arg_vec_description *side_vla;
206 void *side_vla_app_visitor_ctx;
207
208 void *side_array_fixint;
209 struct {
210 void *p;
211 uint32_t length;
212 } side_vla_fixint;
213
214 struct side_arg_dynamic_vec dynamic;
215 } u;
216 };
217
218 struct side_arg_vec_description {
219 const struct side_arg_vec *sav;
220 uint32_t len;
221 };
222
223 /* The visitor pattern is a double-dispatch visitor. */
224 struct side_tracer_visitor_ctx {
225 enum side_visitor_status (*write_elem)(const struct side_tracer_visitor_ctx *tracer_ctx,
226 const struct side_arg_vec *elem);
227 void *priv; /* Private tracer context. */
228 };
229
230 struct side_tracer_dynamic_struct_visitor_ctx {
231 enum side_visitor_status (*write_field)(const struct side_tracer_dynamic_struct_visitor_ctx *tracer_ctx,
232 const struct side_arg_dynamic_event_field *field);
233 void *priv; /* Private tracer context. */
234 };
235
236 struct side_tracer_dynamic_vla_visitor_ctx {
237 enum side_visitor_status (*write_elem)(const struct side_tracer_dynamic_vla_visitor_ctx *tracer_ctx,
238 const struct side_arg_dynamic_vec *elem);
239 void *priv; /* Private tracer context. */
240 };
241
242 #define side_type_decl(_type) { .type = _type }
243 #define side_field(_name, _type) { .field_name = _name, .side_type = side_type_decl(_type) }
244
245 #define side_type_struct_decl(_fields) \
246 { \
247 .type = SIDE_TYPE_STRUCT, \
248 .u = { \
249 .side_struct = { \
250 .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
251 .fields = _fields, \
252 }, \
253 }, \
254 }
255 #define side_field_struct(_name, _fields) \
256 { \
257 .field_name = _name, \
258 .side_type = side_type_struct_decl(SIDE_PARAM(_fields)), \
259 }
260
261 #define side_type_array_decl(_elem_type, _length) \
262 { \
263 .type = SIDE_TYPE_ARRAY, \
264 .u = { \
265 .side_array = { \
266 .length = _length, \
267 .elem_type = _elem_type, \
268 }, \
269 }, \
270 }
271 #define side_field_array(_name, _elem_type, _length) \
272 { \
273 .field_name = _name, \
274 .side_type = side_type_array_decl(_elem_type, _length), \
275 }
276
277 #define side_type_vla_decl(_elem_type) \
278 { \
279 .type = SIDE_TYPE_VLA, \
280 .u = { \
281 .side_vla = { \
282 .elem_type = _elem_type, \
283 }, \
284 }, \
285 }
286 #define side_field_vla(_name, _elem_type) \
287 { \
288 .field_name = _name, \
289 .side_type = side_type_vla_decl(_elem_type), \
290 }
291
292 #define side_type_vla_visitor_decl(_elem_type, _visitor) \
293 { \
294 .type = SIDE_TYPE_VLA_VISITOR, \
295 .u = { \
296 .side_vla_visitor = { \
297 .elem_type = SIDE_PARAM(_elem_type), \
298 .visitor = _visitor, \
299 }, \
300 }, \
301 }
302 #define side_field_vla_visitor(_name, _elem_type, _visitor) \
303 { \
304 .field_name = _name, \
305 .side_type = side_type_vla_visitor_decl(SIDE_PARAM(_elem_type), _visitor), \
306 }
307
308 #define side_elem(...) \
309 SIDE_COMPOUND_LITERAL(const struct side_type_description, __VA_ARGS__)
310
311 #define side_elem_type(...) \
312 side_elem(side_type_decl(__VA_ARGS__))
313
314 #define side_field_list(...) \
315 SIDE_COMPOUND_LITERAL(const struct side_event_field, __VA_ARGS__)
316
317 #define side_arg_u8(val) { .type = SIDE_TYPE_U8, .u = { .side_u8 = (val) } }
318 #define side_arg_u16(val) { .type = SIDE_TYPE_U16, .u = { .side_u16 = (val) } }
319 #define side_arg_u32(val) { .type = SIDE_TYPE_U32, .u = { .side_u32 = (val) } }
320 #define side_arg_u64(val) { .type = SIDE_TYPE_U64, .u = { .side_u64 = (val) } }
321 #define side_arg_s8(val) { .type = SIDE_TYPE_S8, .u = { .side_s8 = (val) } }
322 #define side_arg_s16(val) { .type = SIDE_TYPE_S16, .u = { .side_s16 = (val) } }
323 #define side_arg_s32(val) { .type = SIDE_TYPE_S32, .u = { .side_s32 = (val) } }
324 #define side_arg_s64(val) { .type = SIDE_TYPE_S64, .u = { .side_s64 = (val) } }
325 #define side_arg_string(val) { .type = SIDE_TYPE_STRING, .u = { .string = (val) } }
326 #define side_arg_struct(_side_type) { .type = SIDE_TYPE_STRUCT, .u = { .side_struct = (_side_type) } }
327 #define side_arg_array(_side_type) { .type = SIDE_TYPE_ARRAY, .u = { .side_array = (_side_type) } }
328 #define side_arg_vla(_side_type) { .type = SIDE_TYPE_VLA, .u = { .side_vla = (_side_type) } }
329 #define side_arg_vla_visitor(_ctx) { .type = SIDE_TYPE_VLA_VISITOR, .u = { .side_vla_app_visitor_ctx = (_ctx) } }
330
331 #define side_arg_array_u8(_ptr) { .type = SIDE_TYPE_ARRAY_U8, .u = { .side_array_fixint = (_ptr) } }
332 #define side_arg_array_u16(_ptr) { .type = SIDE_TYPE_ARRAY_U16, .u = { .side_array_fixint = (_ptr) } }
333 #define side_arg_array_u32(_ptr) { .type = SIDE_TYPE_ARRAY_U32, .u = { .side_array_fixint = (_ptr) } }
334 #define side_arg_array_u64(_ptr) { .type = SIDE_TYPE_ARRAY_U64, .u = { .side_array_fixint = (_ptr) } }
335 #define side_arg_array_s8(_ptr) { .type = SIDE_TYPE_ARRAY_S8, .u = { .side_array_fixint = (_ptr) } }
336 #define side_arg_array_s16(_ptr) { .type = SIDE_TYPE_ARRAY_S16, .u = { .side_array_fixint = (_ptr) } }
337 #define side_arg_array_s32(_ptr) { .type = SIDE_TYPE_ARRAY_S32, .u = { .side_array_fixint = (_ptr) } }
338 #define side_arg_array_s64(_ptr) { .type = SIDE_TYPE_ARRAY_S64, .u = { .side_array_fixint = (_ptr) } }
339
340 #define side_arg_vla_u8(_ptr, _length) { .type = SIDE_TYPE_VLA_U8, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } }
341 #define side_arg_vla_u16(_ptr, _length) { .type = SIDE_TYPE_VLA_U16, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
342 #define side_arg_vla_u32(_ptr, _length) { .type = SIDE_TYPE_VLA_U32, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
343 #define side_arg_vla_u64(_ptr, _length) { .type = SIDE_TYPE_VLA_U64, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
344 #define side_arg_vla_s8(_ptr, _length) { .type = SIDE_TYPE_VLA_S8, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
345 #define side_arg_vla_s16(_ptr, _length) { .type = SIDE_TYPE_VLA_S16, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
346 #define side_arg_vla_s32(_ptr, _length) { .type = SIDE_TYPE_VLA_S32, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
347 #define side_arg_vla_s64(_ptr, _length) { .type = SIDE_TYPE_VLA_S64, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } }
348
349 #define side_arg_dynamic(dynamic_arg_type) \
350 { \
351 .type = SIDE_TYPE_DYNAMIC, \
352 .u = { \
353 .dynamic = dynamic_arg_type, \
354 }, \
355 }
356
357 #define side_arg_dynamic_null(val) { .type = SIDE_DYNAMIC_TYPE_NULL }
358
359 #define side_arg_dynamic_u8(val) { .type = SIDE_DYNAMIC_TYPE_U8, .u = { .side_u8 = (val) } }
360 #define side_arg_dynamic_u16(val) { .type = SIDE_DYNAMIC_TYPE_U16, .u = { .side_u16 = (val) } }
361 #define side_arg_dynamic_u32(val) { .type = SIDE_DYNAMIC_TYPE_U32, .u = { .side_u32 = (val) } }
362 #define side_arg_dynamic_u64(val) { .type = SIDE_DYNAMIC_TYPE_U64, .u = { .side_u64 = (val) } }
363 #define side_arg_dynamic_s8(val) { .type = SIDE_DYNAMIC_TYPE_S8, .u = { .side_s8 = (val) } }
364 #define side_arg_dynamic_s16(val) { .type = SIDE_DYNAMIC_TYPE_S16, .u = { .side_s16 = (val) } }
365 #define side_arg_dynamic_s32(val) { .type = SIDE_DYNAMIC_TYPE_S32, .u = { .side_s32 = (val) } }
366 #define side_arg_dynamic_s64(val) { .type = SIDE_DYNAMIC_TYPE_S64, .u = { .side_s64 = (val) } }
367 #define side_arg_dynamic_string(val) { .type = SIDE_DYNAMIC_TYPE_STRING, .u = { .string = (val) } }
368
369 #define side_arg_dynamic_vla(_vla) { .type = SIDE_DYNAMIC_TYPE_VLA, .u = { .side_dynamic_vla = (_vla) } }
370 #define side_arg_dynamic_vla_visitor(_dynamic_vla_visitor, _ctx) \
371 { \
372 .type = SIDE_DYNAMIC_TYPE_VLA_VISITOR, \
373 .app_dynamic_visitor_ctx = _ctx, \
374 .u = { \
375 .vla_visitor = _dynamic_vla_visitor, \
376 }, \
377 }
378
379 #define side_arg_dynamic_struct(_struct) { .type = SIDE_DYNAMIC_TYPE_STRUCT, .u = { .side_dynamic_struct = (_struct) } }
380 #define side_arg_dynamic_struct_visitor(_dynamic_struct_visitor, _ctx) \
381 { \
382 .type = SIDE_DYNAMIC_TYPE_STRUCT_VISITOR, \
383 .app_dynamic_visitor_ctx = _ctx, \
384 .u = { \
385 .struct_visitor = _dynamic_struct_visitor, \
386 }, \
387 }
388
389 #define side_arg_dynamic_define_vec(_identifier, _sav) \
390 const struct side_arg_dynamic_vec _identifier##_vec[] = { _sav }; \
391 const struct side_arg_dynamic_vec_vla _identifier = { \
392 .sav = _identifier##_vec, \
393 .len = SIDE_ARRAY_SIZE(_identifier##_vec), \
394 }
395
396 #define side_arg_dynamic_define_struct(_identifier, _struct_fields) \
397 const struct side_arg_dynamic_event_field _identifier##_fields[] = { _struct_fields }; \
398 const struct side_arg_dynamic_event_struct _identifier = { \
399 .fields = _identifier##_fields, \
400 .len = SIDE_ARRAY_SIZE(_identifier##_fields), \
401 }
402
403 #define side_arg_define_vec(_identifier, _sav) \
404 const struct side_arg_vec _identifier##_vec[] = { _sav }; \
405 const struct side_arg_vec_description _identifier = { \
406 .sav = _identifier##_vec, \
407 .len = SIDE_ARRAY_SIZE(_identifier##_vec), \
408 }
409
410 #define side_arg_dynamic_field(_name, _elem) \
411 { \
412 .field_name = _name, \
413 .elem = _elem, \
414 }
415
416 #define side_arg_list(...) __VA_ARGS__
417
418 #define side_event_cond(desc) if (side_unlikely((desc)->enabled))
419 #define side_event_call(desc, _sav) \
420 { \
421 const struct side_arg_vec side_sav[] = { _sav }; \
422 const struct side_arg_vec_description sav_desc = { \
423 .sav = side_sav, \
424 .len = SIDE_ARRAY_SIZE(side_sav), \
425 }; \
426 tracer_call(desc, &sav_desc); \
427 }
428
429 #define side_event(desc, sav) \
430 side_event_cond(desc) \
431 side_event_call(desc, SIDE_PARAM(sav)); \
432
433 #define side_define_event(_identifier, _provider, _event, _loglevel, _fields) \
434 struct side_event_description _identifier = { \
435 .version = 0, \
436 .enabled = 0, \
437 .loglevel = _loglevel, \
438 .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \
439 .provider_name = _provider, \
440 .event_name = _event, \
441 .fields = _fields, \
442 }
443
444 #define side_declare_event(_identifier) \
445 struct side_event_description _identifier
446
447 #endif /* _SIDE_TRACE_H */
This page took 0.040876 seconds and 5 git commands to generate.