4 * Babeltrace CTF IR - Stream packet
6 * Copyright 2016 Philippe Proulx <pproulx@efficios.com>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 #define BT_LOG_TAG "PACKET"
28 #include <babeltrace/lib-logging-internal.h>
30 #include <babeltrace/assert-pre-internal.h>
31 #include <babeltrace/ctf-ir/fields-internal.h>
32 #include <babeltrace/ctf-ir/packet.h>
33 #include <babeltrace/ctf-ir/packet-internal.h>
34 #include <babeltrace/ctf-ir/field-wrapper-internal.h>
35 #include <babeltrace/ctf-ir/trace.h>
36 #include <babeltrace/ctf-ir/stream-class-internal.h>
37 #include <babeltrace/ctf-ir/stream-class.h>
38 #include <babeltrace/ctf-ir/stream.h>
39 #include <babeltrace/ctf-ir/stream-internal.h>
40 #include <babeltrace/ctf-ir/trace-internal.h>
41 #include <babeltrace/object-internal.h>
42 #include <babeltrace/ref.h>
43 #include <babeltrace/assert-internal.h>
46 struct bt_stream
*bt_packet_borrow_stream(struct bt_packet
*packet
)
48 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
49 return packet
->stream
;
52 struct bt_field
*bt_packet_borrow_header(struct bt_packet
*packet
)
54 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
55 return packet
->header
? (void *) packet
->header
->field
: NULL
;
58 struct bt_field
*bt_packet_borrow_context(struct bt_packet
*packet
)
60 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
61 return packet
->context
? (void *) packet
->context
->field
: NULL
;
65 void _bt_packet_set_is_frozen(struct bt_packet
*packet
, bool is_frozen
)
71 BT_LOGD("Setting packet's frozen state: addr=%p, frozen=%d",
75 BT_LOGD("Setting packet's header field's frozen state: "
76 "frozen=%d", is_frozen
);
77 bt_field_set_is_frozen_recursive((void *) packet
->header
->field
,
81 if (packet
->context
) {
82 BT_LOGD("Setting packet's context field's frozen state: "
83 "frozen=%d", is_frozen
);
84 bt_field_set_is_frozen_recursive((void *) packet
->context
->field
,
88 packet
->frozen
= is_frozen
;
92 void bt_packet_reset_avail(struct bt_packet
*packet
)
95 packet
->prev_packet_info
.avail
=
96 BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NOT_AVAILABLE
;
97 packet
->prev_packet_info
.discarded_event_counter
.avail
=
98 BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE
;
99 packet
->prev_packet_info
.seq_num
.avail
=
100 BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE
;
101 packet
->prev_packet_info
.default_end_cv
.avail
=
102 BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE
;
105 packet
->discarded_event_counter
.avail
=
106 BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE
;
107 packet
->seq_num
.avail
=
108 BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE
;
111 packet
->discarded_event_count
.avail
=
112 BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE
;
113 packet
->discarded_packet_count
.avail
=
114 BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE
;
118 void bt_packet_reset(struct bt_packet
*packet
)
121 bt_packet_set_is_frozen(packet
, false);
123 if (packet
->header
) {
124 bt_field_set_is_frozen_recursive(
125 (void *) packet
->header
->field
, false);
126 bt_field_reset_recursive((void *) packet
->header
->field
);
129 if (packet
->context
) {
130 bt_field_set_is_frozen_recursive(
131 (void *) packet
->context
->field
, false);
132 bt_field_reset_recursive((void *) packet
->context
->field
);
135 bt_clock_value_set_reset(&packet
->begin_cv_set
);
136 bt_clock_value_set_reset(&packet
->end_cv_set
);
137 bt_packet_reset_avail(packet
);
138 bt_packet_invalidate_properties(packet
);
140 if (packet
->prev_packet_info
.default_end_cv
.cv
) {
141 bt_clock_value_recycle(packet
->prev_packet_info
.default_end_cv
.cv
);
142 packet
->prev_packet_info
.default_end_cv
.cv
= NULL
;
147 void bt_packet_header_field_recycle(struct bt_field_wrapper
*header_field
,
148 struct bt_trace
*trace
)
150 BT_ASSERT(header_field
);
151 BT_LIB_LOGD("Recycling packet header field: "
152 "addr=%p, %![trace-]+t, %![field-]+f", header_field
,
153 trace
, header_field
->field
);
154 bt_object_pool_recycle_object(&trace
->packet_header_field_pool
,
159 void bt_packet_context_field_recycle(struct bt_field_wrapper
*context_field
,
160 struct bt_stream_class
*stream_class
)
162 BT_ASSERT(context_field
);
163 BT_LIB_LOGD("Recycling packet context field: "
164 "addr=%p, %![sc-]+S, %![field-]+f", context_field
,
165 stream_class
, context_field
->field
);
166 bt_object_pool_recycle_object(&stream_class
->packet_context_field_pool
,
171 void bt_packet_recycle(struct bt_packet
*packet
)
173 struct bt_stream
*stream
;
176 BT_LIB_LOGD("Recycling packet: %!+a", packet
);
179 * Those are the important ordered steps:
181 * 1. Reset the packet object (put any permanent reference it
182 * has, unfreeze it and its fields in developer mode, etc.),
183 * but do NOT put its stream's reference. This stream
184 * contains the pool to which we're about to recycle this
185 * packet object, so we must guarantee its existence thanks
186 * to this existing reference.
188 * 2. Move the stream reference to our `stream`
189 * variable so that we can set the packet's stream member
190 * to NULL before recycling it. We CANNOT do this after
191 * we put the stream reference because this bt_put()
192 * could destroy the stream, also destroying its
193 * packet pool, thus also destroying our packet object (this
194 * would result in an invalid write access).
196 * 3. Recycle the packet object.
198 * 4. Put our stream reference.
200 bt_packet_reset(packet
);
201 stream
= packet
->stream
;
203 packet
->stream
= NULL
;
204 bt_object_pool_recycle_object(&stream
->packet_pool
, packet
);
205 bt_object_put_no_null_check(&stream
->common
.base
);
209 void bt_packet_destroy(struct bt_packet
*packet
)
211 BT_LOGD("Destroying packet: addr=%p", packet
);
212 BT_LOGD_STR("Destroying packet's header field.");
214 if (packet
->header
) {
215 if (packet
->stream
) {
216 BT_LOGD_STR("Recycling packet's header field.");
217 bt_packet_header_field_recycle(packet
->header
,
218 bt_stream_class_borrow_trace(
219 bt_stream_borrow_class(packet
->stream
)));
221 bt_field_wrapper_destroy(packet
->header
);
225 if (packet
->context
) {
226 if (packet
->stream
) {
227 BT_LOGD_STR("Recycling packet's context field.");
228 bt_packet_context_field_recycle(packet
->context
,
229 bt_stream_borrow_class(packet
->stream
));
231 bt_field_wrapper_destroy(packet
->context
);
235 bt_clock_value_set_finalize(&packet
->begin_cv_set
);
236 bt_clock_value_set_finalize(&packet
->end_cv_set
);
237 BT_LOGD_STR("Putting packet's stream.");
238 bt_put(packet
->stream
);
243 struct bt_packet
*bt_packet_new(struct bt_stream
*stream
)
245 struct bt_packet
*packet
= NULL
;
246 struct bt_stream_class
*stream_class
= NULL
;
247 struct bt_trace
*trace
= NULL
;
250 BT_LOGD("Creating packet object: stream-addr=%p, "
251 "stream-name=\"%s\", stream-class-addr=%p, "
252 "stream-class-name=\"%s\", stream-class-id=%" PRId64
,
253 stream
, bt_stream_get_name(stream
),
254 stream
->common
.stream_class
,
255 bt_stream_class_common_get_name(stream
->common
.stream_class
),
256 bt_stream_class_common_get_id(stream
->common
.stream_class
));
257 stream_class
= bt_stream_borrow_class(stream
);
258 BT_ASSERT(stream_class
);
259 trace
= bt_stream_class_borrow_trace(stream_class
);
261 packet
= g_new0(struct bt_packet
, 1);
263 BT_LOGE_STR("Failed to allocate one packet object.");
267 bt_object_init_shared(&packet
->base
,
268 (bt_object_release_func
) bt_packet_recycle
);
269 packet
->stream
= bt_get(stream
);
271 if (trace
->common
.packet_header_field_type
) {
272 BT_LOGD("Creating initial packet header field: ft-addr=%p",
273 trace
->common
.packet_header_field_type
);
274 packet
->header
= bt_field_wrapper_create(
275 &trace
->packet_header_field_pool
,
276 (void *) trace
->common
.packet_header_field_type
);
277 if (!packet
->header
) {
278 BT_LOGE("Cannot create packet header field wrapper.");
284 if (stream
->common
.stream_class
->packet_context_field_type
) {
285 BT_LOGD("Creating initial packet context field: ft-addr=%p",
286 stream
->common
.stream_class
->packet_context_field_type
);
287 packet
->context
= bt_field_wrapper_create(
288 &stream_class
->packet_context_field_pool
,
289 (void *) stream
->common
.stream_class
->packet_context_field_type
);
290 if (!packet
->context
) {
291 BT_LOGE("Cannot create packet context field wrapper.");
297 if (bt_clock_value_set_initialize(&packet
->begin_cv_set
)) {
302 if (bt_clock_value_set_initialize(&packet
->end_cv_set
)) {
307 bt_packet_reset_avail(packet
);
308 BT_LOGD("Created packet object: addr=%p", packet
);
315 uint64_t get_uint_field_value(struct bt_field
*parent_field
, const char *name
)
317 uint64_t val
= UINT64_C(-1);
318 struct bt_field
*field
= bt_field_structure_borrow_field_by_name(
326 BT_ASSERT(bt_field_is_integer(field
));
327 BT_ASSERT(!bt_field_type_integer_is_signed(
328 bt_field_borrow_type(field
)));
329 ret
= bt_field_integer_unsigned_get_value(field
, &val
);
337 void set_packet_prop_uint64(struct bt_packet_prop_uint64
*prop
, uint64_t val
)
341 prop
->avail
= BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
;
345 int set_packet_default_clock_value(struct bt_field
*pkt_ctx_field
,
346 const char *field_name
, struct bt_clock_value_set
*cv_set
)
349 uint64_t val
= UINT64_C(-1);
350 struct bt_field
*field
= bt_field_structure_borrow_field_by_name(
351 pkt_ctx_field
, field_name
);
352 struct bt_clock_class
*clock_class
;
358 BT_ASSERT(bt_field_is_integer(field
));
359 BT_ASSERT(!bt_field_type_integer_is_signed(
360 bt_field_borrow_type(field
)));
361 clock_class
= bt_field_type_integer_borrow_mapped_clock_class(
362 bt_field_borrow_type(field
));
367 ret
= bt_field_integer_unsigned_get_value(field
, &val
);
369 ret
= bt_clock_value_set_set_clock_value(cv_set
, clock_class
,
377 int bt_packet_set_properties(struct bt_packet
*packet
)
379 struct bt_field
*pkt_context_field
;
383 BT_ASSERT(!packet
->props_are_set
);
385 pkt_context_field
= bt_packet_borrow_context(packet
);
386 if (!pkt_context_field
) {
390 /* Discarded event counter */
391 val
= get_uint_field_value(pkt_context_field
, "events_discarded");
392 if (val
!= UINT64_C(-1)) {
393 set_packet_prop_uint64(&packet
->discarded_event_counter
, val
);
396 /* Sequence number */
397 val
= get_uint_field_value(pkt_context_field
, "packet_seq_num");
398 if (val
!= UINT64_C(-1)) {
399 set_packet_prop_uint64(&packet
->seq_num
, val
);
402 /* Beginning and end times */
403 ret
= set_packet_default_clock_value(pkt_context_field
,
404 "timestamp_begin", &packet
->begin_cv_set
);
409 ret
= set_packet_default_clock_value(pkt_context_field
,
410 "timestamp_end", &packet
->end_cv_set
);
415 /* Information from previous packet */
416 if (packet
->prev_packet_info
.avail
==
417 BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE
) {
418 /* Discarded event count */
419 if (packet
->prev_packet_info
.discarded_event_counter
.avail
==
420 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
) {
421 BT_ASSERT(packet
->discarded_event_counter
.avail
==
422 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
);
423 set_packet_prop_uint64(&packet
->discarded_event_count
,
424 packet
->discarded_event_counter
.value
-
425 packet
->prev_packet_info
.discarded_event_counter
.value
);
428 /* Discarded packet count */
429 if (packet
->prev_packet_info
.seq_num
.avail
==
430 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
) {
431 BT_ASSERT(packet
->seq_num
.avail
==
432 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
);
433 set_packet_prop_uint64(&packet
->discarded_packet_count
,
434 packet
->seq_num
.value
-
435 packet
->prev_packet_info
.seq_num
.value
- 1);
444 int snapshot_prev_packet_properties(struct bt_packet
*packet
,
445 enum bt_packet_previous_packet_availability prev_packet_avail
,
446 struct bt_packet
*prev_packet
)
449 struct bt_clock_value
*prev_packet_default_end_cv
;
455 if (!prev_packet
->props_are_set
) {
456 ret
= bt_packet_set_properties(prev_packet
);
458 BT_LIB_LOGE("Cannot update previous packet's properties: "
459 "%![prev-packet-]+a", prev_packet
);
464 packet
->prev_packet_info
.avail
= prev_packet_avail
;
465 prev_packet_default_end_cv
= prev_packet
->end_cv_set
.default_cv
;
468 if (prev_packet_default_end_cv
) {
469 /* Copy clock value */
470 packet
->prev_packet_info
.default_end_cv
.cv
=
471 bt_clock_value_create(
472 prev_packet_default_end_cv
->clock_class
);
473 if (!packet
->prev_packet_info
.default_end_cv
.cv
) {
474 BT_LIB_LOGE("Cannot create a clock value from a clock class: "
476 prev_packet_default_end_cv
->clock_class
);
481 bt_clock_value_set_raw_value(
482 packet
->prev_packet_info
.default_end_cv
.cv
,
483 prev_packet_default_end_cv
->value
);
484 packet
->prev_packet_info
.default_end_cv
.avail
=
485 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
;
488 /* Discarded event counter */
489 packet
->prev_packet_info
.discarded_event_counter
=
490 prev_packet
->discarded_event_counter
;
492 /* Sequence number */
493 packet
->prev_packet_info
.seq_num
= prev_packet
->seq_num
;
499 struct bt_packet
*bt_packet_create(struct bt_stream
*stream
,
500 enum bt_packet_previous_packet_availability prev_packet_avail
,
501 struct bt_packet
*prev_packet
)
503 struct bt_packet
*packet
= NULL
;
506 BT_ASSERT_PRE_NON_NULL(stream
, "Stream");
507 BT_ASSERT_PRE(!prev_packet
|| prev_packet
->stream
== stream
,
508 "New packet's and previous packet's stream are not the same: "
509 "%![new-packet-stream-]+s, %![prev-packet]+a, "
510 "%![prev-packet-stream]+s", stream
, prev_packet
,
511 prev_packet
->stream
);
513 prev_packet_avail
== BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE
||
514 prev_packet_avail
== BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NOT_AVAILABLE
||
515 prev_packet_avail
== BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_NONE
,
516 "Invalid previous packet availability value: val=%d",
518 BT_ASSERT_PRE(!prev_packet
||
519 prev_packet_avail
== BT_PACKET_PREVIOUS_PACKET_AVAILABILITY_AVAILABLE
,
520 "Previous packet is available, but previous packet is NULL.");
521 packet
= bt_object_pool_create_object(&stream
->packet_pool
);
522 if (unlikely(!packet
)) {
523 BT_LIB_LOGE("Cannot allocate one packet from stream's packet pool: "
524 "%![stream-]+s", stream
);
528 if (unlikely(!packet
->stream
)) {
529 packet
->stream
= stream
;
530 bt_object_get_no_null_check_no_parent_check(
531 &packet
->stream
->common
.base
);
534 ret
= snapshot_prev_packet_properties(packet
, prev_packet_avail
,
543 bt_packet_validate_properties(prev_packet
);
544 bt_packet_set_is_frozen(prev_packet
, true);
553 int bt_packet_move_header(struct bt_packet
*packet
,
554 struct bt_packet_header_field
*header_field
)
556 struct bt_trace
*trace
;
557 struct bt_field_wrapper
*field_wrapper
= (void *) header_field
;
559 BT_ASSERT_PRE_NON_NULL(packet
, "Event");
560 BT_ASSERT_PRE_NON_NULL(field_wrapper
, "Header field");
561 BT_ASSERT_PRE_HOT(packet
, "Packet", ": %!+a", packet
);
562 trace
= bt_stream_class_borrow_trace(
563 bt_stream_borrow_class(packet
->stream
));
564 BT_ASSERT_PRE(trace
->common
.packet_header_field_type
,
565 "Trace has no packet header field type: %!+t",
568 /* TODO: compare field types (precondition) */
570 /* Recycle current header field: always exists */
571 BT_ASSERT(packet
->header
);
572 bt_packet_header_field_recycle(packet
->header
, trace
);
575 packet
->header
= field_wrapper
;
579 int bt_packet_move_context(struct bt_packet
*packet
,
580 struct bt_packet_context_field
*context_field
)
582 struct bt_stream_class
*stream_class
;
583 struct bt_field_wrapper
*field_wrapper
= (void *) context_field
;
585 BT_ASSERT_PRE_NON_NULL(packet
, "Event");
586 BT_ASSERT_PRE_NON_NULL(field_wrapper
, "Context field");
587 BT_ASSERT_PRE_HOT(packet
, "Packet", ": %!+a", packet
);
588 stream_class
= bt_stream_borrow_class(packet
->stream
);
589 BT_ASSERT_PRE(stream_class
->common
.packet_context_field_type
,
590 "Stream class has no packet context field type: %!+S",
593 /* TODO: compare field types (precondition) */
595 /* Recycle current context field: always exists */
596 BT_ASSERT(packet
->context
);
597 bt_packet_context_field_recycle(packet
->context
, stream_class
);
600 packet
->context
= field_wrapper
;
604 enum bt_packet_property_availability
605 bt_packet_borrow_default_beginning_clock_value(struct bt_packet
*packet
,
606 struct bt_clock_value
**clock_value
)
608 enum bt_packet_property_availability avail
=
609 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
;
611 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
612 BT_ASSERT_PRE_NON_NULL(clock_value
, "Clock value");
613 *clock_value
= packet
->begin_cv_set
.default_cv
;
615 avail
= BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE
;
621 enum bt_packet_property_availability
622 bt_packet_borrow_default_end_clock_value(struct bt_packet
*packet
,
623 struct bt_clock_value
**clock_value
)
625 enum bt_packet_property_availability avail
=
626 BT_PACKET_PROPERTY_AVAILABILITY_AVAILABLE
;
628 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
629 BT_ASSERT_PRE_NON_NULL(clock_value
, "Clock value");
630 *clock_value
= packet
->end_cv_set
.default_cv
;
632 avail
= BT_PACKET_PROPERTY_AVAILABILITY_NOT_AVAILABLE
;
638 enum bt_packet_previous_packet_availability
639 bt_packet_get_previous_packet_availability(struct bt_packet
*packet
)
641 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
642 return packet
->prev_packet_info
.avail
;
645 enum bt_packet_property_availability
646 bt_packet_borrow_previous_packet_default_end_clock_value(
647 struct bt_packet
*packet
, struct bt_clock_value
**clock_value
)
649 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
650 BT_ASSERT_PRE_NON_NULL(clock_value
, "Clock value");
651 *clock_value
= packet
->prev_packet_info
.default_end_cv
.cv
;
652 return packet
->prev_packet_info
.default_end_cv
.avail
;
655 enum bt_packet_property_availability
bt_packet_get_discarded_event_counter(
656 struct bt_packet
*packet
, uint64_t *counter
)
658 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
659 BT_ASSERT_PRE_NON_NULL(counter
, "Counter");
660 *counter
= packet
->discarded_event_counter
.value
;
661 return packet
->discarded_event_counter
.avail
;
664 enum bt_packet_property_availability
bt_packet_get_sequence_number(
665 struct bt_packet
*packet
, uint64_t *sequence_number
)
667 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
668 BT_ASSERT_PRE_NON_NULL(sequence_number
, "Sequence number");
669 *sequence_number
= packet
->seq_num
.value
;
670 return packet
->seq_num
.avail
;
673 enum bt_packet_property_availability
bt_packet_get_discarded_event_count(
674 struct bt_packet
*packet
, uint64_t *count
)
676 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
677 BT_ASSERT_PRE_NON_NULL(count
, "Count");
678 *count
= packet
->discarded_event_count
.value
;
679 return packet
->discarded_event_count
.avail
;
682 enum bt_packet_property_availability
bt_packet_get_discarded_packet_count(
683 struct bt_packet
*packet
, uint64_t *count
)
685 BT_ASSERT_PRE_NON_NULL(packet
, "Packet");
686 BT_ASSERT_PRE_NON_NULL(count
, "Count");
687 *count
= packet
->discarded_packet_count
.value
;
688 return packet
->discarded_packet_count
.avail
;