Commit | Line | Data |
---|---|---|
13405819 PP |
1 | # The MIT License (MIT) |
2 | # | |
4a90140d | 3 | # Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com> |
13405819 | 4 | # |
1378f213 PP |
5 | # Permission is hereby granted, free of charge, to any person obtaining |
6 | # a copy of this software and associated documentation files (the | |
7 | # "Software"), to deal in the Software without restriction, including | |
8 | # without limitation the rights to use, copy, modify, merge, publish, | |
9 | # distribute, sublicense, and/or sell copies of the Software, and to | |
10 | # permit persons to whom the Software is furnished to do so, subject to | |
11 | # the following conditions: | |
13405819 | 12 | # |
1378f213 PP |
13 | # The above copyright notice and this permission notice shall be |
14 | # included in all copies or substantial portions of the Software. | |
13405819 | 15 | # |
1378f213 PP |
16 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
17 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
18 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
19 | # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
20 | # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
21 | # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
22 | # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
13405819 | 23 | |
e5aa0be3 PP |
24 | _FUNC_INIT_PROTO = '''/* initialize context */ |
25 | void {prefix}init( | |
f66be07f | 26 | void *vctx, |
e5aa0be3 PP |
27 | uint8_t *buf, |
28 | uint32_t buf_size, | |
29 | struct {prefix}platform_callbacks cbs, | |
30 | void *data | |
31 | )''' | |
32 | ||
33 | ||
34 | _FUNC_INIT_BODY = '''{{ | |
f66be07f PP |
35 | struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx); |
36 | ctx->cbs = cbs; | |
37 | ctx->data = data; | |
38 | ctx->buf = buf; | |
39 | ctx->packet_size = _BYTES_TO_BITS(buf_size); | |
40 | ctx->at = 0; | |
41 | ctx->events_discarded = 0; | |
42 | ctx->packet_is_open = 0; | |
3cb793a1 PP |
43 | ctx->in_tracing_section = 0; |
44 | ctx->is_tracing_enabled = 1; | |
27bc6f1e | 45 | ctx->use_cur_last_event_ts = 0; |
e5aa0be3 PP |
46 | }}''' |
47 | ||
48 | ||
2277c89f | 49 | _FUNC_OPEN_PROTO_BEGIN = '''/* open packet for stream `{sname}` */ |
e5aa0be3 PP |
50 | void {prefix}{sname}_open_packet( |
51 | struct {prefix}{sname}_ctx *ctx''' | |
52 | ||
53 | ||
54 | _FUNC_OPEN_PROTO_END = ')' | |
55 | ||
56 | ||
3cb793a1 PP |
57 | _FUNC_OPEN_BODY_BEGIN = '''{{ |
58 | {ts} | |
59 | const int saved_in_tracing_section = ctx->parent.in_tracing_section; | |
60 | ||
61 | /* | |
62 | * This function is either called by a tracing function, or | |
63 | * directly by the platform. | |
64 | * | |
65 | * If it's called by a tracing function, then | |
66 | * ctx->parent.in_tracing_section is 1, so it's safe to open | |
67 | * the packet here (alter the packet), even if tracing was | |
68 | * disabled in the meantime because we're already in a tracing | |
69 | * section (which finishes at the end of the tracing function | |
70 | * call). | |
71 | * | |
72 | * If it's called directly by the platform, then if tracing is | |
73 | * disabled, we don't want to alter the packet, and return | |
74 | * immediately. | |
75 | */ | |
76 | if (!ctx->parent.is_tracing_enabled && !saved_in_tracing_section) {{ | |
77 | ctx->parent.in_tracing_section = 0; | |
78 | return; | |
79 | }} | |
80 | ||
81 | /* we can modify the packet */ | |
82 | ctx->parent.in_tracing_section = 1; | |
83 | ''' | |
e5aa0be3 PP |
84 | |
85 | ||
86 | _FUNC_OPEN_BODY_END = ''' | |
27bc6f1e | 87 | /* save content beginning's offset */ |
e5aa0be3 PP |
88 | ctx->parent.off_content = ctx->parent.at; |
89 | ||
90 | /* mark current packet as open */ | |
91 | ctx->parent.packet_is_open = 1; | |
3cb793a1 PP |
92 | |
93 | /* not tracing anymore */ | |
94 | ctx->parent.in_tracing_section = saved_in_tracing_section; | |
e5aa0be3 PP |
95 | }''' |
96 | ||
97 | ||
2277c89f | 98 | _FUNC_CLOSE_PROTO = '''/* close packet for stream `{sname}` */ |
e5aa0be3 PP |
99 | void {prefix}{sname}_close_packet(struct {prefix}{sname}_ctx *ctx)''' |
100 | ||
101 | ||
3cb793a1 PP |
102 | _FUNC_CLOSE_BODY_BEGIN = '''{{ |
103 | {ts} | |
104 | const int saved_in_tracing_section = ctx->parent.in_tracing_section; | |
105 | ||
106 | /* | |
107 | * This function is either called by a tracing function, or | |
108 | * directly by the platform. | |
109 | * | |
110 | * If it's called by a tracing function, then | |
111 | * ctx->parent.in_tracing_section is 1, so it's safe to close | |
112 | * the packet here (alter the packet), even if tracing was | |
113 | * disabled in the meantime, because we're already in a tracing | |
114 | * section (which finishes at the end of the tracing function | |
115 | * call). | |
116 | * | |
117 | * If it's called directly by the platform, then if tracing is | |
118 | * disabled, we don't want to alter the packet, and return | |
119 | * immediately. | |
120 | */ | |
121 | if (!ctx->parent.is_tracing_enabled && !saved_in_tracing_section) {{ | |
122 | ctx->parent.in_tracing_section = 0; | |
123 | return; | |
124 | }} | |
125 | ||
126 | /* we can modify the packet */ | |
127 | ctx->parent.in_tracing_section = 1; | |
128 | ''' | |
e5aa0be3 PP |
129 | |
130 | ||
131 | _FUNC_CLOSE_BODY_END = ''' | |
132 | /* go back to end of packet */ | |
133 | ctx->parent.at = ctx->parent.packet_size; | |
134 | ||
135 | /* mark packet as closed */ | |
136 | ctx->parent.packet_is_open = 0; | |
3cb793a1 PP |
137 | |
138 | /* not tracing anymore */ | |
139 | ctx->parent.in_tracing_section = saved_in_tracing_section; | |
e5aa0be3 PP |
140 | }''' |
141 | ||
142 | ||
2277c89f | 143 | _FUNC_TRACE_PROTO_BEGIN = '''/* trace (stream `{sname}`, event `{evname}`) */ |
e5aa0be3 PP |
144 | void {prefix}{sname}_trace_{evname}( |
145 | struct {prefix}{sname}_ctx *ctx''' | |
146 | ||
147 | ||
148 | _FUNC_TRACE_PROTO_END = ')' | |
149 | ||
150 | ||
151 | _FUNC_TRACE_BODY = '''{{ | |
152 | uint32_t ev_size; | |
153 | ||
27bc6f1e PP |
154 | /* save timestamp */ |
155 | {save_ts} | |
156 | ||
3cb793a1 PP |
157 | if (!ctx->parent.is_tracing_enabled) {{ |
158 | return; | |
159 | }} | |
160 | ||
161 | /* we can modify the packet */ | |
162 | ctx->parent.in_tracing_section = 1; | |
163 | ||
e5aa0be3 | 164 | /* get event size */ |
f66be07f | 165 | ev_size = _get_event_size_{sname}_{evname}(TO_VOID_PTR(ctx){params}); |
e5aa0be3 PP |
166 | |
167 | /* do we have enough space to serialize? */ | |
f66be07f | 168 | if (!_reserve_event_space(TO_VOID_PTR(ctx), ev_size)) {{ |
e5aa0be3 | 169 | /* no: forget this */ |
3cb793a1 | 170 | ctx->parent.in_tracing_section = 0; |
e5aa0be3 PP |
171 | return; |
172 | }} | |
173 | ||
174 | /* serialize event */ | |
27bc6f1e | 175 | _serialize_event_{sname}_{evname}(TO_VOID_PTR(ctx){params}); |
e5aa0be3 PP |
176 | |
177 | /* commit event */ | |
f66be07f | 178 | _commit_event(TO_VOID_PTR(ctx)); |
3cb793a1 PP |
179 | |
180 | /* not tracing anymore */ | |
181 | ctx->parent.in_tracing_section = 0; | |
e5aa0be3 PP |
182 | }}''' |
183 | ||
184 | ||
185 | _FUNC_GET_EVENT_SIZE_PROTO_BEGIN = '''static uint32_t _get_event_size_{sname}_{evname}( | |
f66be07f | 186 | void *vctx''' |
e5aa0be3 PP |
187 | |
188 | ||
189 | _FUNC_GET_EVENT_SIZE_PROTO_END = ')' | |
190 | ||
191 | ||
f66be07f PP |
192 | _FUNC_GET_EVENT_SIZE_BODY_BEGIN = '''{{ |
193 | struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx); | |
e5aa0be3 PP |
194 | uint32_t at = ctx->at;''' |
195 | ||
196 | ||
197 | _FUNC_GET_EVENT_SIZE_BODY_END = ''' return at - ctx->at; | |
198 | }''' | |
199 | ||
200 | ||
201 | _FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_BEGIN = '''static void _serialize_stream_event_header_{sname}( | |
f66be07f | 202 | void *vctx, |
e5aa0be3 | 203 | uint32_t event_id''' |
df892ed5 | 204 | |
df892ed5 | 205 | |
e5aa0be3 | 206 | _FUNC_SERIALIZE_STREAM_EVENT_HEADER_PROTO_END = ')' |
67bd189f | 207 | |
df892ed5 | 208 | |
f66be07f PP |
209 | _FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_BEGIN = '''{{ |
210 | struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx);''' | |
df892ed5 | 211 | |
df892ed5 | 212 | |
e5aa0be3 | 213 | _FUNC_SERIALIZE_STREAM_EVENT_HEADER_BODY_END = '}' |
df892ed5 | 214 | |
6b9ba5f3 | 215 | |
e5aa0be3 | 216 | _FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_BEGIN = '''static void _serialize_stream_event_context_{sname}( |
f66be07f | 217 | void *vctx''' |
e5aa0be3 PP |
218 | |
219 | ||
220 | _FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_PROTO_END = ')' | |
221 | ||
222 | ||
f66be07f PP |
223 | _FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_BEGIN = '''{{ |
224 | struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx);''' | |
e5aa0be3 PP |
225 | |
226 | ||
227 | _FUNC_SERIALIZE_STREAM_EVENT_CONTEXT_BODY_END = '}' | |
228 | ||
229 | ||
230 | _FUNC_SERIALIZE_EVENT_PROTO_BEGIN = '''static void _serialize_event_{sname}_{evname}( | |
27bc6f1e | 231 | void *vctx''' |
e5aa0be3 PP |
232 | |
233 | ||
234 | _FUNC_SERIALIZE_EVENT_PROTO_END = ')' | |
235 | ||
236 | ||
f66be07f PP |
237 | _FUNC_SERIALIZE_EVENT_BODY_BEGIN = '''{{ |
238 | struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx);''' | |
e5aa0be3 PP |
239 | |
240 | ||
241 | _FUNC_SERIALIZE_EVENT_BODY_END = '}' | |
242 | ||
243 | ||
e5aa0be3 | 244 | _C_SRC = '''/* |
cfb53ba6 PP |
245 | * The MIT License (MIT) |
246 | * | |
4a90140d | 247 | * Copyright (c) 2015-2020 Philippe Proulx <pproulx@efficios.com> |
cfb53ba6 | 248 | * |
1378f213 PP |
249 | * Permission is hereby granted, free of charge, to any person obtaining |
250 | * a copy of this software and associated documentation files (the | |
251 | * "Software"), to deal in the Software without restriction, including | |
252 | * without limitation the rights to use, copy, modify, merge, publish, | |
253 | * distribute, sublicense, and/or sell copies of the Software, and to | |
254 | * permit persons to whom the Software is furnished to do so, subject to | |
255 | * the following conditions: | |
cfb53ba6 | 256 | * |
1378f213 PP |
257 | * The above copyright notice and this permission notice shall be |
258 | * included in all copies or substantial portions of the Software. | |
cfb53ba6 | 259 | * |
1378f213 PP |
260 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
261 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
262 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
263 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
264 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
265 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
266 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
267 | * SOFTWARE. | |
cfb53ba6 PP |
268 | * |
269 | * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - | |
270 | * | |
e5aa0be3 PP |
271 | * The following C code was generated by barectf {version} |
272 | * on {date}. | |
273 | * | |
a3ebf585 | 274 | * For more details, see <http://barectf.org>. |
e5aa0be3 | 275 | */ |
445687b2 | 276 | |
e5aa0be3 | 277 | #include <stdint.h> |
8079a626 | 278 | #include <string.h> |
e5aa0be3 PP |
279 | #include <assert.h> |
280 | ||
281 | #include "{header_filename}" | |
7db1a1f5 | 282 | #include "{bitfield_header_filename}" |
e5aa0be3 | 283 | |
1645a650 PP |
284 | #define _ALIGN(_at, _align) \\ |
285 | do {{ \\ | |
e5aa0be3 PP |
286 | (_at) = ((_at) + ((_align) - 1)) & -(_align); \\ |
287 | }} while (0) | |
8079a626 | 288 | |
f66be07f PP |
289 | #ifdef __cplusplus |
290 | # define TO_VOID_PTR(_value) static_cast<void *>(_value) | |
291 | # define FROM_VOID_PTR(_type, _value) static_cast<_type *>(_value) | |
292 | #else | |
293 | # define TO_VOID_PTR(_value) ((void *) (_value)) | |
294 | # define FROM_VOID_PTR(_type, _value) ((_type *) (_value)) | |
295 | #endif | |
296 | ||
e5aa0be3 PP |
297 | #define _BITS_TO_BYTES(_x) ((_x) >> 3) |
298 | #define _BYTES_TO_BITS(_x) ((_x) << 3) | |
445687b2 | 299 | |
1405552b PP |
300 | union f2u {{ |
301 | float f; | |
302 | uint32_t u; | |
303 | }}; | |
304 | ||
305 | union d2u {{ | |
306 | double f; | |
307 | uint64_t u; | |
308 | }}; | |
309 | ||
e5aa0be3 PP |
310 | uint32_t {prefix}packet_size(void *ctx) |
311 | {{ | |
f66be07f | 312 | return FROM_VOID_PTR(struct {prefix}ctx, ctx)->packet_size; |
e5aa0be3 | 313 | }} |
9a0782f7 | 314 | |
e5aa0be3 PP |
315 | int {prefix}packet_is_full(void *ctx) |
316 | {{ | |
f66be07f | 317 | struct {prefix}ctx *cctx = FROM_VOID_PTR(struct {prefix}ctx, ctx); |
e5aa0be3 PP |
318 | |
319 | return cctx->at == cctx->packet_size; | |
320 | }} | |
321 | ||
322 | int {prefix}packet_is_empty(void *ctx) | |
323 | {{ | |
f66be07f | 324 | struct {prefix}ctx *cctx = FROM_VOID_PTR(struct {prefix}ctx, ctx); |
e5aa0be3 PP |
325 | |
326 | return cctx->at <= cctx->off_content; | |
327 | }} | |
328 | ||
329 | uint32_t {prefix}packet_events_discarded(void *ctx) | |
330 | {{ | |
f66be07f | 331 | return FROM_VOID_PTR(struct {prefix}ctx, ctx)->events_discarded; |
e5aa0be3 PP |
332 | }} |
333 | ||
334 | uint8_t *{prefix}packet_buf(void *ctx) | |
335 | {{ | |
f66be07f | 336 | return FROM_VOID_PTR(struct {prefix}ctx, ctx)->buf; |
e5aa0be3 PP |
337 | }} |
338 | ||
339 | uint32_t {prefix}packet_buf_size(void *ctx) | |
340 | {{ | |
f66be07f PP |
341 | struct {prefix}ctx *cctx = FROM_VOID_PTR(struct {prefix}ctx, ctx); |
342 | ||
343 | return _BITS_TO_BYTES(cctx->packet_size); | |
e5aa0be3 PP |
344 | }} |
345 | ||
346 | void {prefix}packet_set_buf(void *ctx, uint8_t *buf, uint32_t buf_size) | |
347 | {{ | |
f66be07f | 348 | struct {prefix}ctx *cctx = FROM_VOID_PTR(struct {prefix}ctx, ctx); |
e5aa0be3 | 349 | |
f66be07f PP |
350 | cctx->buf = buf; |
351 | cctx->packet_size = _BYTES_TO_BITS(buf_size); | |
e5aa0be3 PP |
352 | }} |
353 | ||
354 | int {prefix}packet_is_open(void *ctx) | |
355 | {{ | |
f66be07f | 356 | return FROM_VOID_PTR(struct {prefix}ctx, ctx)->packet_is_open; |
e5aa0be3 PP |
357 | }} |
358 | ||
3cb793a1 PP |
359 | int {prefix}is_in_tracing_section(void *ctx) |
360 | {{ | |
361 | return FROM_VOID_PTR(struct {prefix}ctx, ctx)->in_tracing_section; | |
362 | }} | |
363 | ||
364 | volatile const int *{prefix}is_in_tracing_section_ptr(void *ctx) | |
365 | {{ | |
366 | return &FROM_VOID_PTR(struct {prefix}ctx, ctx)->in_tracing_section; | |
367 | }} | |
368 | ||
369 | int {prefix}is_tracing_enabled(void *ctx) | |
370 | {{ | |
371 | return FROM_VOID_PTR(struct {prefix}ctx, ctx)->is_tracing_enabled; | |
372 | }} | |
373 | ||
374 | void {prefix}enable_tracing(void *ctx, int enable) | |
375 | {{ | |
376 | FROM_VOID_PTR(struct {prefix}ctx, ctx)->is_tracing_enabled = enable; | |
377 | }} | |
378 | ||
e5aa0be3 | 379 | static |
ca275dc0 | 380 | void _write_cstring(struct {prefix}ctx *ctx, const char *src) |
e5aa0be3 PP |
381 | {{ |
382 | uint32_t sz = strlen(src) + 1; | |
383 | ||
384 | memcpy(&ctx->buf[_BITS_TO_BYTES(ctx->at)], src, sz); | |
385 | ctx->at += _BYTES_TO_BITS(sz); | |
386 | }} | |
387 | ||
e5aa0be3 | 388 | static |
f66be07f | 389 | int _reserve_event_space(void *vctx, uint32_t ev_size) |
e5aa0be3 | 390 | {{ |
f66be07f PP |
391 | struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx); |
392 | ||
e5aa0be3 PP |
393 | /* event _cannot_ fit? */ |
394 | if (ev_size > (ctx->packet_size - ctx->off_content)) {{ | |
395 | ctx->events_discarded++; | |
396 | ||
397 | return 0; | |
398 | }} | |
399 | ||
400 | /* packet is full? */ | |
401 | if ({prefix}packet_is_full(ctx)) {{ | |
402 | /* yes: is back-end full? */ | |
403 | if (ctx->cbs.is_backend_full(ctx->data)) {{ | |
404 | /* yes: discard event */ | |
405 | ctx->events_discarded++; | |
406 | ||
407 | return 0; | |
408 | }} | |
409 | ||
410 | /* back-end is not full: open new packet */ | |
27bc6f1e | 411 | ctx->use_cur_last_event_ts = 1; |
e5aa0be3 | 412 | ctx->cbs.open_packet(ctx->data); |
27bc6f1e | 413 | ctx->use_cur_last_event_ts = 0; |
e5aa0be3 PP |
414 | }} |
415 | ||
416 | /* event fits the current packet? */ | |
417 | if (ev_size > (ctx->packet_size - ctx->at)) {{ | |
418 | /* no: close packet now */ | |
27bc6f1e | 419 | ctx->use_cur_last_event_ts = 1; |
e5aa0be3 | 420 | ctx->cbs.close_packet(ctx->data); |
27bc6f1e | 421 | ctx->use_cur_last_event_ts = 0; |
e5aa0be3 PP |
422 | |
423 | /* is back-end full? */ | |
424 | if (ctx->cbs.is_backend_full(ctx->data)) {{ | |
425 | /* yes: discard event */ | |
426 | ctx->events_discarded++; | |
427 | ||
428 | return 0; | |
429 | }} | |
430 | ||
431 | /* back-end is not full: open new packet */ | |
27bc6f1e | 432 | ctx->use_cur_last_event_ts = 1; |
e5aa0be3 | 433 | ctx->cbs.open_packet(ctx->data); |
27bc6f1e | 434 | ctx->use_cur_last_event_ts = 0; |
e5aa0be3 PP |
435 | assert(ev_size <= (ctx->packet_size - ctx->at)); |
436 | }} | |
437 | ||
438 | return 1; | |
439 | }} | |
440 | ||
441 | static | |
f66be07f | 442 | void _commit_event(void *vctx) |
e5aa0be3 | 443 | {{ |
f66be07f PP |
444 | struct {prefix}ctx *ctx = FROM_VOID_PTR(struct {prefix}ctx, vctx); |
445 | ||
e5aa0be3 PP |
446 | /* is packet full? */ |
447 | if ({prefix}packet_is_full(ctx)) {{ | |
448 | /* yes: close it now */ | |
449 | ctx->cbs.close_packet(ctx->data); | |
450 | }} | |
451 | }}''' |