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