Commit | Line | Data |
---|---|---|
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 | ||
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, | |
ba845af5 | 30 | |
f611d0c3 MD |
31 | SIDE_TYPE_STRING, |
32 | SIDE_TYPE_DYNAMIC, | |
33 | SIDE_TYPE_STRUCT, | |
34 | SIDE_TYPE_ARRAY, | |
35 | SIDE_TYPE_VLA, | |
36 | SIDE_TYPE_VLA_VISITOR, | |
ba845af5 MD |
37 | |
38 | SIDE_TYPE_ARRAY_U8, | |
39 | SIDE_TYPE_ARRAY_U16, | |
40 | SIDE_TYPE_ARRAY_U32, | |
41 | SIDE_TYPE_ARRAY_U64, | |
42 | SIDE_TYPE_ARRAY_S8, | |
43 | SIDE_TYPE_ARRAY_S16, | |
44 | SIDE_TYPE_ARRAY_S32, | |
45 | SIDE_TYPE_ARRAY_S64, | |
46 | ||
1533629f MD |
47 | SIDE_TYPE_VLA_U8, |
48 | SIDE_TYPE_VLA_U16, | |
49 | SIDE_TYPE_VLA_U32, | |
50 | SIDE_TYPE_VLA_U64, | |
51 | SIDE_TYPE_VLA_S8, | |
52 | SIDE_TYPE_VLA_S16, | |
53 | SIDE_TYPE_VLA_S32, | |
54 | SIDE_TYPE_VLA_S64, | |
55 | ||
f611d0c3 | 56 | //TODO: |
f611d0c3 MD |
57 | //variants (discriminated unions) |
58 | }; | |
59 | ||
60 | enum side_loglevel { | |
61 | SIDE_LOGLEVEL_EMERG = 0, | |
62 | SIDE_LOGLEVEL_ALERT = 1, | |
63 | SIDE_LOGLEVEL_CRIT = 2, | |
64 | SIDE_LOGLEVEL_ERR = 3, | |
65 | SIDE_LOGLEVEL_WARNING = 4, | |
66 | SIDE_LOGLEVEL_NOTICE = 5, | |
67 | SIDE_LOGLEVEL_INFO = 6, | |
68 | SIDE_LOGLEVEL_DEBUG = 7, | |
69 | }; | |
70 | ||
71 | enum side_visitor_status { | |
72 | SIDE_VISITOR_STATUS_ERROR = -1, | |
73 | SIDE_VISITOR_STATUS_OK = 0, | |
74 | SIDE_VISITOR_STATUS_END = 1, | |
75 | }; | |
76 | ||
77 | typedef enum side_visitor_status (*side_visitor_begin)(void *ctx); | |
78 | typedef enum side_visitor_status (*side_visitor_end)(void *ctx); | |
79 | typedef enum side_visitor_status (*side_visitor_get_next)(void *ctx, struct side_arg_vec *sav_elem); | |
80 | ||
81 | struct side_type_description { | |
82 | enum side_type type; | |
8d02fd98 | 83 | //TODO: we should add something like a list of user attributes (namespaced strings) |
f611d0c3 MD |
84 | union { |
85 | struct { | |
86 | uint32_t nr_fields; | |
87 | const struct side_event_field *fields; | |
88 | } side_struct; | |
89 | struct { | |
90 | uint32_t length; | |
91 | const struct side_type_description *elem_type; | |
92 | } side_array; | |
93 | struct { | |
94 | const struct side_type_description *elem_type; | |
95 | } side_vla; | |
96 | struct { | |
97 | const struct side_type_description *elem_type; | |
98 | side_visitor_begin begin; | |
99 | side_visitor_end end; | |
100 | side_visitor_get_next get_next; | |
101 | } side_vla_visitor; | |
102 | } u; | |
103 | }; | |
104 | ||
105 | struct side_event_field { | |
106 | const char *field_name; | |
107 | struct side_type_description side_type; | |
108 | }; | |
109 | ||
110 | struct side_event_description { | |
111 | uint32_t version; | |
112 | uint32_t enabled; | |
113 | uint32_t loglevel; /* enum side_loglevel */ | |
114 | uint32_t nr_fields; | |
115 | const char *provider_name; | |
116 | const char *event_name; | |
117 | const struct side_event_field *fields; | |
118 | }; | |
119 | ||
120 | struct side_arg_vec { | |
121 | uint32_t type; /* enum side_type */ | |
122 | union { | |
123 | uint8_t side_u8; | |
124 | uint16_t side_u16; | |
125 | uint32_t side_u32; | |
126 | uint64_t side_u64; | |
127 | int8_t side_s8; | |
128 | int16_t side_s16; | |
129 | int32_t side_s32; | |
130 | int64_t side_s64; | |
ba845af5 | 131 | |
f611d0c3 MD |
132 | const char *string; |
133 | const struct side_arg_vec_description *side_struct; | |
134 | const struct side_arg_vec_description *side_array; | |
135 | const struct side_arg_vec_description *side_vla; | |
136 | void *side_vla_visitor_ctx; | |
ba845af5 MD |
137 | |
138 | void *side_array_fixint; | |
1533629f MD |
139 | struct { |
140 | void *p; | |
141 | uint32_t length; | |
142 | } side_vla_fixint; | |
f611d0c3 MD |
143 | } u; |
144 | }; | |
145 | ||
146 | struct side_arg_vec_description { | |
147 | const struct side_arg_vec *sav; | |
148 | uint32_t len; | |
149 | }; | |
150 | ||
151 | #define side_type_decl(_type) { .type = _type } | |
152 | #define side_field(_type, _name) { .field_name = _name, .side_type = side_type_decl(_type) } | |
153 | ||
154 | #define side_type_struct_decl(_fields) \ | |
155 | { \ | |
156 | .type = SIDE_TYPE_STRUCT, \ | |
157 | .u = { \ | |
158 | .side_struct = { \ | |
159 | .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \ | |
160 | .fields = _fields, \ | |
161 | }, \ | |
162 | }, \ | |
163 | } | |
164 | #define side_field_struct(_name, _fields) \ | |
165 | { \ | |
166 | .field_name = _name, \ | |
167 | .side_type = side_type_struct_decl(SIDE_PARAM(_fields)), \ | |
168 | } | |
169 | ||
170 | #define side_type_array_decl(_elem_type, _length) \ | |
171 | { \ | |
172 | .type = SIDE_TYPE_ARRAY, \ | |
173 | .u = { \ | |
174 | .side_array = { \ | |
175 | .length = _length, \ | |
176 | .elem_type = _elem_type, \ | |
177 | }, \ | |
178 | }, \ | |
179 | } | |
180 | #define side_field_array(_name, _elem_type, _length) \ | |
181 | { \ | |
182 | .field_name = _name, \ | |
183 | .side_type = side_type_array_decl(_elem_type, _length), \ | |
184 | } | |
185 | ||
186 | #define side_type_vla_decl(_elem_type) \ | |
187 | { \ | |
188 | .type = SIDE_TYPE_VLA, \ | |
189 | .u = { \ | |
190 | .side_vla = { \ | |
191 | .elem_type = _elem_type, \ | |
192 | }, \ | |
193 | }, \ | |
194 | } | |
195 | #define side_field_vla(_name, _elem_type) \ | |
196 | { \ | |
197 | .field_name = _name, \ | |
198 | .side_type = side_type_vla_decl(_elem_type), \ | |
199 | } | |
200 | ||
201 | #define side_type_vla_visitor_decl(_elem_type, _begin, _end, _get_next) \ | |
202 | { \ | |
203 | .type = SIDE_TYPE_VLA_VISITOR, \ | |
204 | .u = { \ | |
205 | .side_vla_visitor = { \ | |
206 | .elem_type = _elem_type, \ | |
207 | .begin = _begin, \ | |
208 | .end = _end, \ | |
209 | .get_next = _get_next, \ | |
210 | }, \ | |
211 | }, \ | |
212 | } | |
213 | #define side_field_vla_visitor(_name, _elem_type, _begin, _end, _get_next) \ | |
214 | { \ | |
215 | .field_name = _name, \ | |
216 | .side_type = side_type_vla_visitor_decl(_elem_type, _begin, _end, _get_next), \ | |
217 | } | |
218 | ||
71002b5e | 219 | #define side_elem(...) \ |
f611d0c3 MD |
220 | SIDE_COMPOUND_LITERAL(const struct side_type_description, side_type_decl(__VA_ARGS__)) |
221 | ||
222 | #define side_field_list(...) \ | |
223 | SIDE_COMPOUND_LITERAL(const struct side_event_field, __VA_ARGS__) | |
224 | ||
225 | #define side_arg_u8(val) { .type = SIDE_TYPE_U8, .u = { .side_u8 = (val) } } | |
226 | #define side_arg_u16(val) { .type = SIDE_TYPE_U16, .u = { .side_u16 = (val) } } | |
227 | #define side_arg_u32(val) { .type = SIDE_TYPE_U32, .u = { .side_u32 = (val) } } | |
228 | #define side_arg_u64(val) { .type = SIDE_TYPE_U64, .u = { .side_u64 = (val) } } | |
229 | #define side_arg_s8(val) { .type = SIDE_TYPE_S8, .u = { .side_s8 = (val) } } | |
230 | #define side_arg_s16(val) { .type = SIDE_TYPE_S16, .u = { .side_s16 = (val) } } | |
231 | #define side_arg_s32(val) { .type = SIDE_TYPE_S32, .u = { .side_s32 = (val) } } | |
232 | #define side_arg_s64(val) { .type = SIDE_TYPE_S64, .u = { .side_s64 = (val) } } | |
233 | #define side_arg_string(val) { .type = SIDE_TYPE_STRING, .u = { .string = (val) } } | |
234 | #define side_arg_struct(_side_type) { .type = SIDE_TYPE_STRUCT, .u = { .side_struct = (_side_type) } } | |
235 | #define side_arg_array(_side_type) { .type = SIDE_TYPE_ARRAY, .u = { .side_array = (_side_type) } } | |
236 | #define side_arg_vla(_side_type) { .type = SIDE_TYPE_VLA, .u = { .side_vla = (_side_type) } } | |
237 | #define side_arg_vla_visitor(_ctx) { .type = SIDE_TYPE_VLA_VISITOR, .u = { .side_vla_visitor_ctx = (_ctx) } } | |
238 | ||
1533629f MD |
239 | #define side_arg_array_u8(_ptr) { .type = SIDE_TYPE_ARRAY_U8, .u = { .side_array_fixint = (_ptr) } } |
240 | #define side_arg_array_u16(_ptr) { .type = SIDE_TYPE_ARRAY_U16, .u = { .side_array_fixint = (_ptr) } } | |
241 | #define side_arg_array_u32(_ptr) { .type = SIDE_TYPE_ARRAY_U32, .u = { .side_array_fixint = (_ptr) } } | |
242 | #define side_arg_array_u64(_ptr) { .type = SIDE_TYPE_ARRAY_U64, .u = { .side_array_fixint = (_ptr) } } | |
243 | #define side_arg_array_s8(_ptr) { .type = SIDE_TYPE_ARRAY_S8, .u = { .side_array_fixint = (_ptr) } } | |
244 | #define side_arg_array_s16(_ptr) { .type = SIDE_TYPE_ARRAY_S16, .u = { .side_array_fixint = (_ptr) } } | |
245 | #define side_arg_array_s32(_ptr) { .type = SIDE_TYPE_ARRAY_S32, .u = { .side_array_fixint = (_ptr) } } | |
246 | #define side_arg_array_s64(_ptr) { .type = SIDE_TYPE_ARRAY_S64, .u = { .side_array_fixint = (_ptr) } } | |
247 | ||
248 | #define side_arg_vla_u8(_ptr, _length) { .type = SIDE_TYPE_VLA_U8, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } | |
249 | #define side_arg_vla_u16(_ptr, _length) { .type = SIDE_TYPE_VLA_U16, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } } | |
250 | #define side_arg_vla_u32(_ptr, _length) { .type = SIDE_TYPE_VLA_U32, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } } | |
251 | #define side_arg_vla_u64(_ptr, _length) { .type = SIDE_TYPE_VLA_U64, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } } | |
252 | #define side_arg_vla_s8(_ptr, _length) { .type = SIDE_TYPE_VLA_S8, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } } | |
253 | #define side_arg_vla_s16(_ptr, _length) { .type = SIDE_TYPE_VLA_S16, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } } | |
254 | #define side_arg_vla_s32(_ptr, _length) { .type = SIDE_TYPE_VLA_S32, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } } | |
255 | #define side_arg_vla_s64(_ptr, _length) { .type = SIDE_TYPE_VLA_S64, .u = { .side_vla_fixint = { .p = (_ptr), .length = (_length) } } } | |
ba845af5 | 256 | |
f611d0c3 MD |
257 | #define side_arg_define_vec(_identifier, _sav) \ |
258 | const struct side_arg_vec _identifier##_vec[] = { _sav }; \ | |
259 | const struct side_arg_vec_description _identifier = { \ | |
260 | .sav = _identifier##_vec, \ | |
261 | .len = SIDE_ARRAY_SIZE(_identifier##_vec), \ | |
262 | } | |
263 | ||
264 | #define side_arg_list(...) __VA_ARGS__ | |
265 | ||
266 | #define side_event_cond(desc) if (side_unlikely((desc)->enabled)) | |
267 | #define side_event_call(desc, _sav) \ | |
268 | { \ | |
269 | const struct side_arg_vec side_sav[] = { _sav }; \ | |
270 | const struct side_arg_vec_description sav_desc = { \ | |
271 | .sav = side_sav, \ | |
272 | .len = SIDE_ARRAY_SIZE(side_sav), \ | |
273 | }; \ | |
274 | tracer_call(desc, &sav_desc); \ | |
275 | } | |
276 | ||
277 | #define side_event(desc, sav) \ | |
278 | side_event_cond(desc) \ | |
279 | side_event_call(desc, SIDE_PARAM(sav)); \ | |
280 | ||
281 | #define side_define_event(_identifier, _provider, _event, _loglevel, _fields) \ | |
282 | struct side_event_description _identifier = { \ | |
283 | .version = 0, \ | |
284 | .enabled = 0, \ | |
285 | .loglevel = _loglevel, \ | |
286 | .nr_fields = SIDE_ARRAY_SIZE(SIDE_PARAM(_fields)), \ | |
287 | .provider_name = _provider, \ | |
288 | .event_name = _event, \ | |
289 | .fields = _fields, \ | |
290 | } | |
291 | ||
292 | #define side_declare_event(_identifier) \ | |
293 | struct side_event_description _identifier | |
294 | ||
295 | #endif /* _SIDE_TRACE_H */ |