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