templates: commonize the licence header
[deliverable/barectf.git] / barectf / templates / c / barectf.c.j2
CommitLineData
fdbf8740
PP
1{#
2 # The MIT License (MIT)
3 #
4 # Copyright (c) 2020 Philippe Proulx <pproulx@efficios.com>
5 #
6 # Permission is hereby granted, free of charge, to any person obtaining
7 # a copy of this software and associated documentation files (the
8 # "Software"), to deal in the Software without restriction, including
9 # without limitation the rights to use, copy, modify, merge, publish,
10 # distribute, sublicense, and/or sell copies of the Software, and to
11 # permit persons to whom the Software is furnished to do so, subject to
12 # the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be
15 # included in all copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 #}
d6483c83
PP
25{% import 'common.j2' as common %}
26{% import 'c/common.j2' as c_common %}
27{% import 'c/barectf.c-macros.j2' as macros %}
28{% set prefix = common.prefix %}
29{% set ucprefix = common.ucprefix %}
30{% set ctx_struct_name = c_common.ctx_struct_name %}
31{% set cg_opts = cfg.options.code_generation_options %}
e72875eb
PP
32{% include 'licence-header.j2' %}
33
d6483c83
PP
34
35#include <stdint.h>
36#include <string.h>
37#include <assert.h>
38
39#include "{{ header_file_name }}"
40#include "{{ bitfield_header_file_name }}"
41
42#define _ALIGN(_at, _align) \
43 do { \
44 (_at) = ((_at) + ((_align) - 1)) & -(_align); \
45 } while (0)
46
47#ifdef __cplusplus
48# define _TO_VOID_PTR(_value) static_cast<void *>(_value)
49# define _FROM_VOID_PTR(_type, _value) static_cast<_type *>(_value)
50#else
51# define _TO_VOID_PTR(_value) ((void *) (_value))
52# define _FROM_VOID_PTR(_type, _value) ((_type *) (_value))
53#endif
54
55#define _BITS_TO_BYTES(_x) ((_x) >> 3)
56#define _BYTES_TO_BITS(_x) ((_x) << 3)
57
58union _f2u {
59 float f;
60 uint32_t u;
61};
62
63union _d2u {
64 double f;
65 uint64_t u;
66};
67
68uint32_t {{ prefix }}packet_size(void *ctx)
69{
70 return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, ctx)->packet_size;
71}
72
73int {{ prefix }}packet_is_full(void *vctx)
74{
75 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
76
77 return ctx->at == ctx->packet_size;
78}
79
80int {{ prefix }}packet_is_empty(void *vctx)
81{
82 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
83
84 return ctx->at <= ctx->off_content;
85}
86
87uint32_t {{ prefix }}packet_events_discarded(void *vctx)
88{
89 return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->events_discarded;
90}
91
92uint8_t *{{ prefix }}packet_buf(void *vctx)
93{
94 return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->buf;
95}
96
97uint32_t {{ prefix }}packet_buf_size(void *vctx)
98{
99 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
100
101 return _BITS_TO_BYTES(ctx->packet_size);
102}
103
104void {{ prefix }}packet_set_buf(void *vctx, uint8_t *buf, uint32_t buf_size)
105{
106 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
107
108 ctx->buf = buf;
109 ctx->packet_size = _BYTES_TO_BITS(buf_size);
110}
111
112int {{ prefix }}packet_is_open(void *vctx)
113{
114 return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->packet_is_open;
115}
116
117int {{ prefix }}is_in_tracing_section(void *vctx)
118{
119 return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->in_tracing_section;
120}
121
122volatile const int *{{ prefix }}is_in_tracing_section_ptr(void *vctx)
123{
124 return &_FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->in_tracing_section;
125}
126
127int {{ prefix }}is_tracing_enabled(void *vctx)
128{
129 return _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->is_tracing_enabled;
130}
131
132void {{ prefix }}enable_tracing(void *vctx, int enable)
133{
134 _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx)->is_tracing_enabled = enable;
135}
136
137static
138void _write_c_str(struct {{ ctx_struct_name }} *ctx, const char *src)
139{
140 uint32_t sz = strlen(src) + 1;
141
142 memcpy(&ctx->buf[_BITS_TO_BYTES(ctx->at)], src, sz);
143 ctx->at += _BYTES_TO_BITS(sz);
144}
145
146static
147int _reserve_ev_space(void *vctx, uint32_t ev_size)
148{
149 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
150
151 /* event _cannot_ fit? */
152 if (ev_size > (ctx->packet_size - ctx->off_content)) {
153 ctx->events_discarded++;
154 return 0;
155 }
156
157 /* packet is full? */
158 if ({{ prefix }}packet_is_full(ctx)) {
159 /* yes: is back-end full? */
160 if (ctx->cbs.is_backend_full(ctx->data)) {
161 /* yes: discard event */
162 ctx->events_discarded++;
163 return 0;
164 }
165
166 /* back-end is not full: open new packet */
167 ctx->use_cur_last_event_ts = 1;
168 ctx->cbs.open_packet(ctx->data);
169 ctx->use_cur_last_event_ts = 0;
170 }
171
172 /* event fits the current packet? */
173 if (ev_size > (ctx->packet_size - ctx->at)) {
174 /* no: close packet now */
175 ctx->use_cur_last_event_ts = 1;
176 ctx->cbs.close_packet(ctx->data);
177 ctx->use_cur_last_event_ts = 0;
178
179 /* is back-end full? */
180 if (ctx->cbs.is_backend_full(ctx->data)) {
181 /* yes: discard event */
182 ctx->events_discarded++;
183 return 0;
184 }
185
186 /* back-end is not full: open new packet */
187 ctx->use_cur_last_event_ts = 1;
188 ctx->cbs.open_packet(ctx->data);
189 ctx->use_cur_last_event_ts = 0;
190 assert(ev_size <= (ctx->packet_size - ctx->at));
191 }
192
193 return 1;
194}
195
196static
197void _commit_ev(void *vctx)
198{
199 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
200
201 /* is packet full? */
202 if ({{ prefix }}packet_is_full(ctx)) {
203 /* yes: close it now */
204 ctx->cbs.close_packet(ctx->data);
205 }
206}
207
208{% include 'c/ctx-init-func-proto.j2' %}
209
210{
211 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
212 ctx->cbs = cbs;
213 ctx->data = data;
214 ctx->buf = buf;
215 ctx->packet_size = _BYTES_TO_BITS(buf_size);
216 ctx->at = 0;
217 ctx->events_discarded = 0;
218 ctx->packet_is_open = 0;
219 ctx->in_tracing_section = 0;
220 ctx->is_tracing_enabled = 1;
221 ctx->use_cur_last_event_ts = 0;
222}
223
224{% for stream_type in cfg.trace.type.stream_types | sort %}
225 {% set def_clk_type = stream_type.default_clock_type %}
226 {% set sctx_name %}{{ prefix }}{{ stream_type.name }}{% endset %}
227 {% set this_stream_ops = stream_ops[stream_type] %}
228 {% include 'c/open-func-proto.j2' %}
229
230{
231 {{ macros.open_close_func_preamble(stream_type) | indent_tab }}
232
233 /*
234 * This function is either called by a tracing function, or
235 * directly by the platform.
236 *
237 * If it's called by a tracing function, then
238 * `ctx->in_tracing_section` is 1, so it's safe to open
239 * the packet here (alter the packet), even if tracing was
240 * disabled in the meantime because we're already in a tracing
241 * section (which finishes at the end of the tracing function
242 * call).
243 *
244 * If it's called directly by the platform, then if tracing is
245 * disabled, we don't want to alter the packet, and return
246 * immediately.
247 */
248 if (!ctx->is_tracing_enabled && !saved_in_tracing_section) {
249 ctx->in_tracing_section = 0;
250 return;
251 }
252
253 /* we can alter the packet */
254 ctx->in_tracing_section = 1;
255
256 /* do not open a packet that is already open */
257 if (ctx->packet_is_open) {
258 ctx->in_tracing_section = saved_in_tracing_section;
259 return;
260 }
261
262 ctx->at = 0;
263 {% set pkt_header_ops = this_stream_ops.pkt_header_ops %}
264 {% if pkt_header_ops %}
265
266 /* serialize packet header */
267 {
268 {% for op in pkt_header_ops %}
269 {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
270
271 {% endfor %}
272 }
273 {% endif %}
274
275 /* serialize packet context */
276 {
277 {% for op in this_stream_ops.pkt_ctx_ops %}
278 {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
279
280 {% endfor %}
281 }
282
283 /* save content beginning's offset */
284 ctx->off_content = ctx->at;
285
286 /* mark current packet as open */
287 ctx->packet_is_open = 1;
288
289 /* not tracing anymore */
290 ctx->in_tracing_section = saved_in_tracing_section;
291}
292
293 {% include 'c/close-func-proto.j2' %}
294
295{
296 {{ macros.open_close_func_preamble(stream_type) | indent_tab }}
297
298 /*
299 * This function is either called by a tracing function, or
300 * directly by the platform.
301 *
302 * If it's called by a tracing function, then
303 * `ctx->in_tracing_section` is 1, so it's safe to close
304 * the packet here (alter the packet), even if tracing was
305 * disabled in the meantime, because we're already in a tracing
306 * section (which finishes at the end of the tracing function
307 * call).
308 *
309 * If it's called directly by the platform, then if tracing is
310 * disabled, we don't want to alter the packet, and return
311 * immediately.
312 */
313 if (!ctx->is_tracing_enabled && !saved_in_tracing_section) {
314 ctx->in_tracing_section = 0;
315 return;
316 }
317
318 /* we can alter the packet */
319 ctx->in_tracing_section = 1;
320
321 /* do not close a packet that is not open */
322 if (!ctx->packet_is_open) {
323 ctx->in_tracing_section = saved_in_tracing_section;
324 return;
325 }
326
327 /* save content size */
328 ctx->content_size = ctx->at;
329 {% if 'timestamp_end' in stream_type._pkt_ctx_ft.members %}
330 {% set op = stream_op_pkt_ctx_op(stream_type, 'timestamp_end') %}
331
332 /* go back to `timestamp_end` field offset */
333 ctx->at = sctx->off_{{ c_common.op_src(op) }};
334
335 {% set src = 'ts' %}
336 {% filter indent_tab(indent_first=True) %}
337 {% include 'c/serialize-write-saved-int-statements.j2' %}
338
339 {% endfilter %}
340 {% endif %}
341 {% if 'content_size' in stream_type._pkt_ctx_ft.members %}
342 {% set op = stream_op_pkt_ctx_op(stream_type, 'content_size') %}
343
344 /* go back to `content_size` field offset */
345 ctx->at = sctx->off_{{ c_common.op_src(op) }};
346
347 {% set src = 'ctx->content_size' %}
348 {% filter indent_tab(indent_first=True) %}
349 {% include 'c/serialize-write-saved-int-statements.j2' %}
350
351 {% endfilter %}
352 {% endif %}
353 {% if 'events_discarded' in stream_type._pkt_ctx_ft.members %}
354 {% set op = stream_op_pkt_ctx_op(stream_type, 'events_discarded') %}
355
356 /* go back to `events_discarded` field offset */
357 ctx->at = sctx->off_{{ c_common.op_src(op) }};
358
359 {% set src = 'ctx->events_discarded' %}
360 {% filter indent_tab(indent_first=True) %}
361 {% include 'c/serialize-write-saved-int-statements.j2' %}
362
363 {% endfilter %}
364 {% endif %}
365
366 /* go back to end of packet */
367 ctx->at = ctx->packet_size;
368
369 /* mark packet as closed */
370 ctx->packet_is_open = 0;
371
372 /* not tracing anymore */
373 ctx->in_tracing_section = saved_in_tracing_section;
374}
375 {% if stream_type._ev_header_ft %}
376
377static void _serialize_ev_header_{{ stream_type.name }}(void *vctx,
378 uint32_t ev_type_id)
379{
380 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
381 {% if def_clk_type %}
382 struct {{ sctx_name }}_ctx *sctx = _FROM_VOID_PTR(struct {{ sctx_name }}_ctx, vctx);
383 const {{ cg_opts.clock_type_c_types[def_clk_type] }} ts = sctx->cur_last_event_ts;
384 {% endif %}
385
386 /* serialize event header */
387 {
388 {% for op in this_stream_ops.ev_header_ops %}
389 {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
390
391 {% endfor %}
392 }
393}
394 {% endif %}
395 {% if stream_type.event_common_context_field_type %}
396
397static void _serialize_ev_common_ctx_{{ stream_type.name }}(void *vctx{{ stream_type | serialize_ev_common_ctx_func_params_str }})
398{
399 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
400
401 /* serialize event common context */
402 {
403 {% for op in this_stream_ops.ev_common_ctx_ops %}
404 {{ op.serialize_str(stream_type=stream_type) | indent_tab(2) }}
405
406 {% endfor %}
407 }
408}
409 {% endif %}
410 {# internal serialization functions #}
411 {% for ev_type in stream_type.event_types | sort %}
412
413static void _serialize_ev_{{ stream_type.name }}_{{ ev_type.name }}(void *vctx{{ (stream_type, ev_type) | trace_func_params_str }})
414{
415 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
416 {% if stream_type._ev_header_ft %}
417
418 /* serialize header */
419 _serialize_ev_header_{{ stream_type.name }}(ctx, {{ ev_type.id }});
420 {% endif %}
421 {% if stream_type.event_common_context_field_type %}
422
423 /* serialize common context */
424 {% set params = macros.ft_call_params(root_ft_prefixes.SEC, stream_type.event_common_context_field_type) %}
425 _serialize_ev_common_ctx_{{ stream_type.name }}(ctx{{ params }});
426 {% endif %}
427 {% set this_ev_ops = this_stream_ops.ev_ops[ev_type] %}
428 {% if this_ev_ops.spec_ctx_ops %}
429
430 /* serialize specific context */
431 {
432 {% for op in this_ev_ops.spec_ctx_ops %}
433 {{ op.serialize_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
434
435 {% endfor %}
436 }
437 {% endif %}
438 {% if this_ev_ops.payload_ops %}
439
440 /* serialize payload */
441 {
442 {% for op in this_ev_ops.payload_ops %}
443 {{ op.serialize_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
444
445 {% endfor %}
446 }
447 {% endif %}
448}
449 {% endfor %}
450 {# internal size functions #}
451 {% for ev_type in stream_type.event_types | sort %}
452 {% set this_ev_ops = this_stream_ops.ev_ops[ev_type] %}
453
454static uint32_t _ev_size_{{ stream_type.name }}_{{ ev_type.name }}(void *vctx{{ (stream_type, ev_type) | trace_func_params_str }})
455{
456 struct {{ ctx_struct_name }} *ctx = _FROM_VOID_PTR(struct {{ ctx_struct_name }}, vctx);
457 uint32_t at = ctx->at;
458 {% if this_stream_ops.ev_header_ops %}
459
460 /* add header size */
461 {
462 {% for op in this_stream_ops.ev_header_ops %}
463 {{ op.size_str(stream_type=stream_type) | indent_tab(2) }}
464
465 {% endfor %}
466 }
467 {% endif %}
468 {% if this_stream_ops.ev_common_ctx_ops %}
469
470 /* add common context size */
471 {
472 {% for op in this_stream_ops.ev_common_ctx_ops %}
473 {{ op.size_str(stream_type=stream_type) | indent_tab(2) }}
474
475 {% endfor %}
476 }
477 {% endif %}
478 {% if this_ev_ops.spec_ctx_ops %}
479
480 /* add specific context size */
481 {
482 {% for op in this_ev_ops.spec_ctx_ops %}
483 {{ op.size_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
484
485 {% endfor %}
486 }
487 {% endif %}
488 {% if this_ev_ops.payload_ops %}
489
490 /* add payload size */
491 {
492 {% for op in this_ev_ops.payload_ops %}
493 {{ op.size_str(stream_type=stream_type, ev_type=ev_type) | indent_tab(2) }}
494
495 {% endfor %}
496 }
497 {% endif %}
498
499 return at - ctx->at;
500}
501 {% endfor %}
502 {# public tracing functions #}
503 {% for ev_type in stream_type.event_types | sort %}
504
505 {% include 'c/trace-func-proto.j2' %}
506
507{
508 struct {{ ctx_struct_name }} *ctx = &sctx->parent;
509 uint32_t ev_size;
510
511 {% if def_clk_type %}
512 /* save time */
513 sctx->cur_last_event_ts = ctx->cbs.{{ def_clk_type.name }}_clock_get_value(ctx->data);
514
515 {% endif %}
516
517 if (!ctx->is_tracing_enabled) {
518 return;
519 }
520
521 /* we can alter the packet */
522 ctx->in_tracing_section = 1;
523
524 /* compute event size */
525 {% set ev_common_ctx_params = macros.ft_call_params(root_ft_prefixes.SEC, stream_type.event_common_context_field_type) %}
526 {% set spec_ctx_params = macros.ft_call_params(root_ft_prefixes.EC, ev_type.specific_context_field_type) %}
527 {% set payload_params = macros.ft_call_params(root_ft_prefixes.EP, ev_type.payload_field_type) %}
528 {% set params %}{{ ev_common_ctx_params }}{{ spec_ctx_params }}{{ payload_params }}{% endset %}
529 ev_size = _ev_size_{{ stream_type.name }}_{{ ev_type.name }}(_TO_VOID_PTR(ctx){{ params }});
530
531 /* do we have enough space to serialize? */
532 if (!_reserve_ev_space(_TO_VOID_PTR(ctx), ev_size)) {
533 /* no: forget this */
534 ctx->in_tracing_section = 0;
535 return;
536 }
537
538 /* serialize event */
539 _serialize_ev_{{ stream_type.name }}_{{ ev_type.name }}(_TO_VOID_PTR(ctx){{ params }});
540
541 /* commit event */
542 _commit_ev(_TO_VOID_PTR(ctx));
543
544 /* not tracing anymore */
545 ctx->in_tracing_section = 0;
546}
547 {% endfor %}
548{% endfor %}
This page took 0.049412 seconds and 4 git commands to generate.