4 * Babeltrace CTF IR - Clock class
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #define BT_LOG_TAG "CLOCK-CLASS"
30 #include <babeltrace/lib-logging-internal.h>
32 #include <babeltrace/compat/uuid-internal.h>
33 #include <babeltrace/ctf-ir/clock-class-internal.h>
34 #include <babeltrace/ctf-ir/clock-value-internal.h>
35 #include <babeltrace/ctf-ir/utils.h>
36 #include <babeltrace/ref.h>
37 #include <babeltrace/compiler-internal.h>
38 #include <babeltrace/types.h>
39 #include <babeltrace/compat/string-internal.h>
41 #include <babeltrace/object-internal.h>
44 void bt_clock_class_destroy(struct bt_object
*obj
);
47 bt_bool
bt_clock_class_is_valid(struct bt_clock_class
*clock_class
)
49 return clock_class
&& clock_class
->name
;
52 int bt_clock_class_set_name(struct bt_clock_class
*clock_class
,
58 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
63 if (clock_class
->frozen
) {
64 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
65 clock_class
, bt_clock_class_get_name(clock_class
));
70 if (!bt_identifier_is_valid(name
)) {
71 BT_LOGE("Clock class's name is not a valid CTF identifier: "
72 "addr=%p, name=\"%s\"",
78 if (clock_class
->name
) {
79 g_string_assign(clock_class
->name
, name
);
81 clock_class
->name
= g_string_new(name
);
82 if (!clock_class
->name
) {
83 BT_LOGE_STR("Failed to allocate a GString.");
89 BT_LOGV("Set clock class's name: addr=%p, name=\"%s\"",
97 bool validate_freq(struct bt_clock_class
*clock_class
,
98 const char *name
, uint64_t freq
)
100 bool is_valid
= true;
102 if (freq
== -1ULL || freq
== 0) {
103 BT_LOGW("Invalid parameter: frequency is invalid: "
104 "addr=%p, name=\"%s\", freq=%" PRIu64
,
105 clock_class
, name
, freq
);
114 struct bt_clock_class
*bt_clock_class_create(const char *name
,
118 struct bt_clock_class
*clock_class
= NULL
;
120 BT_LOGD("Creating default clock class object: name=\"%s\"",
123 if (!validate_freq(NULL
, name
, freq
)) {
124 /* validate_freq() logs errors */
128 clock_class
= g_new0(struct bt_clock_class
, 1);
130 BT_LOGE_STR("Failed to allocate one clock class.");
134 clock_class
->precision
= 1;
135 clock_class
->frequency
= freq
;
136 bt_object_init(clock_class
, bt_clock_class_destroy
);
139 ret
= bt_clock_class_set_name(clock_class
, name
);
141 BT_LOGE("Cannot set clock class's name: "
142 "addr=%p, name=\"%s\"",
148 BT_LOGD("Created clock class object: addr=%p, name=\"%s\"",
156 const char *bt_clock_class_get_name(struct bt_clock_class
*clock_class
)
158 const char *ret
= NULL
;
161 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
165 if (clock_class
->name
) {
166 ret
= clock_class
->name
->str
;
173 const char *bt_clock_class_get_description(
174 struct bt_clock_class
*clock_class
)
176 const char *ret
= NULL
;
179 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
183 if (clock_class
->description
) {
184 ret
= clock_class
->description
->str
;
190 int bt_clock_class_set_description(struct bt_clock_class
*clock_class
,
195 if (!clock_class
|| !desc
) {
196 BT_LOGW("Invalid parameter: clock class or description is NULL: "
197 "clock-class-addr=%p, name=\"%s\", desc-addr=%p",
198 clock_class
, bt_clock_class_get_name(clock_class
),
204 if (clock_class
->frozen
) {
205 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
206 clock_class
, bt_clock_class_get_name(clock_class
));
211 clock_class
->description
= g_string_new(desc
);
212 ret
= clock_class
->description
? 0 : -1;
213 BT_LOGV("Set clock class's description: addr=%p, "
214 "name=\"%s\", desc=\"%s\"",
215 clock_class
, bt_clock_class_get_name(clock_class
), desc
);
220 uint64_t bt_clock_class_get_frequency(
221 struct bt_clock_class
*clock_class
)
223 uint64_t ret
= -1ULL;
226 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
230 ret
= clock_class
->frequency
;
235 int bt_clock_class_set_frequency(struct bt_clock_class
*clock_class
,
241 BT_LOGW("Invalid parameter: clock class is NULL or frequency is invalid: "
242 "addr=%p, name=\"%s\"",
243 clock_class
, bt_clock_class_get_name(clock_class
));
248 if (!validate_freq(clock_class
, bt_clock_class_get_name(clock_class
),
250 /* validate_freq() logs errors */
254 if (clock_class
->frozen
) {
255 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
256 clock_class
, bt_clock_class_get_name(clock_class
));
261 clock_class
->frequency
= freq
;
262 BT_LOGV("Set clock class's frequency: addr=%p, name=\"%s\", freq=%" PRIu64
,
263 clock_class
, bt_clock_class_get_name(clock_class
), freq
);
268 uint64_t bt_clock_class_get_precision(struct bt_clock_class
*clock_class
)
270 uint64_t ret
= -1ULL;
273 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
277 ret
= clock_class
->precision
;
282 int bt_clock_class_set_precision(struct bt_clock_class
*clock_class
,
287 if (!clock_class
|| precision
== -1ULL) {
288 BT_LOGW("Invalid parameter: clock class is NULL or precision is invalid: "
289 "addr=%p, name=\"%s\", precision=%" PRIu64
,
290 clock_class
, bt_clock_class_get_name(clock_class
),
296 if (clock_class
->frozen
) {
297 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
298 clock_class
, bt_clock_class_get_name(clock_class
));
303 clock_class
->precision
= precision
;
304 BT_LOGV("Set clock class's precision: addr=%p, name=\"%s\", precision=%" PRIu64
,
305 clock_class
, bt_clock_class_get_name(clock_class
),
311 int bt_clock_class_get_offset_s(struct bt_clock_class
*clock_class
,
316 if (!clock_class
|| !offset_s
) {
317 BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
318 "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
319 clock_class
, bt_clock_class_get_name(clock_class
),
325 *offset_s
= clock_class
->offset_s
;
330 int bt_clock_class_set_offset_s(struct bt_clock_class
*clock_class
,
336 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
341 if (clock_class
->frozen
) {
342 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
343 clock_class
, bt_clock_class_get_name(clock_class
));
348 clock_class
->offset_s
= offset_s
;
349 BT_LOGV("Set clock class's offset (seconds): "
350 "addr=%p, name=\"%s\", offset-s=%" PRId64
,
351 clock_class
, bt_clock_class_get_name(clock_class
),
357 int bt_clock_class_get_offset_cycles(struct bt_clock_class
*clock_class
,
362 if (!clock_class
|| !offset
) {
363 BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
364 "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
365 clock_class
, bt_clock_class_get_name(clock_class
),
371 *offset
= clock_class
->offset
;
376 int bt_clock_class_set_offset_cycles(struct bt_clock_class
*clock_class
,
382 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
387 if (clock_class
->frozen
) {
388 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
389 clock_class
, bt_clock_class_get_name(clock_class
));
394 clock_class
->offset
= offset
;
395 BT_LOGV("Set clock class's offset (cycles): addr=%p, name=\"%s\", offset-cycles=%" PRId64
,
396 clock_class
, bt_clock_class_get_name(clock_class
), offset
);
401 bt_bool
bt_clock_class_is_absolute(struct bt_clock_class
*clock_class
)
406 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
410 ret
= clock_class
->absolute
;
415 int bt_clock_class_set_is_absolute(struct bt_clock_class
*clock_class
,
421 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
426 if (clock_class
->frozen
) {
427 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
428 clock_class
, bt_clock_class_get_name(clock_class
));
433 clock_class
->absolute
= !!is_absolute
;
434 BT_LOGV("Set clock class's absolute flag: addr=%p, name=\"%s\", is-absolute=%d",
435 clock_class
, bt_clock_class_get_name(clock_class
),
441 const unsigned char *bt_clock_class_get_uuid(
442 struct bt_clock_class
*clock_class
)
444 const unsigned char *ret
;
447 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
452 if (!clock_class
->uuid_set
) {
453 BT_LOGV("Clock class's UUID is not set: addr=%p, name=\"%s\"",
454 clock_class
, bt_clock_class_get_name(clock_class
));
459 ret
= clock_class
->uuid
;
464 int bt_clock_class_set_uuid(struct bt_clock_class
*clock_class
,
465 const unsigned char *uuid
)
469 if (!clock_class
|| !uuid
) {
470 BT_LOGW("Invalid parameter: clock class or UUID is NULL: "
471 "clock-class-addr=%p, name=\"%s\", uuid-addr=%p",
472 clock_class
, bt_clock_class_get_name(clock_class
),
478 if (clock_class
->frozen
) {
479 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
480 clock_class
, bt_clock_class_get_name(clock_class
));
485 memcpy(clock_class
->uuid
, uuid
, BABELTRACE_UUID_LEN
);
486 clock_class
->uuid_set
= 1;
487 BT_LOGV("Set clock class's UUID: addr=%p, name=\"%s\", "
488 "uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
489 clock_class
, bt_clock_class_get_name(clock_class
),
490 (unsigned int) uuid
[0],
491 (unsigned int) uuid
[1],
492 (unsigned int) uuid
[2],
493 (unsigned int) uuid
[3],
494 (unsigned int) uuid
[4],
495 (unsigned int) uuid
[5],
496 (unsigned int) uuid
[6],
497 (unsigned int) uuid
[7],
498 (unsigned int) uuid
[8],
499 (unsigned int) uuid
[9],
500 (unsigned int) uuid
[10],
501 (unsigned int) uuid
[11],
502 (unsigned int) uuid
[12],
503 (unsigned int) uuid
[13],
504 (unsigned int) uuid
[14],
505 (unsigned int) uuid
[15]);
510 static uint64_t ns_from_value(uint64_t frequency
, uint64_t value
)
514 if (frequency
== 1000000000) {
517 double dblres
= ((1e9
* (double) value
) / (double) frequency
);
519 if (dblres
>= (double) UINT64_MAX
) {
520 /* Overflows uint64_t */
523 ns
= (uint64_t) dblres
;
531 void bt_clock_class_freeze(struct bt_clock_class
*clock_class
)
534 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
538 if (!clock_class
->frozen
) {
539 BT_LOGD("Freezing clock class: addr=%p, name=\"%s\"",
540 clock_class
, bt_clock_class_get_name(clock_class
));
541 clock_class
->frozen
= 1;
546 void bt_clock_class_serialize(struct bt_clock_class
*clock_class
,
547 struct metadata_context
*context
)
551 BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, "
552 "name=\"%s\", metadata-context-addr=%p", clock_class
,
553 bt_clock_class_get_name(clock_class
), context
);
555 if (!clock_class
|| !context
) {
556 BT_LOGW("Invalid parameter: clock class or metadata context is NULL: "
557 "clock-class-addr=%p, name=\"%s\", metadata-context-addr=%p",
558 clock_class
, bt_clock_class_get_name(clock_class
),
563 uuid
= clock_class
->uuid
;
564 g_string_append(context
->string
, "clock {\n");
565 g_string_append_printf(context
->string
, "\tname = %s;\n",
566 clock_class
->name
->str
);
568 if (clock_class
->uuid_set
) {
569 g_string_append_printf(context
->string
,
570 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
571 uuid
[0], uuid
[1], uuid
[2], uuid
[3],
572 uuid
[4], uuid
[5], uuid
[6], uuid
[7],
573 uuid
[8], uuid
[9], uuid
[10], uuid
[11],
574 uuid
[12], uuid
[13], uuid
[14], uuid
[15]);
577 if (clock_class
->description
) {
578 g_string_append_printf(context
->string
, "\tdescription = \"%s\";\n",
579 clock_class
->description
->str
);
582 g_string_append_printf(context
->string
, "\tfreq = %" PRIu64
";\n",
583 clock_class
->frequency
);
584 g_string_append_printf(context
->string
, "\tprecision = %" PRIu64
";\n",
585 clock_class
->precision
);
586 g_string_append_printf(context
->string
, "\toffset_s = %" PRIu64
";\n",
587 clock_class
->offset_s
);
588 g_string_append_printf(context
->string
, "\toffset = %" PRIu64
";\n",
589 clock_class
->offset
);
590 g_string_append_printf(context
->string
, "\tabsolute = %s;\n",
591 clock_class
->absolute
? "true" : "false");
592 g_string_append(context
->string
, "};\n\n");
596 void bt_clock_class_destroy(struct bt_object
*obj
)
598 struct bt_clock_class
*clock_class
;
600 clock_class
= container_of(obj
, struct bt_clock_class
, base
);
601 BT_LOGD("Destroying clock class: addr=%p, name=\"%s\"",
602 obj
, bt_clock_class_get_name(clock_class
));
603 if (clock_class
->name
) {
604 g_string_free(clock_class
->name
, TRUE
);
606 if (clock_class
->description
) {
607 g_string_free(clock_class
->description
, TRUE
);
614 void bt_clock_value_destroy(struct bt_object
*obj
)
616 struct bt_clock_value
*value
;
622 value
= container_of(obj
, struct bt_clock_value
, base
);
623 BT_LOGD("Destroying clock value: addr=%p, clock-class-addr=%p, "
624 "clock-class-name=\"%s\"", obj
, value
->clock_class
,
625 bt_clock_class_get_name(value
->clock_class
));
626 bt_put(value
->clock_class
);
631 void set_ns_from_epoch(struct bt_clock_value
*clock_value
)
633 struct bt_clock_class
*clock_class
= clock_value
->clock_class
;
639 /* Initialize nanosecond timestamp to clock's offset in seconds */
640 if (clock_class
->offset_s
<= (INT64_MIN
/ 1000000000) ||
641 clock_class
->offset_s
>= (INT64_MAX
/ 1000000000)) {
643 * Overflow: offset in seconds converted to nanoseconds
644 * is outside the int64_t range.
646 clock_value
->ns_from_epoch_overflows
= true;
650 clock_value
->ns_from_epoch
= clock_class
->offset_s
* (int64_t) 1000000000;
652 /* Add offset in cycles */
653 if (clock_class
->offset
< 0) {
654 cycles
= (uint64_t) (-clock_class
->offset
);
656 cycles
= (uint64_t) clock_class
->offset
;
659 u_ns
= ns_from_value(clock_class
->frequency
, cycles
);
661 if (u_ns
== -1ULL || u_ns
>= INT64_MAX
) {
663 * Overflow: offset in cycles converted to nanoseconds
664 * is outside the int64_t range.
666 clock_value
->ns_from_epoch_overflows
= true;
670 s_ns
= (int64_t) u_ns
;
673 if (clock_class
->offset
< 0) {
674 if (clock_value
->ns_from_epoch
>= 0) {
676 * Offset in cycles is negative so it must also
677 * be negative once converted to nanoseconds.
683 diff
= clock_value
->ns_from_epoch
- INT64_MIN
;
687 * Overflow: current timestamp in nanoseconds
688 * plus the offset in cycles converted to
689 * nanoseconds is outside the int64_t range.
691 clock_value
->ns_from_epoch_overflows
= true;
696 * Offset in cycles is negative so it must also be
697 * negative once converted to nanoseconds.
701 if (clock_value
->ns_from_epoch
<= 0) {
705 diff
= INT64_MAX
- clock_value
->ns_from_epoch
;
709 * Overflow: current timestamp in nanoseconds
710 * plus the offset in cycles converted to
711 * nanoseconds is outside the int64_t range.
713 clock_value
->ns_from_epoch_overflows
= true;
719 clock_value
->ns_from_epoch
+= s_ns
;
721 /* Add clock value (cycles) */
722 u_ns
= ns_from_value(clock_class
->frequency
, clock_value
->value
);
724 if (u_ns
== -1ULL || u_ns
>= INT64_MAX
) {
726 * Overflow: value converted to nanoseconds is outside
729 clock_value
->ns_from_epoch_overflows
= true;
733 s_ns
= (int64_t) u_ns
;
736 /* Clock value (cycles) is always positive */
737 if (clock_value
->ns_from_epoch
<= 0) {
741 diff
= INT64_MAX
- clock_value
->ns_from_epoch
;
745 * Overflow: current timestamp in nanoseconds plus the
746 * clock value converted to nanoseconds is outside the
749 clock_value
->ns_from_epoch_overflows
= true;
754 clock_value
->ns_from_epoch
+= s_ns
;
757 if (clock_value
->ns_from_epoch_overflows
) {
758 clock_value
->ns_from_epoch
= 0;
762 struct bt_clock_value
*bt_clock_value_create(
763 struct bt_clock_class
*clock_class
, uint64_t value
)
765 struct bt_clock_value
*ret
= NULL
;
767 BT_LOGD("Creating clock value object: clock-class-addr=%p, "
768 "clock-class-name=\"%s\", value=%" PRIu64
, clock_class
,
769 bt_clock_class_get_name(clock_class
), value
);
772 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
776 ret
= g_new0(struct bt_clock_value
, 1);
778 BT_LOGE_STR("Failed to allocate one clock value.");
782 bt_object_init(ret
, bt_clock_value_destroy
);
783 ret
->clock_class
= bt_get(clock_class
);
785 set_ns_from_epoch(ret
);
786 bt_clock_class_freeze(clock_class
);
787 BT_LOGD("Created clock value object: clock-value-addr=%p, "
788 "clock-class-addr=%p, clock-class-name=\"%s\", "
789 "ns-from-epoch=%" PRId64
", ns-from-epoch-overflows=%d",
790 ret
, clock_class
, bt_clock_class_get_name(clock_class
),
791 ret
->ns_from_epoch
, ret
->ns_from_epoch_overflows
);
797 int bt_clock_value_get_value(
798 struct bt_clock_value
*clock_value
, uint64_t *raw_value
)
802 if (!clock_value
|| !raw_value
) {
803 BT_LOGW("Invalid parameter: clock value or raw value is NULL: "
804 "clock-value-addr=%p, raw-value-addr=%p",
805 clock_value
, raw_value
);
810 *raw_value
= clock_value
->value
;
815 int bt_clock_value_get_value_ns_from_epoch(struct bt_clock_value
*value
,
816 int64_t *ret_value_ns
)
820 if (!value
|| !ret_value_ns
) {
821 BT_LOGW("Invalid parameter: clock value or return value pointer is NULL: "
822 "clock-value-addr=%p, ret-value-addr=%p",
823 value
, ret_value_ns
);
828 if (value
->ns_from_epoch_overflows
) {
829 BT_LOGW("Clock value converted to nanoseconds from Epoch overflows the signed 64-bit integer range: "
830 "clock-value-addr=%p, "
831 "clock-class-offset-s=%" PRId64
", "
832 "clock-class-offset-cycles=%" PRId64
", "
834 value
, value
->clock_class
->offset_s
,
835 value
->clock_class
->offset
,
841 *ret_value_ns
= value
->ns_from_epoch
;
847 struct bt_clock_class
*bt_clock_value_get_class(
848 struct bt_clock_value
*clock_value
)
850 struct bt_clock_class
*clock_class
= NULL
;
853 BT_LOGW_STR("Invalid parameter: clock value is NULL.");
857 clock_class
= bt_get(clock_value
->clock_class
);
This page took 0.053172 seconds and 4 git commands to generate.