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