Replace assert() -> BT_ASSERT() and some preconditions with BT_ASSERT_PRE()
[babeltrace.git] / lib / ctf-ir / clock-class.c
1 /*
2 * clock-class.c
3 *
4 * Babeltrace CTF IR - Clock class
5 *
6 * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com>
7 *
8 * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com>
9 *
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:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
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
26 * SOFTWARE.
27 */
28
29 #define BT_LOG_TAG "CLOCK-CLASS"
30 #include <babeltrace/lib-logging-internal.h>
31
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>
40 #include <inttypes.h>
41 #include <babeltrace/object-internal.h>
42 #include <babeltrace/assert-internal.h>
43
44 static
45 void bt_clock_class_destroy(struct bt_object *obj);
46
47 BT_HIDDEN
48 bt_bool bt_clock_class_is_valid(struct bt_clock_class *clock_class)
49 {
50 return clock_class && clock_class->name;
51 }
52
53 int bt_clock_class_set_name(struct bt_clock_class *clock_class,
54 const char *name)
55 {
56 int ret = 0;
57
58 if (!clock_class) {
59 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
60 ret = -1;
61 goto end;
62 }
63
64 if (clock_class->frozen) {
65 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
66 clock_class, bt_clock_class_get_name(clock_class));
67 ret = -1;
68 goto end;
69 }
70
71 if (!bt_identifier_is_valid(name)) {
72 BT_LOGE("Clock class's name is not a valid CTF identifier: "
73 "addr=%p, name=\"%s\"",
74 clock_class, name);
75 ret = -1;
76 goto end;
77 }
78
79 if (clock_class->name) {
80 g_string_assign(clock_class->name, name);
81 } else {
82 clock_class->name = g_string_new(name);
83 if (!clock_class->name) {
84 BT_LOGE_STR("Failed to allocate a GString.");
85 ret = -1;
86 goto end;
87 }
88 }
89
90 BT_LOGV("Set clock class's name: addr=%p, name=\"%s\"",
91 clock_class, name);
92
93 end:
94 return ret;
95 }
96
97 static
98 bool validate_freq(struct bt_clock_class *clock_class,
99 const char *name, uint64_t freq)
100 {
101 bool is_valid = true;
102
103 if (freq == -1ULL || freq == 0) {
104 BT_LOGW("Invalid parameter: frequency is invalid: "
105 "addr=%p, name=\"%s\", freq=%" PRIu64,
106 clock_class, name, freq);
107 is_valid = false;
108 goto end;
109 }
110
111 end:
112 return is_valid;
113 }
114
115 struct bt_clock_class *bt_clock_class_create(const char *name,
116 uint64_t freq)
117 {
118 int ret;
119 struct bt_clock_class *clock_class = NULL;
120
121 BT_LOGD("Creating default clock class object: name=\"%s\"",
122 name);
123
124 if (!validate_freq(NULL, name, freq)) {
125 /* validate_freq() logs errors */
126 goto error;
127 }
128
129 clock_class = g_new0(struct bt_clock_class, 1);
130 if (!clock_class) {
131 BT_LOGE_STR("Failed to allocate one clock class.");
132 goto error;
133 }
134
135 clock_class->precision = 1;
136 clock_class->frequency = freq;
137 bt_object_init(clock_class, bt_clock_class_destroy);
138
139 if (name) {
140 ret = bt_clock_class_set_name(clock_class, name);
141 if (ret) {
142 BT_LOGE("Cannot set clock class's name: "
143 "addr=%p, name=\"%s\"",
144 clock_class, name);
145 goto error;
146 }
147 }
148
149 BT_LOGD("Created clock class object: addr=%p, name=\"%s\"",
150 clock_class, name);
151 return clock_class;
152 error:
153 BT_PUT(clock_class);
154 return clock_class;
155 }
156
157 const char *bt_clock_class_get_name(struct bt_clock_class *clock_class)
158 {
159 const char *ret = NULL;
160
161 if (!clock_class) {
162 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
163 goto end;
164 }
165
166 if (clock_class->name) {
167 ret = clock_class->name->str;
168 }
169
170 end:
171 return ret;
172 }
173
174 const char *bt_clock_class_get_description(
175 struct bt_clock_class *clock_class)
176 {
177 const char *ret = NULL;
178
179 if (!clock_class) {
180 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
181 goto end;
182 }
183
184 if (clock_class->description) {
185 ret = clock_class->description->str;
186 }
187 end:
188 return ret;
189 }
190
191 int bt_clock_class_set_description(struct bt_clock_class *clock_class,
192 const char *desc)
193 {
194 int ret = 0;
195
196 if (!clock_class || !desc) {
197 BT_LOGW("Invalid parameter: clock class or description is NULL: "
198 "clock-class-addr=%p, name=\"%s\", desc-addr=%p",
199 clock_class, bt_clock_class_get_name(clock_class),
200 desc);
201 ret = -1;
202 goto end;
203 }
204
205 if (clock_class->frozen) {
206 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
207 clock_class, bt_clock_class_get_name(clock_class));
208 ret = -1;
209 goto end;
210 }
211
212 clock_class->description = g_string_new(desc);
213 ret = clock_class->description ? 0 : -1;
214 BT_LOGV("Set clock class's description: addr=%p, "
215 "name=\"%s\", desc=\"%s\"",
216 clock_class, bt_clock_class_get_name(clock_class), desc);
217 end:
218 return ret;
219 }
220
221 uint64_t bt_clock_class_get_frequency(
222 struct bt_clock_class *clock_class)
223 {
224 uint64_t ret = -1ULL;
225
226 if (!clock_class) {
227 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
228 goto end;
229 }
230
231 ret = clock_class->frequency;
232 end:
233 return ret;
234 }
235
236 int bt_clock_class_set_frequency(struct bt_clock_class *clock_class,
237 uint64_t freq)
238 {
239 int ret = 0;
240
241 if (!clock_class) {
242 BT_LOGW("Invalid parameter: clock class is NULL or frequency is invalid: "
243 "addr=%p, name=\"%s\"",
244 clock_class, bt_clock_class_get_name(clock_class));
245 ret = -1;
246 goto end;
247 }
248
249 if (!validate_freq(clock_class, bt_clock_class_get_name(clock_class),
250 freq)) {
251 /* validate_freq() logs errors */
252 goto end;
253 }
254
255 if (clock_class->frozen) {
256 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
257 clock_class, bt_clock_class_get_name(clock_class));
258 ret = -1;
259 goto end;
260 }
261
262 clock_class->frequency = freq;
263 BT_LOGV("Set clock class's frequency: addr=%p, name=\"%s\", freq=%" PRIu64,
264 clock_class, bt_clock_class_get_name(clock_class), freq);
265 end:
266 return ret;
267 }
268
269 uint64_t bt_clock_class_get_precision(struct bt_clock_class *clock_class)
270 {
271 uint64_t ret = -1ULL;
272
273 if (!clock_class) {
274 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
275 goto end;
276 }
277
278 ret = clock_class->precision;
279 end:
280 return ret;
281 }
282
283 int bt_clock_class_set_precision(struct bt_clock_class *clock_class,
284 uint64_t precision)
285 {
286 int ret = 0;
287
288 if (!clock_class || precision == -1ULL) {
289 BT_LOGW("Invalid parameter: clock class is NULL or precision is invalid: "
290 "addr=%p, name=\"%s\", precision=%" PRIu64,
291 clock_class, bt_clock_class_get_name(clock_class),
292 precision);
293 ret = -1;
294 goto end;
295 }
296
297 if (clock_class->frozen) {
298 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
299 clock_class, bt_clock_class_get_name(clock_class));
300 ret = -1;
301 goto end;
302 }
303
304 clock_class->precision = precision;
305 BT_LOGV("Set clock class's precision: addr=%p, name=\"%s\", precision=%" PRIu64,
306 clock_class, bt_clock_class_get_name(clock_class),
307 precision);
308 end:
309 return ret;
310 }
311
312 int bt_clock_class_get_offset_s(struct bt_clock_class *clock_class,
313 int64_t *offset_s)
314 {
315 int ret = 0;
316
317 if (!clock_class || !offset_s) {
318 BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
319 "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
320 clock_class, bt_clock_class_get_name(clock_class),
321 offset_s);
322 ret = -1;
323 goto end;
324 }
325
326 *offset_s = clock_class->offset_s;
327 end:
328 return ret;
329 }
330
331 int bt_clock_class_set_offset_s(struct bt_clock_class *clock_class,
332 int64_t offset_s)
333 {
334 int ret = 0;
335
336 if (!clock_class) {
337 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
338 ret = -1;
339 goto end;
340 }
341
342 if (clock_class->frozen) {
343 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
344 clock_class, bt_clock_class_get_name(clock_class));
345 ret = -1;
346 goto end;
347 }
348
349 clock_class->offset_s = offset_s;
350 BT_LOGV("Set clock class's offset (seconds): "
351 "addr=%p, name=\"%s\", offset-s=%" PRId64,
352 clock_class, bt_clock_class_get_name(clock_class),
353 offset_s);
354 end:
355 return ret;
356 }
357
358 int bt_clock_class_get_offset_cycles(struct bt_clock_class *clock_class,
359 int64_t *offset)
360 {
361 int ret = 0;
362
363 if (!clock_class || !offset) {
364 BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
365 "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
366 clock_class, bt_clock_class_get_name(clock_class),
367 offset);
368 ret = -1;
369 goto end;
370 }
371
372 *offset = clock_class->offset;
373 end:
374 return ret;
375 }
376
377 int bt_clock_class_set_offset_cycles(struct bt_clock_class *clock_class,
378 int64_t offset)
379 {
380 int ret = 0;
381
382 if (!clock_class) {
383 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
384 ret = -1;
385 goto end;
386 }
387
388 if (clock_class->frozen) {
389 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
390 clock_class, bt_clock_class_get_name(clock_class));
391 ret = -1;
392 goto end;
393 }
394
395 clock_class->offset = offset;
396 BT_LOGV("Set clock class's offset (cycles): addr=%p, name=\"%s\", offset-cycles=%" PRId64,
397 clock_class, bt_clock_class_get_name(clock_class), offset);
398 end:
399 return ret;
400 }
401
402 bt_bool bt_clock_class_is_absolute(struct bt_clock_class *clock_class)
403 {
404 int ret = -1;
405
406 if (!clock_class) {
407 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
408 goto end;
409 }
410
411 ret = clock_class->absolute;
412 end:
413 return ret;
414 }
415
416 int bt_clock_class_set_is_absolute(struct bt_clock_class *clock_class,
417 bt_bool is_absolute)
418 {
419 int ret = 0;
420
421 if (!clock_class) {
422 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
423 ret = -1;
424 goto end;
425 }
426
427 if (clock_class->frozen) {
428 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
429 clock_class, bt_clock_class_get_name(clock_class));
430 ret = -1;
431 goto end;
432 }
433
434 clock_class->absolute = !!is_absolute;
435 BT_LOGV("Set clock class's absolute flag: addr=%p, name=\"%s\", is-absolute=%d",
436 clock_class, bt_clock_class_get_name(clock_class),
437 is_absolute);
438 end:
439 return ret;
440 }
441
442 const unsigned char *bt_clock_class_get_uuid(
443 struct bt_clock_class *clock_class)
444 {
445 const unsigned char *ret;
446
447 if (!clock_class) {
448 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
449 ret = NULL;
450 goto end;
451 }
452
453 if (!clock_class->uuid_set) {
454 BT_LOGV("Clock class's UUID is not set: addr=%p, name=\"%s\"",
455 clock_class, bt_clock_class_get_name(clock_class));
456 ret = NULL;
457 goto end;
458 }
459
460 ret = clock_class->uuid;
461 end:
462 return ret;
463 }
464
465 int bt_clock_class_set_uuid(struct bt_clock_class *clock_class,
466 const unsigned char *uuid)
467 {
468 int ret = 0;
469
470 if (!clock_class || !uuid) {
471 BT_LOGW("Invalid parameter: clock class or UUID is NULL: "
472 "clock-class-addr=%p, name=\"%s\", uuid-addr=%p",
473 clock_class, bt_clock_class_get_name(clock_class),
474 uuid);
475 ret = -1;
476 goto end;
477 }
478
479 if (clock_class->frozen) {
480 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
481 clock_class, bt_clock_class_get_name(clock_class));
482 ret = -1;
483 goto end;
484 }
485
486 memcpy(clock_class->uuid, uuid, BABELTRACE_UUID_LEN);
487 clock_class->uuid_set = 1;
488 BT_LOGV("Set clock class's UUID: addr=%p, name=\"%s\", "
489 "uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
490 clock_class, bt_clock_class_get_name(clock_class),
491 (unsigned int) uuid[0],
492 (unsigned int) uuid[1],
493 (unsigned int) uuid[2],
494 (unsigned int) uuid[3],
495 (unsigned int) uuid[4],
496 (unsigned int) uuid[5],
497 (unsigned int) uuid[6],
498 (unsigned int) uuid[7],
499 (unsigned int) uuid[8],
500 (unsigned int) uuid[9],
501 (unsigned int) uuid[10],
502 (unsigned int) uuid[11],
503 (unsigned int) uuid[12],
504 (unsigned int) uuid[13],
505 (unsigned int) uuid[14],
506 (unsigned int) uuid[15]);
507 end:
508 return ret;
509 }
510
511 static uint64_t ns_from_value(uint64_t frequency, uint64_t value)
512 {
513 uint64_t ns;
514
515 if (frequency == 1000000000) {
516 ns = value;
517 } else {
518 double dblres = ((1e9 * (double) value) / (double) frequency);
519
520 if (dblres >= (double) UINT64_MAX) {
521 /* Overflows uint64_t */
522 ns = -1ULL;
523 } else {
524 ns = (uint64_t) dblres;
525 }
526 }
527
528 return ns;
529 }
530
531 BT_HIDDEN
532 void bt_clock_class_freeze(struct bt_clock_class *clock_class)
533 {
534 if (!clock_class) {
535 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
536 return;
537 }
538
539 if (!clock_class->frozen) {
540 BT_LOGD("Freezing clock class: addr=%p, name=\"%s\"",
541 clock_class, bt_clock_class_get_name(clock_class));
542 clock_class->frozen = 1;
543 }
544 }
545
546 BT_HIDDEN
547 void bt_clock_class_serialize(struct bt_clock_class *clock_class,
548 struct metadata_context *context)
549 {
550 unsigned char *uuid;
551
552 BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, "
553 "name=\"%s\", metadata-context-addr=%p", clock_class,
554 bt_clock_class_get_name(clock_class), context);
555
556 if (!clock_class || !context) {
557 BT_LOGW("Invalid parameter: clock class or metadata context is NULL: "
558 "clock-class-addr=%p, name=\"%s\", metadata-context-addr=%p",
559 clock_class, bt_clock_class_get_name(clock_class),
560 context);
561 return;
562 }
563
564 uuid = clock_class->uuid;
565 g_string_append(context->string, "clock {\n");
566 g_string_append_printf(context->string, "\tname = %s;\n",
567 clock_class->name->str);
568
569 if (clock_class->uuid_set) {
570 g_string_append_printf(context->string,
571 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
572 uuid[0], uuid[1], uuid[2], uuid[3],
573 uuid[4], uuid[5], uuid[6], uuid[7],
574 uuid[8], uuid[9], uuid[10], uuid[11],
575 uuid[12], uuid[13], uuid[14], uuid[15]);
576 }
577
578 if (clock_class->description) {
579 g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
580 clock_class->description->str);
581 }
582
583 g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
584 clock_class->frequency);
585 g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
586 clock_class->precision);
587 g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
588 clock_class->offset_s);
589 g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
590 clock_class->offset);
591 g_string_append_printf(context->string, "\tabsolute = %s;\n",
592 clock_class->absolute ? "true" : "false");
593 g_string_append(context->string, "};\n\n");
594 }
595
596 static
597 void bt_clock_class_destroy(struct bt_object *obj)
598 {
599 struct bt_clock_class *clock_class;
600
601 clock_class = container_of(obj, struct bt_clock_class, base);
602 BT_LOGD("Destroying clock class: addr=%p, name=\"%s\"",
603 obj, bt_clock_class_get_name(clock_class));
604 if (clock_class->name) {
605 g_string_free(clock_class->name, TRUE);
606 }
607 if (clock_class->description) {
608 g_string_free(clock_class->description, TRUE);
609 }
610
611 g_free(clock_class);
612 }
613
614 static
615 void bt_clock_value_destroy(struct bt_object *obj)
616 {
617 struct bt_clock_value *value;
618
619 if (!obj) {
620 return;
621 }
622
623 value = container_of(obj, struct bt_clock_value, base);
624 BT_LOGD("Destroying clock value: addr=%p, clock-class-addr=%p, "
625 "clock-class-name=\"%s\"", obj, value->clock_class,
626 bt_clock_class_get_name(value->clock_class));
627 bt_put(value->clock_class);
628 g_free(value);
629 }
630
631 static
632 void set_ns_from_epoch(struct bt_clock_value *clock_value)
633 {
634 struct bt_clock_class *clock_class = clock_value->clock_class;
635 int64_t diff;
636 int64_t s_ns;
637 uint64_t u_ns;
638 uint64_t cycles;
639
640 /* Initialize nanosecond timestamp to clock's offset in seconds */
641 if (clock_class->offset_s <= (INT64_MIN / 1000000000) ||
642 clock_class->offset_s >= (INT64_MAX / 1000000000)) {
643 /*
644 * Overflow: offset in seconds converted to nanoseconds
645 * is outside the int64_t range.
646 */
647 clock_value->ns_from_epoch_overflows = true;
648 goto end;
649 }
650
651 clock_value->ns_from_epoch = clock_class->offset_s * (int64_t) 1000000000;
652
653 /* Add offset in cycles */
654 if (clock_class->offset < 0) {
655 cycles = (uint64_t) (-clock_class->offset);
656 } else {
657 cycles = (uint64_t) clock_class->offset;
658 }
659
660 u_ns = ns_from_value(clock_class->frequency, cycles);
661
662 if (u_ns == -1ULL || u_ns >= INT64_MAX) {
663 /*
664 * Overflow: offset in cycles converted to nanoseconds
665 * is outside the int64_t range.
666 */
667 clock_value->ns_from_epoch_overflows = true;
668 goto end;
669 }
670
671 s_ns = (int64_t) u_ns;
672 BT_ASSERT(s_ns >= 0);
673
674 if (clock_class->offset < 0) {
675 if (clock_value->ns_from_epoch >= 0) {
676 /*
677 * Offset in cycles is negative so it must also
678 * be negative once converted to nanoseconds.
679 */
680 s_ns = -s_ns;
681 goto offset_ok;
682 }
683
684 diff = clock_value->ns_from_epoch - INT64_MIN;
685
686 if (s_ns >= diff) {
687 /*
688 * Overflow: current timestamp in nanoseconds
689 * plus the offset in cycles converted to
690 * nanoseconds is outside the int64_t range.
691 */
692 clock_value->ns_from_epoch_overflows = true;
693 goto end;
694 }
695
696 /*
697 * Offset in cycles is negative so it must also be
698 * negative once converted to nanoseconds.
699 */
700 s_ns = -s_ns;
701 } else {
702 if (clock_value->ns_from_epoch <= 0) {
703 goto offset_ok;
704 }
705
706 diff = INT64_MAX - clock_value->ns_from_epoch;
707
708 if (s_ns >= diff) {
709 /*
710 * Overflow: current timestamp in nanoseconds
711 * plus the offset in cycles converted to
712 * nanoseconds is outside the int64_t range.
713 */
714 clock_value->ns_from_epoch_overflows = true;
715 goto end;
716 }
717 }
718
719 offset_ok:
720 clock_value->ns_from_epoch += s_ns;
721
722 /* Add clock value (cycles) */
723 u_ns = ns_from_value(clock_class->frequency, clock_value->value);
724
725 if (u_ns == -1ULL || u_ns >= INT64_MAX) {
726 /*
727 * Overflow: value converted to nanoseconds is outside
728 * the int64_t range.
729 */
730 clock_value->ns_from_epoch_overflows = true;
731 goto end;
732 }
733
734 s_ns = (int64_t) u_ns;
735 BT_ASSERT(s_ns >= 0);
736
737 /* Clock value (cycles) is always positive */
738 if (clock_value->ns_from_epoch <= 0) {
739 goto value_ok;
740 }
741
742 diff = INT64_MAX - clock_value->ns_from_epoch;
743
744 if (s_ns >= diff) {
745 /*
746 * Overflow: current timestamp in nanoseconds plus the
747 * clock value converted to nanoseconds is outside the
748 * int64_t range.
749 */
750 clock_value->ns_from_epoch_overflows = true;
751 goto end;
752 }
753
754 value_ok:
755 clock_value->ns_from_epoch += s_ns;
756
757 end:
758 if (clock_value->ns_from_epoch_overflows) {
759 clock_value->ns_from_epoch = 0;
760 }
761 }
762
763 struct bt_clock_value *bt_clock_value_create(
764 struct bt_clock_class *clock_class, uint64_t value)
765 {
766 struct bt_clock_value *ret = NULL;
767
768 BT_LOGD("Creating clock value object: clock-class-addr=%p, "
769 "clock-class-name=\"%s\", value=%" PRIu64, clock_class,
770 bt_clock_class_get_name(clock_class), value);
771
772 if (!clock_class) {
773 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
774 goto end;
775 }
776
777 ret = g_new0(struct bt_clock_value, 1);
778 if (!ret) {
779 BT_LOGE_STR("Failed to allocate one clock value.");
780 goto end;
781 }
782
783 bt_object_init(ret, bt_clock_value_destroy);
784 ret->clock_class = bt_get(clock_class);
785 ret->value = value;
786 set_ns_from_epoch(ret);
787 bt_clock_class_freeze(clock_class);
788 BT_LOGD("Created clock value object: clock-value-addr=%p, "
789 "clock-class-addr=%p, clock-class-name=\"%s\", "
790 "ns-from-epoch=%" PRId64 ", ns-from-epoch-overflows=%d",
791 ret, clock_class, bt_clock_class_get_name(clock_class),
792 ret->ns_from_epoch, ret->ns_from_epoch_overflows);
793
794 end:
795 return ret;
796 }
797
798 int bt_clock_value_get_value(
799 struct bt_clock_value *clock_value, uint64_t *raw_value)
800 {
801 int ret = 0;
802
803 if (!clock_value || !raw_value) {
804 BT_LOGW("Invalid parameter: clock value or raw value is NULL: "
805 "clock-value-addr=%p, raw-value-addr=%p",
806 clock_value, raw_value);
807 ret = -1;
808 goto end;
809 }
810
811 *raw_value = clock_value->value;
812 end:
813 return ret;
814 }
815
816 int bt_clock_value_get_value_ns_from_epoch(struct bt_clock_value *value,
817 int64_t *ret_value_ns)
818 {
819 int ret = 0;
820
821 if (!value || !ret_value_ns) {
822 BT_LOGW("Invalid parameter: clock value or return value pointer is NULL: "
823 "clock-value-addr=%p, ret-value-addr=%p",
824 value, ret_value_ns);
825 ret = -1;
826 goto end;
827 }
828
829 if (value->ns_from_epoch_overflows) {
830 BT_LOGW("Clock value converted to nanoseconds from Epoch overflows the signed 64-bit integer range: "
831 "clock-value-addr=%p, "
832 "clock-class-offset-s=%" PRId64 ", "
833 "clock-class-offset-cycles=%" PRId64 ", "
834 "value=%" PRIu64,
835 value, value->clock_class->offset_s,
836 value->clock_class->offset,
837 value->value);
838 ret = -1;
839 goto end;
840 }
841
842 *ret_value_ns = value->ns_from_epoch;
843
844 end:
845 return ret;
846 }
847
848 struct bt_clock_class *bt_clock_value_get_class(
849 struct bt_clock_value *clock_value)
850 {
851 struct bt_clock_class *clock_class = NULL;
852
853 if (!clock_value) {
854 BT_LOGW_STR("Invalid parameter: clock value is NULL.");
855 goto end;
856 }
857
858 clock_class = bt_get(clock_value->clock_class);
859
860 end:
861 return clock_class;
862 }
863
864 BT_HIDDEN
865 int bt_clock_class_compare(struct bt_clock_class *clock_class_a,
866 struct bt_clock_class *clock_class_b)
867 {
868 int ret = 1;
869 BT_ASSERT(clock_class_a);
870 BT_ASSERT(clock_class_b);
871
872 /* Name */
873 if (strcmp(clock_class_a->name->str, clock_class_b->name->str) != 0) {
874 BT_LOGV("Clock classes differ: different names: "
875 "cc-a-name=\"%s\", cc-b-name=\"%s\"",
876 clock_class_a->name->str,
877 clock_class_b->name->str);
878 goto end;
879 }
880
881 /* Description */
882 if (clock_class_a->description) {
883 if (!clock_class_b->description) {
884 BT_LOGV_STR("Clock classes differ: clock class A has a "
885 "description, but clock class B does not.");
886 goto end;
887 }
888
889 if (strcmp(clock_class_a->name->str, clock_class_b->name->str)
890 != 0) {
891 BT_LOGV("Clock classes differ: different descriptions: "
892 "cc-a-descr=\"%s\", cc-b-descr=\"%s\"",
893 clock_class_a->description->str,
894 clock_class_b->description->str);
895 goto end;
896 }
897 } else {
898 if (clock_class_b->description) {
899 BT_LOGV_STR("Clock classes differ: clock class A has "
900 "no description, but clock class B has one.");
901 goto end;
902 }
903 }
904
905 /* Frequency */
906 if (clock_class_a->frequency != clock_class_b->frequency) {
907 BT_LOGV("Clock classes differ: different frequencies: "
908 "cc-a-freq=%" PRIu64 ", cc-b-freq=%" PRIu64,
909 clock_class_a->frequency,
910 clock_class_b->frequency);
911 goto end;
912 }
913
914 /* Precision */
915 if (clock_class_a->precision != clock_class_b->precision) {
916 BT_LOGV("Clock classes differ: different precisions: "
917 "cc-a-freq=%" PRIu64 ", cc-b-freq=%" PRIu64,
918 clock_class_a->precision,
919 clock_class_b->precision);
920 goto end;
921 }
922
923 /* Offset (seconds) */
924 if (clock_class_a->offset_s != clock_class_b->offset_s) {
925 BT_LOGV("Clock classes differ: different offsets (seconds): "
926 "cc-a-offset-s=%" PRId64 ", cc-b-offset-s=%" PRId64,
927 clock_class_a->offset_s,
928 clock_class_b->offset_s);
929 goto end;
930 }
931
932 /* Offset (cycles) */
933 if (clock_class_a->offset != clock_class_b->offset) {
934 BT_LOGV("Clock classes differ: different offsets (cycles): "
935 "cc-a-offset-s=%" PRId64 ", cc-b-offset-s=%" PRId64,
936 clock_class_a->offset,
937 clock_class_b->offset);
938 goto end;
939 }
940
941 /* UUIDs */
942 if (clock_class_a->uuid_set) {
943 if (!clock_class_b->uuid_set) {
944 BT_LOGV_STR("Clock classes differ: clock class A has a "
945 "UUID, but clock class B does not.");
946 goto end;
947 }
948
949 if (memcmp(clock_class_a->uuid, clock_class_b->uuid,
950 BABELTRACE_UUID_LEN) != 0) {
951 BT_LOGV("Clock classes differ: different UUIDs: "
952 "cc-a-uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\", "
953 "cc-b-uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
954 (unsigned int) clock_class_a->uuid[0],
955 (unsigned int) clock_class_a->uuid[1],
956 (unsigned int) clock_class_a->uuid[2],
957 (unsigned int) clock_class_a->uuid[3],
958 (unsigned int) clock_class_a->uuid[4],
959 (unsigned int) clock_class_a->uuid[5],
960 (unsigned int) clock_class_a->uuid[6],
961 (unsigned int) clock_class_a->uuid[7],
962 (unsigned int) clock_class_a->uuid[8],
963 (unsigned int) clock_class_a->uuid[9],
964 (unsigned int) clock_class_a->uuid[10],
965 (unsigned int) clock_class_a->uuid[11],
966 (unsigned int) clock_class_a->uuid[12],
967 (unsigned int) clock_class_a->uuid[13],
968 (unsigned int) clock_class_a->uuid[14],
969 (unsigned int) clock_class_a->uuid[15],
970 (unsigned int) clock_class_b->uuid[0],
971 (unsigned int) clock_class_b->uuid[1],
972 (unsigned int) clock_class_b->uuid[2],
973 (unsigned int) clock_class_b->uuid[3],
974 (unsigned int) clock_class_b->uuid[4],
975 (unsigned int) clock_class_b->uuid[5],
976 (unsigned int) clock_class_b->uuid[6],
977 (unsigned int) clock_class_b->uuid[7],
978 (unsigned int) clock_class_b->uuid[8],
979 (unsigned int) clock_class_b->uuid[9],
980 (unsigned int) clock_class_b->uuid[10],
981 (unsigned int) clock_class_b->uuid[11],
982 (unsigned int) clock_class_b->uuid[12],
983 (unsigned int) clock_class_b->uuid[13],
984 (unsigned int) clock_class_b->uuid[14],
985 (unsigned int) clock_class_b->uuid[15]);
986 goto end;
987 }
988 } else {
989 if (clock_class_b->uuid_set) {
990 BT_LOGV_STR("Clock classes differ: clock class A has "
991 "no UUID, but clock class B has one.");
992 goto end;
993 }
994 }
995
996 /* Absolute */
997 if (!!clock_class_a->absolute != !!clock_class_b->absolute) {
998 BT_LOGV("Clock classes differ: one is absolute, the other "
999 "is not: cc-a-is-absolute=%d, cc-b-is-absolute=%d",
1000 !!clock_class_a->absolute,
1001 !!clock_class_b->absolute);
1002 goto end;
1003 }
1004
1005 /* Equal */
1006 ret = 0;
1007
1008 end:
1009 return ret;
1010 }
This page took 0.048495 seconds and 5 git commands to generate.