tests: remove `check` targets in subdirectories
[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>
654c1444 34#include <babeltrace/ctf-ir/utils.h>
83509119 35#include <babeltrace/ref.h>
3d9990ac 36#include <babeltrace/compiler-internal.h>
c55a9f58 37#include <babeltrace/types.h>
ee389f01 38#include <babeltrace/compat/string-internal.h>
273b65be 39#include <inttypes.h>
0f5e83e5 40#include <babeltrace/object-internal.h>
5134570b 41
273b65be 42static
ac0c6bdd 43void bt_ctf_clock_class_destroy(struct bt_object *obj);
273b65be 44
4c426c17 45BT_HIDDEN
c55a9f58 46bt_bool bt_ctf_clock_class_is_valid(struct bt_ctf_clock_class *clock_class)
c06116f3 47{
ac0c6bdd 48 return clock_class && clock_class->name;
c06116f3
PP
49}
50
ac0c6bdd 51int bt_ctf_clock_class_set_name(struct bt_ctf_clock_class *clock_class,
4c426c17
JG
52 const char *name)
53{
54 int ret = 0;
273b65be 55
5134570b
PP
56 if (!clock_class) {
57 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
58 ret = -1;
59 goto end;
60 }
61
62 if (clock_class->frozen) {
2cf0acd7
PP
63 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
64 clock_class, bt_ctf_clock_class_get_name(clock_class));
c06116f3
PP
65 ret = -1;
66 goto end;
67 }
68
654c1444 69 if (bt_ctf_validate_identifier(name)) {
5134570b 70 BT_LOGE("Clock class's name is not a valid CTF identifier: "
2cf0acd7 71 "addr=%p, name=\"%s\"",
5134570b 72 clock_class, name);
4c426c17
JG
73 ret = -1;
74 goto end;
273b65be
JG
75 }
76
ac0c6bdd
PP
77 if (clock_class->name) {
78 g_string_assign(clock_class->name, name);
e1ae7645 79 } else {
ac0c6bdd
PP
80 clock_class->name = g_string_new(name);
81 if (!clock_class->name) {
5134570b 82 BT_LOGE_STR("Failed to allocate a GString.");
e1ae7645
JG
83 ret = -1;
84 goto end;
85 }
273b65be
JG
86 }
87
2cf0acd7 88 BT_LOGV("Set clock class's name: addr=%p, name=\"%s\"",
5134570b
PP
89 clock_class, name);
90
4c426c17
JG
91end:
92 return ret;
93}
94
f3534905
PP
95static
96bool validate_freq(struct bt_ctf_clock_class *clock_class,
97 const char *name, uint64_t freq)
98{
99 bool is_valid = true;
100
101 if (freq == -1ULL || freq == 0) {
102 BT_LOGW("Invalid parameter: frequency is invalid: "
103 "addr=%p, name=\"%s\", freq=%" PRIu64,
104 clock_class, name, freq);
105 is_valid = false;
106 goto end;
107 }
108
109end:
110 return is_valid;
111}
112
113struct bt_ctf_clock_class *bt_ctf_clock_class_create(const char *name,
114 uint64_t freq)
4c426c17
JG
115{
116 int ret;
f3534905 117 struct bt_ctf_clock_class *clock_class = NULL;
4c426c17 118
5134570b
PP
119 BT_LOGD("Creating default clock class object: name=\"%s\"",
120 name);
f3534905
PP
121
122 if (!validate_freq(NULL, name, freq)) {
123 /* validate_freq() logs errors */
124 goto error;
125 }
126
5134570b 127 clock_class = g_new0(struct bt_ctf_clock_class, 1);
ac0c6bdd 128 if (!clock_class) {
5134570b 129 BT_LOGE_STR("Failed to allocate one clock class.");
4c426c17
JG
130 goto error;
131 }
132
ac0c6bdd 133 clock_class->precision = 1;
f3534905 134 clock_class->frequency = freq;
ac0c6bdd 135 bt_object_init(clock_class, bt_ctf_clock_class_destroy);
85380e99
JG
136
137 if (name) {
ac0c6bdd 138 ret = bt_ctf_clock_class_set_name(clock_class, name);
85380e99 139 if (ret) {
5134570b 140 BT_LOGE("Cannot set clock class's name: "
2cf0acd7 141 "addr=%p, name=\"%s\"",
5134570b 142 clock_class, name);
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
ac0c6bdd 155const char *bt_ctf_clock_class_get_name(struct bt_ctf_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
ac0c6bdd
PP
172const char *bt_ctf_clock_class_get_description(
173 struct bt_ctf_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
ac0c6bdd
PP
189int bt_ctf_clock_class_set_description(struct bt_ctf_clock_class *clock_class,
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
PP
196 "clock-class-addr=%p, name=\"%s\", desc-addr=%p",
197 clock_class, bt_ctf_clock_class_get_name(clock_class),
198 desc);
5134570b
PP
199 ret = -1;
200 goto end;
201 }
202
203 if (clock_class->frozen) {
2cf0acd7
PP
204 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
205 clock_class, bt_ctf_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\"",
214 clock_class, bt_ctf_clock_class_get_name(clock_class), desc);
273b65be
JG
215end:
216 return ret;
217}
218
ac0c6bdd
PP
219uint64_t bt_ctf_clock_class_get_frequency(
220 struct bt_ctf_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
ac0c6bdd
PP
234int bt_ctf_clock_class_set_frequency(struct bt_ctf_clock_class *clock_class,
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
PP
241 "addr=%p, name=\"%s\"",
242 clock_class, bt_ctf_clock_class_get_name(clock_class));
5134570b
PP
243 ret = -1;
244 goto end;
245 }
246
f3534905
PP
247 if (!validate_freq(clock_class, bt_ctf_clock_class_get_name(clock_class),
248 freq)) {
249 /* validate_freq() logs errors */
250 goto end;
251 }
252
5134570b 253 if (clock_class->frozen) {
2cf0acd7
PP
254 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
255 clock_class, bt_ctf_clock_class_get_name(clock_class));
273b65be
JG
256 ret = -1;
257 goto end;
258 }
259
ac0c6bdd 260 clock_class->frequency = freq;
2cf0acd7
PP
261 BT_LOGV("Set clock class's frequency: addr=%p, name=\"%s\", freq=%" PRIu64,
262 clock_class, bt_ctf_clock_class_get_name(clock_class), freq);
273b65be
JG
263end:
264 return ret;
265}
266
ac0c6bdd 267uint64_t bt_ctf_clock_class_get_precision(struct bt_ctf_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
ac0c6bdd
PP
281int bt_ctf_clock_class_set_precision(struct bt_ctf_clock_class *clock_class,
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
PP
288 "addr=%p, name=\"%s\", precision=%" PRIu64,
289 clock_class, bt_ctf_clock_class_get_name(clock_class),
290 precision);
5134570b
PP
291 ret = -1;
292 goto end;
293 }
294
295 if (clock_class->frozen) {
2cf0acd7
PP
296 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
297 clock_class, bt_ctf_clock_class_get_name(clock_class));
273b65be
JG
298 ret = -1;
299 goto end;
300 }
301
ac0c6bdd 302 clock_class->precision = precision;
2cf0acd7
PP
303 BT_LOGV("Set clock class's precision: addr=%p, name=\"%s\", precision=%" PRIu64,
304 clock_class, bt_ctf_clock_class_get_name(clock_class),
305 precision);
273b65be
JG
306end:
307 return ret;
308}
309
ac0c6bdd
PP
310int bt_ctf_clock_class_get_offset_s(struct bt_ctf_clock_class *clock_class,
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
PP
317 "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
318 clock_class, bt_ctf_clock_class_get_name(clock_class),
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
ac0c6bdd
PP
329int bt_ctf_clock_class_set_offset_s(struct bt_ctf_clock_class *clock_class,
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
PP
341 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
342 clock_class, bt_ctf_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,
350 clock_class, bt_ctf_clock_class_get_name(clock_class),
351 offset_s);
273b65be
JG
352end:
353 return ret;
354}
355
ac0c6bdd
PP
356int bt_ctf_clock_class_get_offset_cycles(struct bt_ctf_clock_class *clock_class,
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
PP
363 "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
364 clock_class, bt_ctf_clock_class_get_name(clock_class),
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
ac0c6bdd
PP
375int bt_ctf_clock_class_set_offset_cycles(struct bt_ctf_clock_class *clock_class,
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
PP
387 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
388 clock_class, bt_ctf_clock_class_get_name(clock_class));
273b65be
JG
389 ret = -1;
390 goto end;
391 }
392
ac0c6bdd 393 clock_class->offset = offset;
2cf0acd7
PP
394 BT_LOGV("Set clock class's offset (cycles): addr=%p, name=\"%s\", offset-cycles=%" PRId64,
395 clock_class, bt_ctf_clock_class_get_name(clock_class), offset);
273b65be
JG
396end:
397 return ret;
398}
399
a2b94977 400bt_bool bt_ctf_clock_class_is_absolute(struct bt_ctf_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
ac0c6bdd 414int bt_ctf_clock_class_set_is_absolute(struct bt_ctf_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
PP
426 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
427 clock_class, bt_ctf_clock_class_get_name(clock_class));
273b65be
JG
428 ret = -1;
429 goto end;
430 }
431
ac0c6bdd 432 clock_class->absolute = !!is_absolute;
2cf0acd7
PP
433 BT_LOGV("Set clock class's absolute flag: addr=%p, name=\"%s\", is-absolute=%d",
434 clock_class, bt_ctf_clock_class_get_name(clock_class),
435 is_absolute);
273b65be
JG
436end:
437 return ret;
438}
439
ac0c6bdd
PP
440const unsigned char *bt_ctf_clock_class_get_uuid(
441 struct bt_ctf_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
PP
452 BT_LOGV("Clock class's UUID is not set: addr=%p, name=\"%s\"",
453 clock_class, bt_ctf_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
ac0c6bdd
PP
463int bt_ctf_clock_class_set_uuid(struct bt_ctf_clock_class *clock_class,
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
PP
470 "clock-class-addr=%p, name=\"%s\", uuid-addr=%p",
471 clock_class, bt_ctf_clock_class_get_name(clock_class),
472 uuid);
5134570b
PP
473 ret = -1;
474 goto end;
475 }
476
477 if (clock_class->frozen) {
2cf0acd7
PP
478 BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
479 clock_class, bt_ctf_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\"",
2cf0acd7 488 clock_class, bt_ctf_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
ac0c6bdd 530void bt_ctf_clock_class_freeze(struct bt_ctf_clock_class *clock_class)
273b65be 531{
ac0c6bdd 532 if (!clock_class) {
5134570b 533 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
273b65be
JG
534 return;
535 }
536
5134570b 537 if (!clock_class->frozen) {
2cf0acd7
PP
538 BT_LOGD("Freezing clock class: addr=%p, name=\"%s\"",
539 clock_class, bt_ctf_clock_class_get_name(clock_class));
5134570b
PP
540 clock_class->frozen = 1;
541 }
273b65be
JG
542}
543
544BT_HIDDEN
ac0c6bdd 545void bt_ctf_clock_class_serialize(struct bt_ctf_clock_class *clock_class,
273b65be
JG
546 struct metadata_context *context)
547{
548 unsigned char *uuid;
549
5134570b 550 BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, "
2cf0acd7
PP
551 "name=\"%s\", metadata-context-addr=%p", clock_class,
552 bt_ctf_clock_class_get_name(clock_class), context);
5134570b 553
ac0c6bdd 554 if (!clock_class || !context) {
5134570b 555 BT_LOGW("Invalid parameter: clock class or metadata context is NULL: "
2cf0acd7
PP
556 "clock-class-addr=%p, name=\"%s\", metadata-context-addr=%p",
557 clock_class, bt_ctf_clock_class_get_name(clock_class),
558 context);
273b65be
JG
559 return;
560 }
561
ac0c6bdd 562 uuid = clock_class->uuid;
273b65be
JG
563 g_string_append(context->string, "clock {\n");
564 g_string_append_printf(context->string, "\tname = %s;\n",
ac0c6bdd 565 clock_class->name->str);
ce57dd3c
PP
566
567 if (clock_class->uuid_set) {
568 g_string_append_printf(context->string,
569 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
570 uuid[0], uuid[1], uuid[2], uuid[3],
571 uuid[4], uuid[5], uuid[6], uuid[7],
572 uuid[8], uuid[9], uuid[10], uuid[11],
573 uuid[12], uuid[13], uuid[14], uuid[15]);
574 }
575
ac0c6bdd 576 if (clock_class->description) {
273b65be 577 g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
ac0c6bdd 578 clock_class->description->str);
273b65be
JG
579 }
580
581 g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
ac0c6bdd 582 clock_class->frequency);
273b65be 583 g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
ac0c6bdd 584 clock_class->precision);
273b65be 585 g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
ac0c6bdd 586 clock_class->offset_s);
273b65be 587 g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
ac0c6bdd 588 clock_class->offset);
273b65be 589 g_string_append_printf(context->string, "\tabsolute = %s;\n",
115d6070 590 clock_class->absolute ? "true" : "false");
273b65be
JG
591 g_string_append(context->string, "};\n\n");
592}
593
273b65be 594static
ac0c6bdd 595void bt_ctf_clock_class_destroy(struct bt_object *obj)
273b65be 596{
ac0c6bdd 597 struct bt_ctf_clock_class *clock_class;
273b65be 598
ac0c6bdd 599 clock_class = container_of(obj, struct bt_ctf_clock_class, base);
2cf0acd7
PP
600 BT_LOGD("Destroying clock class: addr=%p, name=\"%s\"",
601 obj, bt_ctf_clock_class_get_name(clock_class));
ac0c6bdd
PP
602 if (clock_class->name) {
603 g_string_free(clock_class->name, TRUE);
273b65be 604 }
ac0c6bdd
PP
605 if (clock_class->description) {
606 g_string_free(clock_class->description, TRUE);
273b65be
JG
607 }
608
ac0c6bdd 609 g_free(clock_class);
273b65be 610}
4ef18cab 611
61ec14e6
JG
612static
613void bt_ctf_clock_value_destroy(struct bt_object *obj)
614{
615 struct bt_ctf_clock_value *value;
616
617 if (!obj) {
618 return;
619 }
620
621 value = container_of(obj, struct bt_ctf_clock_value, base);
2cf0acd7
PP
622 BT_LOGD("Destroying clock value: addr=%p, clock-class-addr=%p, "
623 "clock-class-name=\"%s\"", obj, value->clock_class,
624 bt_ctf_clock_class_get_name(value->clock_class));
61ec14e6
JG
625 bt_put(value->clock_class);
626 g_free(value);
627}
628
036a7cac
PP
629static
630void set_ns_from_epoch(struct bt_ctf_clock_value *clock_value)
631{
632 struct bt_ctf_clock_class *clock_class = clock_value->clock_class;
633 int64_t diff;
634 int64_t s_ns;
635 uint64_t u_ns;
636 uint64_t cycles;
637
638 /* Initialize nanosecond timestamp to clock's offset in seconds */
639 if (clock_class->offset_s <= (INT64_MIN / 1000000000) ||
640 clock_class->offset_s >= (INT64_MAX / 1000000000)) {
641 /*
642 * Overflow: offset in seconds converted to nanoseconds
643 * is outside the int64_t range.
644 */
645 clock_value->ns_from_epoch_overflows = true;
646 goto end;
647 }
648
649 clock_value->ns_from_epoch = clock_class->offset_s * (int64_t) 1000000000;
650
651 /* Add offset in cycles */
652 if (clock_class->offset < 0) {
653 cycles = (uint64_t) (-clock_class->offset);
654 } else {
655 cycles = (uint64_t) clock_class->offset;
656 }
657
658 u_ns = ns_from_value(clock_class->frequency, cycles);
659
660 if (u_ns == -1ULL || u_ns >= INT64_MAX) {
661 /*
662 * Overflow: offset in cycles converted to nanoseconds
663 * is outside the int64_t range.
664 */
665 clock_value->ns_from_epoch_overflows = true;
666 goto end;
667 }
668
669 s_ns = (int64_t) u_ns;
670 assert(s_ns >= 0);
671
672 if (clock_class->offset < 0) {
673 if (clock_value->ns_from_epoch >= 0) {
674 /*
675 * Offset in cycles is negative so it must also
676 * be negative once converted to nanoseconds.
677 */
678 s_ns = -s_ns;
679 goto offset_ok;
680 }
681
682 diff = clock_value->ns_from_epoch - INT64_MIN;
683
684 if (s_ns >= diff) {
685 /*
686 * Overflow: current timestamp in nanoseconds
687 * plus the offset in cycles converted to
688 * nanoseconds is outside the int64_t range.
689 */
690 clock_value->ns_from_epoch_overflows = true;
691 goto end;
692 }
693
694 /*
695 * Offset in cycles is negative so it must also be
696 * negative once converted to nanoseconds.
697 */
698 s_ns = -s_ns;
699 } else {
700 if (clock_value->ns_from_epoch <= 0) {
701 goto offset_ok;
702 }
703
704 diff = INT64_MAX - clock_value->ns_from_epoch;
705
706 if (s_ns >= diff) {
707 /*
708 * Overflow: current timestamp in nanoseconds
709 * plus the offset in cycles converted to
710 * nanoseconds is outside the int64_t range.
711 */
712 clock_value->ns_from_epoch_overflows = true;
713 goto end;
714 }
715 }
716
717offset_ok:
718 clock_value->ns_from_epoch += s_ns;
719
720 /* Add clock value (cycles) */
721 u_ns = ns_from_value(clock_class->frequency, clock_value->value);
722
723 if (u_ns == -1ULL || u_ns >= INT64_MAX) {
724 /*
725 * Overflow: value converted to nanoseconds is outside
726 * the int64_t range.
727 */
728 clock_value->ns_from_epoch_overflows = true;
729 goto end;
730 }
731
732 s_ns = (int64_t) u_ns;
733 assert(s_ns >= 0);
734
735 /* Clock value (cycles) is always positive */
736 if (clock_value->ns_from_epoch <= 0) {
737 goto value_ok;
738 }
739
740 diff = INT64_MAX - clock_value->ns_from_epoch;
741
742 if (s_ns >= diff) {
743 /*
744 * Overflow: current timestamp in nanoseconds plus the
745 * clock value converted to nanoseconds is outside the
746 * int64_t range.
747 */
748 clock_value->ns_from_epoch_overflows = true;
749 goto end;
750 }
751
752value_ok:
753 clock_value->ns_from_epoch += s_ns;
754
755end:
756 if (clock_value->ns_from_epoch_overflows) {
757 clock_value->ns_from_epoch = 0;
758 }
759}
760
61ec14e6 761struct bt_ctf_clock_value *bt_ctf_clock_value_create(
ac0c6bdd 762 struct bt_ctf_clock_class *clock_class, uint64_t value)
4ef18cab 763{
61ec14e6 764 struct bt_ctf_clock_value *ret = NULL;
4ef18cab 765
5134570b 766 BT_LOGD("Creating clock value object: clock-class-addr=%p, "
2cf0acd7
PP
767 "clock-class-name=\"%s\", value=%" PRIu64, clock_class,
768 bt_ctf_clock_class_get_name(clock_class), value);
5134570b 769
ac0c6bdd 770 if (!clock_class) {
5134570b 771 BT_LOGW_STR("Invalid parameter: clock class is NULL.");
4ef18cab
PP
772 goto end;
773 }
774
61ec14e6
JG
775 ret = g_new0(struct bt_ctf_clock_value, 1);
776 if (!ret) {
5134570b 777 BT_LOGE_STR("Failed to allocate one clock value.");
61ec14e6
JG
778 goto end;
779 }
780
781 bt_object_init(ret, bt_ctf_clock_value_destroy);
ac0c6bdd 782 ret->clock_class = bt_get(clock_class);
61ec14e6 783 ret->value = value;
036a7cac 784 set_ns_from_epoch(ret);
0b4b8df9 785 bt_ctf_clock_class_freeze(clock_class);
2cf0acd7 786 BT_LOGD("Created clock value object: clock-value-addr=%p, "
036a7cac
PP
787 "clock-class-addr=%p, clock-class-name=\"%s\", "
788 "ns-from-epoch=%" PRId64 ", ns-from-epoch-overflows=%d",
789 ret, clock_class, bt_ctf_clock_class_get_name(clock_class),
790 ret->ns_from_epoch, ret->ns_from_epoch_overflows);
791
61ec14e6
JG
792end:
793 return ret;
794}
4ef18cab 795
61ec14e6
JG
796int bt_ctf_clock_value_get_value(
797 struct bt_ctf_clock_value *clock_value, uint64_t *raw_value)
798{
799 int ret = 0;
4ef18cab 800
61ec14e6 801 if (!clock_value || !raw_value) {
5134570b
PP
802 BT_LOGW("Invalid parameter: clock value or raw value is NULL: "
803 "clock-value-addr=%p, raw-value-addr=%p",
804 clock_value, raw_value);
61ec14e6
JG
805 ret = -1;
806 goto end;
807 }
4ef18cab 808
61ec14e6 809 *raw_value = clock_value->value;
4ef18cab 810end:
61ec14e6
JG
811 return ret;
812}
813
1556a1af 814int bt_ctf_clock_value_get_value_ns_from_epoch(struct bt_ctf_clock_value *value,
61ec14e6
JG
815 int64_t *ret_value_ns)
816{
817 int ret = 0;
61ec14e6
JG
818
819 if (!value || !ret_value_ns) {
5134570b
PP
820 BT_LOGW("Invalid parameter: clock value or return value pointer is NULL: "
821 "clock-value-addr=%p, ret-value-addr=%p",
822 value, ret_value_ns);
61ec14e6
JG
823 ret = -1;
824 goto end;
825 }
826
036a7cac
PP
827 if (value->ns_from_epoch_overflows) {
828 BT_LOGW("Clock value converted to nanoseconds from Epoch overflows the signed 64-bit integer range: "
829 "clock-value-addr=%p, "
830 "clock-class-offset-s=%" PRId64 ", "
831 "clock-class-offset-cycles=%" PRId64 ", "
832 "value=%" PRIu64,
833 value, value->clock_class->offset_s,
834 value->clock_class->offset,
835 value->value);
836 ret = -1;
837 goto end;
838 }
61ec14e6 839
036a7cac 840 *ret_value_ns = value->ns_from_epoch;
61ec14e6 841
61ec14e6
JG
842end:
843 return ret;
4ef18cab 844}
6f57e458
PP
845
846struct bt_ctf_clock_class *bt_ctf_clock_value_get_class(
847 struct bt_ctf_clock_value *clock_value)
848{
849 struct bt_ctf_clock_class *clock_class = NULL;
850
851 if (!clock_value) {
5134570b 852 BT_LOGW_STR("Invalid parameter: clock value is NULL.");
6f57e458
PP
853 goto end;
854 }
855
856 clock_class = bt_get(clock_value->clock_class);
857
858end:
859 return clock_class;
860}
This page took 0.083795 seconds and 4 git commands to generate.