lib: metadata: transform fast path precond. checks to BT_ASSERT_PRE()
[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)) {
5134570b 72 BT_LOGE("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) {
5134570b 142 BT_LOGE("Cannot set clock class's name: "
2cf0acd7 143 "addr=%p, name=\"%s\"",
5134570b 144 clock_class, name);
85380e99
JG
145 goto error;
146 }
273b65be
JG
147 }
148
2cf0acd7
PP
149 BT_LOGD("Created clock class object: addr=%p, name=\"%s\"",
150 clock_class, name);
ac0c6bdd 151 return clock_class;
273b65be 152error:
ac0c6bdd
PP
153 BT_PUT(clock_class);
154 return clock_class;
87d76bb1
JG
155}
156
50842bdc 157const char *bt_clock_class_get_name(struct bt_clock_class *clock_class)
87d76bb1
JG
158{
159 const char *ret = NULL;
160
ac0c6bdd 161 if (!clock_class) {
5134570b 162 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
87d76bb1
JG
163 goto end;
164 }
165
ac0c6bdd
PP
166 if (clock_class->name) {
167 ret = clock_class->name->str;
87d76bb1
JG
168 }
169
170end:
171 return ret;
172}
173
50842bdc
PP
174const char *bt_clock_class_get_description(
175 struct bt_clock_class *clock_class)
87d76bb1
JG
176{
177 const char *ret = NULL;
178
ac0c6bdd 179 if (!clock_class) {
5134570b 180 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
87d76bb1
JG
181 goto end;
182 }
183
ac0c6bdd
PP
184 if (clock_class->description) {
185 ret = clock_class->description->str;
87d76bb1
JG
186 }
187end:
188 return ret;
273b65be
JG
189}
190
50842bdc 191int bt_clock_class_set_description(struct bt_clock_class *clock_class,
ac0c6bdd 192 const char *desc)
273b65be
JG
193{
194 int ret = 0;
195
5134570b
PP
196 if (!clock_class || !desc) {
197 BT_LOGW("Invalid parameter: clock class or description is NULL: "
2cf0acd7 198 "clock-class-addr=%p, name=\"%s\", desc-addr=%p",
50842bdc 199 clock_class, bt_clock_class_get_name(clock_class),
2cf0acd7 200 desc);
5134570b
PP
201 ret = -1;
202 goto end;
203 }
204
205 if (clock_class->frozen) {
2cf0acd7 206 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
50842bdc 207 clock_class, bt_clock_class_get_name(clock_class));
273b65be
JG
208 ret = -1;
209 goto end;
210 }
211
ac0c6bdd
PP
212 clock_class->description = g_string_new(desc);
213 ret = clock_class->description ? 0 : -1;
2cf0acd7
PP
214 BT_LOGV("Set clock class's description: addr=%p, "
215 "name=\"%s\", desc=\"%s\"",
50842bdc 216 clock_class, bt_clock_class_get_name(clock_class), desc);
273b65be
JG
217end:
218 return ret;
219}
220
50842bdc
PP
221uint64_t bt_clock_class_get_frequency(
222 struct bt_clock_class *clock_class)
87d76bb1
JG
223{
224 uint64_t ret = -1ULL;
225
ac0c6bdd 226 if (!clock_class) {
5134570b 227 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
87d76bb1
JG
228 goto end;
229 }
230
ac0c6bdd 231 ret = clock_class->frequency;
87d76bb1
JG
232end:
233 return ret;
234}
235
50842bdc 236int bt_clock_class_set_frequency(struct bt_clock_class *clock_class,
ac0c6bdd 237 uint64_t freq)
273b65be
JG
238{
239 int ret = 0;
240
f3534905 241 if (!clock_class) {
5134570b 242 BT_LOGW("Invalid parameter: clock class is NULL or frequency is invalid: "
f3534905 243 "addr=%p, name=\"%s\"",
50842bdc 244 clock_class, bt_clock_class_get_name(clock_class));
5134570b
PP
245 ret = -1;
246 goto end;
247 }
248
50842bdc 249 if (!validate_freq(clock_class, bt_clock_class_get_name(clock_class),
f3534905
PP
250 freq)) {
251 /* validate_freq() logs errors */
252 goto end;
253 }
254
5134570b 255 if (clock_class->frozen) {
2cf0acd7 256 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
50842bdc 257 clock_class, bt_clock_class_get_name(clock_class));
273b65be
JG
258 ret = -1;
259 goto end;
260 }
261
ac0c6bdd 262 clock_class->frequency = freq;
2cf0acd7 263 BT_LOGV("Set clock class's frequency: addr=%p, name=\"%s\", freq=%" PRIu64,
50842bdc 264 clock_class, bt_clock_class_get_name(clock_class), freq);
273b65be
JG
265end:
266 return ret;
267}
268
50842bdc 269uint64_t bt_clock_class_get_precision(struct bt_clock_class *clock_class)
87d76bb1
JG
270{
271 uint64_t ret = -1ULL;
272
ac0c6bdd 273 if (!clock_class) {
5134570b 274 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
87d76bb1
JG
275 goto end;
276 }
277
ac0c6bdd 278 ret = clock_class->precision;
87d76bb1
JG
279end:
280 return ret;
281}
282
50842bdc 283int bt_clock_class_set_precision(struct bt_clock_class *clock_class,
ac0c6bdd 284 uint64_t precision)
273b65be
JG
285{
286 int ret = 0;
287
5134570b
PP
288 if (!clock_class || precision == -1ULL) {
289 BT_LOGW("Invalid parameter: clock class is NULL or precision is invalid: "
2cf0acd7 290 "addr=%p, name=\"%s\", precision=%" PRIu64,
50842bdc 291 clock_class, bt_clock_class_get_name(clock_class),
2cf0acd7 292 precision);
5134570b
PP
293 ret = -1;
294 goto end;
295 }
296
297 if (clock_class->frozen) {
2cf0acd7 298 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
50842bdc 299 clock_class, bt_clock_class_get_name(clock_class));
273b65be
JG
300 ret = -1;
301 goto end;
302 }
303
ac0c6bdd 304 clock_class->precision = precision;
2cf0acd7 305 BT_LOGV("Set clock class's precision: addr=%p, name=\"%s\", precision=%" PRIu64,
50842bdc 306 clock_class, bt_clock_class_get_name(clock_class),
2cf0acd7 307 precision);
273b65be
JG
308end:
309 return ret;
310}
311
50842bdc 312int bt_clock_class_get_offset_s(struct bt_clock_class *clock_class,
ac0c6bdd 313 int64_t *offset_s)
87d76bb1 314{
61cf588b 315 int ret = 0;
87d76bb1 316
ac0c6bdd 317 if (!clock_class || !offset_s) {
5134570b 318 BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
2cf0acd7 319 "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
50842bdc 320 clock_class, bt_clock_class_get_name(clock_class),
2cf0acd7 321 offset_s);
61cf588b 322 ret = -1;
87d76bb1
JG
323 goto end;
324 }
325
ac0c6bdd 326 *offset_s = clock_class->offset_s;
87d76bb1
JG
327end:
328 return ret;
329}
330
50842bdc 331int bt_clock_class_set_offset_s(struct bt_clock_class *clock_class,
ac0c6bdd 332 int64_t offset_s)
273b65be
JG
333{
334 int ret = 0;
335
5134570b
PP
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) {
2cf0acd7 343 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
50842bdc 344 clock_class, bt_clock_class_get_name(clock_class));
273b65be
JG
345 ret = -1;
346 goto end;
347 }
348
ac0c6bdd 349 clock_class->offset_s = offset_s;
2cf0acd7
PP
350 BT_LOGV("Set clock class's offset (seconds): "
351 "addr=%p, name=\"%s\", offset-s=%" PRId64,
50842bdc 352 clock_class, bt_clock_class_get_name(clock_class),
2cf0acd7 353 offset_s);
273b65be
JG
354end:
355 return ret;
356}
357
50842bdc 358int bt_clock_class_get_offset_cycles(struct bt_clock_class *clock_class,
ac0c6bdd 359 int64_t *offset)
87d76bb1 360{
61cf588b 361 int ret = 0;
87d76bb1 362
ac0c6bdd 363 if (!clock_class || !offset) {
5134570b 364 BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
2cf0acd7 365 "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
50842bdc 366 clock_class, bt_clock_class_get_name(clock_class),
2cf0acd7 367 offset);
61cf588b 368 ret = -1;
87d76bb1
JG
369 goto end;
370 }
371
ac0c6bdd 372 *offset = clock_class->offset;
87d76bb1
JG
373end:
374 return ret;
375}
376
50842bdc 377int bt_clock_class_set_offset_cycles(struct bt_clock_class *clock_class,
ac0c6bdd 378 int64_t offset)
273b65be
JG
379{
380 int ret = 0;
381
5134570b
PP
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) {
2cf0acd7 389 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
50842bdc 390 clock_class, bt_clock_class_get_name(clock_class));
273b65be
JG
391 ret = -1;
392 goto end;
393 }
394
ac0c6bdd 395 clock_class->offset = offset;
2cf0acd7 396 BT_LOGV("Set clock class's offset (cycles): addr=%p, name=\"%s\", offset-cycles=%" PRId64,
50842bdc 397 clock_class, bt_clock_class_get_name(clock_class), offset);
273b65be
JG
398end:
399 return ret;
400}
401
50842bdc 402bt_bool bt_clock_class_is_absolute(struct bt_clock_class *clock_class)
87d76bb1
JG
403{
404 int ret = -1;
405
ac0c6bdd 406 if (!clock_class) {
5134570b 407 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
87d76bb1
JG
408 goto end;
409 }
410
ac0c6bdd 411 ret = clock_class->absolute;
87d76bb1
JG
412end:
413 return ret;
414}
415
50842bdc 416int bt_clock_class_set_is_absolute(struct bt_clock_class *clock_class,
a2b94977 417 bt_bool is_absolute)
273b65be
JG
418{
419 int ret = 0;
420
5134570b
PP
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) {
2cf0acd7 428 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
50842bdc 429 clock_class, bt_clock_class_get_name(clock_class));
273b65be
JG
430 ret = -1;
431 goto end;
432 }
433
ac0c6bdd 434 clock_class->absolute = !!is_absolute;
2cf0acd7 435 BT_LOGV("Set clock class's absolute flag: addr=%p, name=\"%s\", is-absolute=%d",
50842bdc 436 clock_class, bt_clock_class_get_name(clock_class),
2cf0acd7 437 is_absolute);
273b65be
JG
438end:
439 return ret;
440}
441
50842bdc
PP
442const unsigned char *bt_clock_class_get_uuid(
443 struct bt_clock_class *clock_class)
85b743f4
JG
444{
445 const unsigned char *ret;
446
5134570b
PP
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) {
2cf0acd7 454 BT_LOGV("Clock class's UUID is not set: addr=%p, name=\"%s\"",
50842bdc 455 clock_class, bt_clock_class_get_name(clock_class));
85b743f4
JG
456 ret = NULL;
457 goto end;
458 }
459
ac0c6bdd 460 ret = clock_class->uuid;
85b743f4
JG
461end:
462 return ret;
463}
464
50842bdc 465int bt_clock_class_set_uuid(struct bt_clock_class *clock_class,
ac0c6bdd 466 const unsigned char *uuid)
85b743f4
JG
467{
468 int ret = 0;
469
5134570b
PP
470 if (!clock_class || !uuid) {
471 BT_LOGW("Invalid parameter: clock class or UUID is NULL: "
2cf0acd7 472 "clock-class-addr=%p, name=\"%s\", uuid-addr=%p",
50842bdc 473 clock_class, bt_clock_class_get_name(clock_class),
2cf0acd7 474 uuid);
5134570b
PP
475 ret = -1;
476 goto end;
477 }
478
479 if (clock_class->frozen) {
2cf0acd7 480 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
50842bdc 481 clock_class, bt_clock_class_get_name(clock_class));
85b743f4
JG
482 ret = -1;
483 goto end;
484 }
485
20eee76e 486 memcpy(clock_class->uuid, uuid, BABELTRACE_UUID_LEN);
ac0c6bdd 487 clock_class->uuid_set = 1;
2cf0acd7 488 BT_LOGV("Set clock class's UUID: addr=%p, name=\"%s\", "
5134570b 489 "uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
50842bdc 490 clock_class, bt_clock_class_get_name(clock_class),
5134570b
PP
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]);
85b743f4
JG
507end:
508 return ret;
509}
510
ac0c6bdd 511static uint64_t ns_from_value(uint64_t frequency, uint64_t value)
4ef18cab
PP
512{
513 uint64_t ns;
514
515 if (frequency == 1000000000) {
516 ns = value;
517 } else {
036a7cac
PP
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 }
4ef18cab
PP
526 }
527
528 return ns;
529}
530
273b65be 531BT_HIDDEN
50842bdc 532void bt_clock_class_freeze(struct bt_clock_class *clock_class)
273b65be 533{
ac0c6bdd 534 if (!clock_class) {
5134570b 535 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
273b65be
JG
536 return;
537 }
538
5134570b 539 if (!clock_class->frozen) {
2cf0acd7 540 BT_LOGD("Freezing clock class: addr=%p, name=\"%s\"",
50842bdc 541 clock_class, bt_clock_class_get_name(clock_class));
5134570b
PP
542 clock_class->frozen = 1;
543 }
273b65be
JG
544}
545
546BT_HIDDEN
50842bdc 547void bt_clock_class_serialize(struct bt_clock_class *clock_class,
273b65be
JG
548 struct metadata_context *context)
549{
550 unsigned char *uuid;
551
5134570b 552 BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, "
2cf0acd7 553 "name=\"%s\", metadata-context-addr=%p", clock_class,
50842bdc 554 bt_clock_class_get_name(clock_class), context);
5134570b 555
ac0c6bdd 556 if (!clock_class || !context) {
5134570b 557 BT_LOGW("Invalid parameter: clock class or metadata context is NULL: "
2cf0acd7 558 "clock-class-addr=%p, name=\"%s\", metadata-context-addr=%p",
50842bdc 559 clock_class, bt_clock_class_get_name(clock_class),
2cf0acd7 560 context);
273b65be
JG
561 return;
562 }
563
ac0c6bdd 564 uuid = clock_class->uuid;
273b65be
JG
565 g_string_append(context->string, "clock {\n");
566 g_string_append_printf(context->string, "\tname = %s;\n",
ac0c6bdd 567 clock_class->name->str);
ce57dd3c
PP
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
ac0c6bdd 578 if (clock_class->description) {
273b65be 579 g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
ac0c6bdd 580 clock_class->description->str);
273b65be
JG
581 }
582
583 g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
ac0c6bdd 584 clock_class->frequency);
273b65be 585 g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
ac0c6bdd 586 clock_class->precision);
273b65be 587 g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
ac0c6bdd 588 clock_class->offset_s);
273b65be 589 g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
ac0c6bdd 590 clock_class->offset);
273b65be 591 g_string_append_printf(context->string, "\tabsolute = %s;\n",
115d6070 592 clock_class->absolute ? "true" : "false");
273b65be
JG
593 g_string_append(context->string, "};\n\n");
594}
595
273b65be 596static
50842bdc 597void bt_clock_class_destroy(struct bt_object *obj)
273b65be 598{
50842bdc 599 struct bt_clock_class *clock_class;
273b65be 600
50842bdc 601 clock_class = container_of(obj, struct bt_clock_class, base);
2cf0acd7 602 BT_LOGD("Destroying clock class: addr=%p, name=\"%s\"",
50842bdc 603 obj, bt_clock_class_get_name(clock_class));
ac0c6bdd
PP
604 if (clock_class->name) {
605 g_string_free(clock_class->name, TRUE);
273b65be 606 }
ac0c6bdd
PP
607 if (clock_class->description) {
608 g_string_free(clock_class->description, TRUE);
273b65be
JG
609 }
610
ac0c6bdd 611 g_free(clock_class);
273b65be 612}
4ef18cab 613
61ec14e6 614static
50842bdc 615void bt_clock_value_destroy(struct bt_object *obj)
61ec14e6 616{
50842bdc 617 struct bt_clock_value *value;
61ec14e6
JG
618
619 if (!obj) {
620 return;
621 }
622
50842bdc 623 value = container_of(obj, struct bt_clock_value, base);
2cf0acd7
PP
624 BT_LOGD("Destroying clock value: addr=%p, clock-class-addr=%p, "
625 "clock-class-name=\"%s\"", obj, value->clock_class,
50842bdc 626 bt_clock_class_get_name(value->clock_class));
61ec14e6
JG
627 bt_put(value->clock_class);
628 g_free(value);
629}
630
036a7cac 631static
50842bdc 632void set_ns_from_epoch(struct bt_clock_value *clock_value)
036a7cac 633{
50842bdc 634 struct bt_clock_class *clock_class = clock_value->clock_class;
036a7cac
PP
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;
f6ccaed9 672 BT_ASSERT(s_ns >= 0);
036a7cac
PP
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
719offset_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;
f6ccaed9 735 BT_ASSERT(s_ns >= 0);
036a7cac
PP
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
754value_ok:
755 clock_value->ns_from_epoch += s_ns;
756
757end:
758 if (clock_value->ns_from_epoch_overflows) {
759 clock_value->ns_from_epoch = 0;
760 }
761}
762
50842bdc
PP
763struct bt_clock_value *bt_clock_value_create(
764 struct bt_clock_class *clock_class, uint64_t value)
4ef18cab 765{
50842bdc 766 struct bt_clock_value *ret = NULL;
4ef18cab 767
5134570b 768 BT_LOGD("Creating clock value object: clock-class-addr=%p, "
2cf0acd7 769 "clock-class-name=\"%s\", value=%" PRIu64, clock_class,
50842bdc 770 bt_clock_class_get_name(clock_class), value);
5134570b 771
ac0c6bdd 772 if (!clock_class) {
5134570b 773 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
4ef18cab
PP
774 goto end;
775 }
776
50842bdc 777 ret = g_new0(struct bt_clock_value, 1);
61ec14e6 778 if (!ret) {
5134570b 779 BT_LOGE_STR("Failed to allocate one clock value.");
61ec14e6
JG
780 goto end;
781 }
782
50842bdc 783 bt_object_init(ret, bt_clock_value_destroy);
ac0c6bdd 784 ret->clock_class = bt_get(clock_class);
61ec14e6 785 ret->value = value;
036a7cac 786 set_ns_from_epoch(ret);
50842bdc 787 bt_clock_class_freeze(clock_class);
2cf0acd7 788 BT_LOGD("Created clock value object: clock-value-addr=%p, "
036a7cac
PP
789 "clock-class-addr=%p, clock-class-name=\"%s\", "
790 "ns-from-epoch=%" PRId64 ", ns-from-epoch-overflows=%d",
50842bdc 791 ret, clock_class, bt_clock_class_get_name(clock_class),
036a7cac
PP
792 ret->ns_from_epoch, ret->ns_from_epoch_overflows);
793
61ec14e6
JG
794end:
795 return ret;
796}
4ef18cab 797
50842bdc
PP
798int bt_clock_value_get_value(
799 struct bt_clock_value *clock_value, uint64_t *raw_value)
61ec14e6
JG
800{
801 int ret = 0;
4ef18cab 802
61ec14e6 803 if (!clock_value || !raw_value) {
5134570b
PP
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);
61ec14e6
JG
807 ret = -1;
808 goto end;
809 }
4ef18cab 810
61ec14e6 811 *raw_value = clock_value->value;
4ef18cab 812end:
61ec14e6
JG
813 return ret;
814}
815
50842bdc 816int bt_clock_value_get_value_ns_from_epoch(struct bt_clock_value *value,
61ec14e6
JG
817 int64_t *ret_value_ns)
818{
819 int ret = 0;
61ec14e6
JG
820
821 if (!value || !ret_value_ns) {
5134570b
PP
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);
61ec14e6
JG
825 ret = -1;
826 goto end;
827 }
828
036a7cac
PP
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 }
61ec14e6 841
036a7cac 842 *ret_value_ns = value->ns_from_epoch;
61ec14e6 843
61ec14e6
JG
844end:
845 return ret;
4ef18cab 846}
6f57e458 847
50842bdc
PP
848struct bt_clock_class *bt_clock_value_get_class(
849 struct bt_clock_value *clock_value)
6f57e458 850{
50842bdc 851 struct bt_clock_class *clock_class = NULL;
6f57e458
PP
852
853 if (!clock_value) {
5134570b 854 BT_LOGW_STR("Invalid parameter: clock value is NULL.");
6f57e458
PP
855 goto end;
856 }
857
858 clock_class = bt_get(clock_value->clock_class);
859
860end:
861 return clock_class;
862}
93dda901
PP
863
864BT_HIDDEN
865int bt_clock_class_compare(struct bt_clock_class *clock_class_a,
866 struct bt_clock_class *clock_class_b)
867{
868 int ret = 1;
f6ccaed9
PP
869 BT_ASSERT(clock_class_a);
870 BT_ASSERT(clock_class_b);
93dda901
PP
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
1008end:
1009 return ret;
1010}
This page took 0.092297 seconds and 4 git commands to generate.