port: namespace align.h with BT_ prefix
[babeltrace.git] / src / ctfser / ctfser.h
CommitLineData
6f4eefbe
PP
1#ifndef BABELTRACE_CTFSER_INTERNAL_H
2#define BABELTRACE_CTFSER_INTERNAL_H
3
4/*
5 * Copyright 2010-2011 EfficiOS Inc. and Linux Foundation
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 * Copyright 2017-2019 Philippe Proulx <pproulx@efficios.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 * SOFTWARE.
26 *
27 * The Common Trace Format (CTF) Specification is available at
28 * http://www.efficios.com/ctf
29 */
30
969c1d8a 31#include <stdbool.h>
6f4eefbe
PP
32#include <stdlib.h>
33#include <stdint.h>
34#include <limits.h>
57952005 35#include "compat/mman.h"
6f4eefbe
PP
36#include <sys/types.h>
37#include <sys/stat.h>
38#include <fcntl.h>
57952005
MJ
39#include "common/align.h"
40#include "compat/endian.h"
41#include "common/common.h"
42#include "common/mmap-align.h"
71c5da58 43#include <babeltrace2/types.h>
57952005 44#include "common/assert.h"
85e7137b 45#include "common/macros.h"
57952005 46#include "compat/bitfield.h"
6f4eefbe
PP
47#include <glib.h>
48
49struct bt_ctfser {
50 /* Stream file's descriptor */
51 int fd;
52
53 /* Offset (bytes) of memory map (current packet) in the stream file */
54 off_t mmap_offset;
55
56 /* Offset (bytes) of packet's first byte in the memory map */
57 off_t mmap_base_offset;
58
59 /* Current offset (bits) within current packet */
60 uint64_t offset_in_cur_packet_bits;
61
62 /* Current packet size (bytes) */
63 uint64_t cur_packet_size_bytes;
64
65 /* Previous packet size (bytes) */
66 uint64_t prev_packet_size_bytes;
67
68 /* Current stream size (bytes) */
69 uint64_t stream_size_bytes;
70
71 /* Memory map base address */
72 struct mmap_align *base_mma;
73
74 /* Stream file's path (for debugging) */
75 GString *path;
c864e29a
PP
76
77 /* Serializer's log level */
78 int log_level;
6f4eefbe
PP
79};
80
6f4eefbe
PP
81/*
82 * Initializes a CTF serializer.
83 *
84 * This function opens the file `path` for writing.
85 */
86BT_HIDDEN
c864e29a
PP
87int bt_ctfser_init(struct bt_ctfser *ctfser, const char *path,
88 int log_level);
6f4eefbe
PP
89
90/*
91 * Finalizes a CTF serializer.
92 *
93 * This function truncates the stream file so that there's no extra
94 * padding after the last packet, and then closes the file.
95 */
96BT_HIDDEN
97int bt_ctfser_fini(struct bt_ctfser *ctfser);
98
99/*
100 * Opens a new packet.
101 *
102 * All the next writing functions are performed within this new packet.
103 */
104BT_HIDDEN
105int bt_ctfser_open_packet(struct bt_ctfser *ctfser);
106
107/*
108 * Closes the current packet, making its size `packet_size_bytes`.
109 */
110BT_HIDDEN
111void bt_ctfser_close_current_packet(struct bt_ctfser *ctfser,
112 uint64_t packet_size_bytes);
113
114BT_HIDDEN
115int _bt_ctfser_increase_cur_packet_size(struct bt_ctfser *ctfser);
116
117static inline
118uint64_t _bt_ctfser_cur_packet_size_bits(struct bt_ctfser *ctfser)
119{
120 return ctfser->cur_packet_size_bytes * 8;
121}
122
123static inline
124uint64_t _bt_ctfser_prev_packet_size_bits(struct bt_ctfser *ctfser)
125{
126 return ctfser->prev_packet_size_bytes * 8;
127}
128
129static inline
130uint64_t _bt_ctfser_offset_bytes(struct bt_ctfser *ctfser)
131{
132 return ctfser->offset_in_cur_packet_bits / 8;
133}
134
135static inline
136uint8_t *_bt_ctfser_get_addr(struct bt_ctfser *ctfser)
137{
138 /* Only makes sense to get the address after aligning on byte */
ec4a3354 139 BT_ASSERT_DBG(ctfser->offset_in_cur_packet_bits % 8 == 0);
6f4eefbe
PP
140 return ((uint8_t *) mmap_align_addr(ctfser->base_mma)) +
141 ctfser->mmap_base_offset + _bt_ctfser_offset_bytes(ctfser);
142}
143
144static inline
145bool _bt_ctfser_has_space_left(struct bt_ctfser *ctfser, uint64_t size_bits)
146{
147 bool has_space_left = true;
148
85e7137b 149 if (G_UNLIKELY((ctfser->offset_in_cur_packet_bits + size_bits >
6f4eefbe
PP
150 _bt_ctfser_cur_packet_size_bits(ctfser)))) {
151 has_space_left = false;
152 goto end;
153 }
154
85e7137b 155 if (G_UNLIKELY(size_bits > UINT64_MAX - ctfser->offset_in_cur_packet_bits)) {
6f4eefbe
PP
156 has_space_left = false;
157 goto end;
158 }
159
160end:
161 return has_space_left;
162}
163
164static inline
165void _bt_ctfser_incr_offset(struct bt_ctfser *ctfser, uint64_t size_bits)
166{
ec4a3354 167 BT_ASSERT_DBG(_bt_ctfser_has_space_left(ctfser, size_bits));
6f4eefbe
PP
168 ctfser->offset_in_cur_packet_bits += size_bits;
169}
170
171/*
172 * Aligns the current offset within the current packet to
173 * `alignment_bits` bits (power of two, > 0).
174 */
175static inline
176int bt_ctfser_align_offset_in_current_packet(struct bt_ctfser *ctfser,
177 uint64_t alignment_bits)
178{
179 int ret = 0;
180 uint64_t align_size_bits;
181
ec4a3354 182 BT_ASSERT_DBG(alignment_bits > 0);
f0bd93c1 183 align_size_bits = BT_ALIGN(ctfser->offset_in_cur_packet_bits,
6f4eefbe
PP
184 alignment_bits) - ctfser->offset_in_cur_packet_bits;
185
85e7137b 186 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, align_size_bits))) {
6f4eefbe 187 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
85e7137b 188 if (G_UNLIKELY(ret)) {
6f4eefbe
PP
189 goto end;
190 }
191 }
192
193 _bt_ctfser_incr_offset(ctfser, align_size_bits);
194
195end:
196 return ret;
197}
198
199static inline
adc10d75
PP
200int _bt_ctfser_write_byte_aligned_unsigned_int_no_align(
201 struct bt_ctfser *ctfser, uint64_t value,
202 unsigned int size_bits, int byte_order)
6f4eefbe
PP
203{
204 int ret = 0;
205
206 /* Reverse byte order? */
207 bool rbo = byte_order != BYTE_ORDER;
208
ec4a3354
PP
209 BT_ASSERT_DBG(size_bits % 8 == 0);
210 BT_ASSERT_DBG(_bt_ctfser_has_space_left(ctfser, size_bits));
6f4eefbe 211
adc10d75
PP
212 switch (size_bits) {
213 case 8:
214 {
215 uint8_t v = (uint8_t) value;
216
217 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
218 break;
219 }
220 case 16:
221 {
222 uint16_t v = (uint16_t) value;
6f4eefbe 223
adc10d75
PP
224 if (rbo) {
225 v = GUINT16_SWAP_LE_BE(v);
6f4eefbe 226 }
6f4eefbe 227
adc10d75
PP
228 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
229 break;
230 }
231 case 32:
232 {
233 uint32_t v = (uint32_t) value;
6f4eefbe 234
adc10d75
PP
235 if (rbo) {
236 v = GUINT32_SWAP_LE_BE(v);
6f4eefbe 237 }
6f4eefbe 238
adc10d75
PP
239 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
240 break;
241 }
242 case 64:
243 {
244 uint64_t v = (uint64_t) value;
6f4eefbe 245
adc10d75
PP
246 if (rbo) {
247 v = GUINT64_SWAP_LE_BE(v);
6f4eefbe 248 }
6f4eefbe 249
adc10d75
PP
250 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
251 break;
252 }
253 default:
24847fc7 254 bt_common_abort();
adc10d75 255 }
6f4eefbe 256
adc10d75
PP
257 _bt_ctfser_incr_offset(ctfser, size_bits);
258 return ret;
259}
6f4eefbe 260
adc10d75
PP
261static inline
262int _bt_ctfser_write_byte_aligned_signed_int_no_align(
263 struct bt_ctfser *ctfser, int64_t value,
264 unsigned int size_bits, int byte_order)
265{
266 int ret = 0;
6f4eefbe 267
adc10d75
PP
268 /* Reverse byte order? */
269 bool rbo = byte_order != BYTE_ORDER;
6f4eefbe 270
ec4a3354
PP
271 BT_ASSERT_DBG(size_bits % 8 == 0);
272 BT_ASSERT_DBG(_bt_ctfser_has_space_left(ctfser, size_bits));
6f4eefbe 273
adc10d75
PP
274 switch (size_bits) {
275 case 8:
276 {
277 int8_t v = (int8_t) value;
6f4eefbe 278
adc10d75
PP
279 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
280 break;
281 }
282 case 16:
283 {
284 int16_t v = (int16_t) value;
285
286 if (rbo) {
287 v = GUINT16_SWAP_LE_BE(v);
6f4eefbe 288 }
6f4eefbe 289
adc10d75
PP
290 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
291 break;
292 }
293 case 32:
294 {
295 int32_t v = (int32_t) value;
6f4eefbe 296
adc10d75
PP
297 if (rbo) {
298 v = GUINT32_SWAP_LE_BE(v);
6f4eefbe 299 }
adc10d75
PP
300
301 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
302 break;
303 }
304 case 64:
305 {
306 int64_t v = (int64_t) value;
307
308 if (rbo) {
309 v = GUINT64_SWAP_LE_BE(v);
6f4eefbe 310 }
adc10d75
PP
311
312 memcpy(_bt_ctfser_get_addr(ctfser), &v, sizeof(v));
313 break;
314 }
315 default:
24847fc7 316 bt_common_abort();
6f4eefbe
PP
317 }
318
319 _bt_ctfser_incr_offset(ctfser, size_bits);
320 return ret;
321}
322
323/*
adc10d75
PP
324 * Writes an unsigned integer known to have a size that is a multiple of
325 * 8 and an alignment that is >= 8 at the current offset within the
326 * current packet.
6f4eefbe
PP
327 */
328static inline
adc10d75
PP
329int bt_ctfser_write_byte_aligned_unsigned_int(struct bt_ctfser *ctfser,
330 uint64_t value, unsigned int alignment_bits,
331 unsigned int size_bits, int byte_order)
6f4eefbe
PP
332{
333 int ret;
334
ec4a3354 335 BT_ASSERT_DBG(alignment_bits % 8 == 0);
6f4eefbe 336 ret = bt_ctfser_align_offset_in_current_packet(ctfser, alignment_bits);
85e7137b 337 if (G_UNLIKELY(ret)) {
6f4eefbe
PP
338 goto end;
339 }
340
85e7137b 341 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, size_bits))) {
6f4eefbe 342 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
85e7137b 343 if (G_UNLIKELY(ret)) {
6f4eefbe
PP
344 goto end;
345 }
346 }
347
adc10d75
PP
348 ret = _bt_ctfser_write_byte_aligned_unsigned_int_no_align(ctfser, value,
349 size_bits, byte_order);
85e7137b 350 if (G_UNLIKELY(ret)) {
6f4eefbe
PP
351 goto end;
352 }
353
354end:
355 return ret;
356}
357
358/*
adc10d75
PP
359 * Writes a signed integer known to have a size that is a multiple of 8
360 * and an alignment that is >= 8 at the current offset within the
361 * current packet.
6f4eefbe
PP
362 */
363static inline
adc10d75
PP
364int bt_ctfser_write_byte_aligned_signed_int(struct bt_ctfser *ctfser,
365 int64_t value, unsigned int alignment_bits,
366 unsigned int size_bits, int byte_order)
367{
368 int ret;
369
ec4a3354 370 BT_ASSERT_DBG(alignment_bits % 8 == 0);
adc10d75 371 ret = bt_ctfser_align_offset_in_current_packet(ctfser, alignment_bits);
85e7137b 372 if (G_UNLIKELY(ret)) {
adc10d75
PP
373 goto end;
374 }
375
85e7137b 376 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, size_bits))) {
adc10d75 377 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
85e7137b 378 if (G_UNLIKELY(ret)) {
adc10d75
PP
379 goto end;
380 }
381 }
382
383 ret = _bt_ctfser_write_byte_aligned_signed_int_no_align(ctfser, value,
384 size_bits, byte_order);
85e7137b 385 if (G_UNLIKELY(ret)) {
adc10d75
PP
386 goto end;
387 }
388
389end:
390 return ret;
391}
392
393/*
394 * Writes an unsigned integer at the current offset within the current
395 * packet.
396 */
397static inline
398int bt_ctfser_write_unsigned_int(struct bt_ctfser *ctfser, uint64_t value,
399 unsigned int alignment_bits, unsigned int size_bits,
6f4eefbe
PP
400 int byte_order)
401{
402 int ret = 0;
403
404 ret = bt_ctfser_align_offset_in_current_packet(ctfser, alignment_bits);
85e7137b 405 if (G_UNLIKELY(ret)) {
6f4eefbe
PP
406 goto end;
407 }
408
85e7137b 409 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, size_bits))) {
6f4eefbe 410 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
85e7137b 411 if (G_UNLIKELY(ret)) {
6f4eefbe
PP
412 goto end;
413 }
414 }
415
416 if (alignment_bits % 8 == 0 && size_bits % 8 == 0) {
adc10d75
PP
417 ret = _bt_ctfser_write_byte_aligned_unsigned_int_no_align(
418 ctfser, value, size_bits, byte_order);
6f4eefbe
PP
419 goto end;
420 }
421
adc10d75
PP
422 if (byte_order == LITTLE_ENDIAN) {
423 bt_bitfield_write_le(mmap_align_addr(ctfser->base_mma) +
424 ctfser->mmap_base_offset, uint8_t,
425 ctfser->offset_in_cur_packet_bits, size_bits, value);
6f4eefbe 426 } else {
adc10d75
PP
427 bt_bitfield_write_be(mmap_align_addr(ctfser->base_mma) +
428 ctfser->mmap_base_offset, uint8_t,
429 ctfser->offset_in_cur_packet_bits, size_bits, value);
430 }
431
432 _bt_ctfser_incr_offset(ctfser, size_bits);
433
434end:
435 return ret;
436}
437
438/*
439 * Writes a signed integer at the current offset within the current
440 * packet.
441 */
442static inline
443int bt_ctfser_write_signed_int(struct bt_ctfser *ctfser, int64_t value,
444 unsigned int alignment_bits, unsigned int size_bits,
445 int byte_order)
446{
447 int ret = 0;
448
449 ret = bt_ctfser_align_offset_in_current_packet(ctfser, alignment_bits);
85e7137b 450 if (G_UNLIKELY(ret)) {
adc10d75
PP
451 goto end;
452 }
453
85e7137b 454 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, size_bits))) {
adc10d75 455 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
85e7137b 456 if (G_UNLIKELY(ret)) {
adc10d75 457 goto end;
6f4eefbe
PP
458 }
459 }
460
adc10d75
PP
461 if (alignment_bits % 8 == 0 && size_bits % 8 == 0) {
462 ret = _bt_ctfser_write_byte_aligned_signed_int_no_align(
463 ctfser, value, size_bits, byte_order);
464 goto end;
465 }
466
467 if (byte_order == LITTLE_ENDIAN) {
468 bt_bitfield_write_le(mmap_align_addr(ctfser->base_mma) +
469 ctfser->mmap_base_offset, uint8_t,
470 ctfser->offset_in_cur_packet_bits, size_bits, value);
471 } else {
472 bt_bitfield_write_be(mmap_align_addr(ctfser->base_mma) +
473 ctfser->mmap_base_offset, uint8_t,
474 ctfser->offset_in_cur_packet_bits, size_bits, value);
475 }
476
6f4eefbe
PP
477 _bt_ctfser_incr_offset(ctfser, size_bits);
478
479end:
480 return ret;
481}
482
483/*
484 * Writes a 32-bit floating point number at the current offset within
485 * the current packet.
486 */
487static inline
488int bt_ctfser_write_float32(struct bt_ctfser *ctfser, double value,
489 unsigned int alignment_bits, int byte_order)
490{
6f4eefbe
PP
491 union u32f {
492 uint32_t u;
493 float f;
494 } u32f;
495
496 u32f.f = (float) value;
adc10d75
PP
497 return bt_ctfser_write_unsigned_int(ctfser, (uint64_t) u32f.u,
498 alignment_bits, 32, byte_order);
6f4eefbe
PP
499}
500
501/*
502 * Writes a 64-bit floating point number at the current offset within
503 * the current packet.
504 */
505static inline
506int bt_ctfser_write_float64(struct bt_ctfser *ctfser, double value,
507 unsigned int alignment_bits, int byte_order)
508{
6f4eefbe
PP
509 union u64f {
510 uint64_t u;
e19f607d 511 double d;
6f4eefbe
PP
512 } u64f;
513
e19f607d 514 u64f.d = value;
adc10d75
PP
515 return bt_ctfser_write_unsigned_int(ctfser, u64f.u, alignment_bits,
516 64, byte_order);
6f4eefbe
PP
517}
518
519/*
520 * Writes a C string, including the terminating null character, at the
521 * current offset within the current packet.
522 */
523static inline
524int bt_ctfser_write_string(struct bt_ctfser *ctfser, const char *value)
525{
526 int ret = 0;
527 const char *at = value;
528
529 ret = bt_ctfser_align_offset_in_current_packet(ctfser, 8);
85e7137b 530 if (G_UNLIKELY(ret)) {
6f4eefbe
PP
531 goto end;
532 }
533
534 while (true) {
85e7137b 535 if (G_UNLIKELY(!_bt_ctfser_has_space_left(ctfser, 8))) {
6f4eefbe 536 ret = _bt_ctfser_increase_cur_packet_size(ctfser);
85e7137b 537 if (G_UNLIKELY(ret)) {
6f4eefbe
PP
538 goto end;
539 }
540 }
541
542 memcpy(_bt_ctfser_get_addr(ctfser), at, sizeof(*at));
543 _bt_ctfser_incr_offset(ctfser, 8);
544
85e7137b 545 if (G_UNLIKELY(*at == '\0')) {
6f4eefbe
PP
546 break;
547 }
548
549 at++;
550 }
551
552end:
553 return ret;
554}
555
556/*
557 * Returns the current offset within the current packet (bits).
558 */
559static inline
560uint64_t bt_ctfser_get_offset_in_current_packet_bits(struct bt_ctfser *ctfser)
561{
562 return ctfser->offset_in_cur_packet_bits;
563}
564
565/*
566 * Sets the current offset within the current packet (bits).
567 */
568static inline
569void bt_ctfser_set_offset_in_current_packet_bits(struct bt_ctfser *ctfser,
570 uint64_t offset_bits)
571{
ec4a3354 572 BT_ASSERT_DBG(offset_bits <= _bt_ctfser_cur_packet_size_bits(ctfser));
6f4eefbe
PP
573 ctfser->offset_in_cur_packet_bits = offset_bits;
574}
575
46bdd3e0
PP
576static inline
577const char *bt_ctfser_get_file_path(struct bt_ctfser *ctfser)
578{
579 return ctfser->path->str;
580}
581
6f4eefbe 582#endif /* BABELTRACE_CTFSER_INTERNAL_H */
This page took 0.082244 seconds and 4 git commands to generate.