ir: add bt_ctf_clock_ns_from_value() utility
[babeltrace.git] / formats / ctf / ir / clock.c
1 /*
2 * clock.c
3 *
4 * Babeltrace CTF IR - Clock
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 #include <babeltrace/ctf-ir/clock-internal.h>
30 #include <babeltrace/ctf-ir/utils.h>
31 #include <babeltrace/ref.h>
32 #include <babeltrace/ctf-writer/writer-internal.h>
33 #include <babeltrace/object-internal.h>
34 #include <babeltrace/compiler.h>
35 #include <inttypes.h>
36
37 static
38 void bt_ctf_clock_destroy(struct bt_object *obj);
39
40 BT_HIDDEN
41 struct bt_ctf_clock *_bt_ctf_clock_create(void)
42 {
43 struct bt_ctf_clock *clock = g_new0(
44 struct bt_ctf_clock, 1);
45
46 if (!clock) {
47 goto end;
48 }
49
50 clock->precision = 1;
51 clock->frequency = 1000000000;
52 bt_object_init(clock, bt_ctf_clock_destroy);
53 end:
54 return clock;
55 }
56
57 BT_HIDDEN
58 int bt_ctf_clock_set_name(struct bt_ctf_clock *clock,
59 const char *name)
60 {
61 int ret = 0;
62
63 if (bt_ctf_validate_identifier(name)) {
64 ret = -1;
65 goto end;
66 }
67
68 if (clock->name) {
69 g_string_assign(clock->name, name);
70 } else {
71 clock->name = g_string_new(name);
72 if (!clock->name) {
73 ret = -1;
74 goto end;
75 }
76 }
77
78 end:
79 return ret;
80 }
81
82 struct bt_ctf_clock *bt_ctf_clock_create(const char *name)
83 {
84 int ret;
85 struct bt_ctf_clock *clock = NULL;
86
87 clock = _bt_ctf_clock_create();
88 if (!clock) {
89 goto error;
90 }
91
92 ret = bt_ctf_clock_set_name(clock, name);
93 if (ret) {
94 goto error;
95 }
96
97 ret = bt_uuid_generate(clock->uuid);
98 if (ret) {
99 goto error;
100 }
101
102 /*
103 * For backward compatibility reasons, a fresh clock can have
104 * a value because it could be added to a trace created by a
105 * CTF writer. As soon as this clock is added to a non-writer
106 * trace, then its value/time functions will be disabled.
107 */
108 clock->has_value = 1;
109 clock->uuid_set = 1;
110 return clock;
111 error:
112 BT_PUT(clock);
113 return clock;
114 }
115
116 const char *bt_ctf_clock_get_name(struct bt_ctf_clock *clock)
117 {
118 const char *ret = NULL;
119
120 if (!clock) {
121 goto end;
122 }
123
124 if (clock->name) {
125 ret = clock->name->str;
126 }
127
128 end:
129 return ret;
130 }
131
132 const char *bt_ctf_clock_get_description(struct bt_ctf_clock *clock)
133 {
134 const char *ret = NULL;
135
136 if (!clock) {
137 goto end;
138 }
139
140 if (clock->description) {
141 ret = clock->description->str;
142 }
143 end:
144 return ret;
145 }
146
147 int bt_ctf_clock_set_description(struct bt_ctf_clock *clock, const char *desc)
148 {
149 int ret = 0;
150
151 if (!clock || !desc || clock->frozen) {
152 ret = -1;
153 goto end;
154 }
155
156 clock->description = g_string_new(desc);
157 ret = clock->description ? 0 : -1;
158 end:
159 return ret;
160 }
161
162 uint64_t bt_ctf_clock_get_frequency(struct bt_ctf_clock *clock)
163 {
164 uint64_t ret = -1ULL;
165
166 if (!clock) {
167 goto end;
168 }
169
170 ret = clock->frequency;
171 end:
172 return ret;
173 }
174
175 int bt_ctf_clock_set_frequency(struct bt_ctf_clock *clock, uint64_t freq)
176 {
177 int ret = 0;
178
179 if (!clock || clock->frozen) {
180 ret = -1;
181 goto end;
182 }
183
184 clock->frequency = freq;
185 end:
186 return ret;
187 }
188
189 uint64_t bt_ctf_clock_get_precision(struct bt_ctf_clock *clock)
190 {
191 uint64_t ret = -1ULL;
192
193 if (!clock) {
194 goto end;
195 }
196
197 ret = clock->precision;
198 end:
199 return ret;
200 }
201
202 int bt_ctf_clock_set_precision(struct bt_ctf_clock *clock, uint64_t precision)
203 {
204 int ret = 0;
205
206 if (!clock || clock->frozen) {
207 ret = -1;
208 goto end;
209 }
210
211 clock->precision = precision;
212 end:
213 return ret;
214 }
215
216 int bt_ctf_clock_get_offset_s(struct bt_ctf_clock *clock, int64_t *offset_s)
217 {
218 int ret = 0;
219
220 if (!clock || !offset_s) {
221 ret = -1;
222 goto end;
223 }
224
225 *offset_s = clock->offset_s;
226 end:
227 return ret;
228 }
229
230 int bt_ctf_clock_set_offset_s(struct bt_ctf_clock *clock, int64_t offset_s)
231 {
232 int ret = 0;
233
234 if (!clock || clock->frozen) {
235 ret = -1;
236 goto end;
237 }
238
239 clock->offset_s = offset_s;
240 end:
241 return ret;
242 }
243
244 int bt_ctf_clock_get_offset(struct bt_ctf_clock *clock, int64_t *offset)
245 {
246 int ret = 0;
247
248 if (!clock || !offset) {
249 ret = -1;
250 goto end;
251 }
252
253 *offset = clock->offset;
254 end:
255 return ret;
256 }
257
258 int bt_ctf_clock_set_offset(struct bt_ctf_clock *clock, int64_t offset)
259 {
260 int ret = 0;
261
262 if (!clock || clock->frozen) {
263 ret = -1;
264 goto end;
265 }
266
267 clock->offset = offset;
268 end:
269 return ret;
270 }
271
272 int bt_ctf_clock_get_is_absolute(struct bt_ctf_clock *clock)
273 {
274 int ret = -1;
275
276 if (!clock) {
277 goto end;
278 }
279
280 ret = clock->absolute;
281 end:
282 return ret;
283 }
284
285 int bt_ctf_clock_set_is_absolute(struct bt_ctf_clock *clock, int is_absolute)
286 {
287 int ret = 0;
288
289 if (!clock || clock->frozen) {
290 ret = -1;
291 goto end;
292 }
293
294 clock->absolute = !!is_absolute;
295 end:
296 return ret;
297 }
298
299 const unsigned char *bt_ctf_clock_get_uuid(struct bt_ctf_clock *clock)
300 {
301 const unsigned char *ret;
302
303 if (!clock || !clock->uuid_set) {
304 ret = NULL;
305 goto end;
306 }
307
308 ret = clock->uuid;
309 end:
310 return ret;
311 }
312
313 int bt_ctf_clock_set_uuid(struct bt_ctf_clock *clock, const unsigned char *uuid)
314 {
315 int ret = 0;
316
317 if (!clock || !uuid || clock->frozen) {
318 ret = -1;
319 goto end;
320 }
321
322 memcpy(clock->uuid, uuid, sizeof(uuid_t));
323 clock->uuid_set = 1;
324 end:
325 return ret;
326 }
327
328 uint64_t ns_from_value(uint64_t frequency, uint64_t value)
329 {
330 uint64_t ns;
331
332 if (frequency == 1000000000) {
333 ns = value;
334 } else {
335 ns = (uint64_t) ((1e9 * (double) value) / (double) frequency);
336 }
337
338 return ns;
339 }
340
341 int bt_ctf_clock_get_time(struct bt_ctf_clock *clock, int64_t *time)
342 {
343 int ret = 0;
344
345 if (!clock || !time) {
346 ret = -1;
347 goto end;
348 }
349
350
351 if (!clock->has_value) {
352 /*
353 * Clock belongs to a non-writer mode trace and thus
354 * this function is disabled.
355 */
356 goto end;
357 }
358
359 *time = (int64_t) ns_from_value(clock->frequency, clock->value);
360
361 end:
362 return ret;
363 }
364
365 int bt_ctf_clock_set_time(struct bt_ctf_clock *clock, int64_t time)
366 {
367 int ret = 0;
368
369 /* Timestamps are strictly monotonic */
370 if (!clock) {
371 ret = -1;
372 goto end;
373 }
374
375
376 if (!clock->has_value) {
377 /*
378 * Clock belongs to a non-writer mode trace and thus
379 * this function is disabled.
380 */
381 ret = -1;
382 goto end;
383 }
384
385 /* Common case where cycles are actually nanoseconds */
386 if (clock->frequency == 1000000000) {
387 clock->value = time;
388 goto end;
389 }
390
391 ret = bt_ctf_clock_set_value(clock,
392 (uint64_t) (((double) time * (double) clock->frequency) / 1e9));
393
394 end:
395 return ret;
396 }
397
398 uint64_t bt_ctf_clock_get_value(struct bt_ctf_clock *clock)
399 {
400 uint64_t ret = -1ULL;
401
402 if (!clock) {
403 goto end;
404 }
405
406 if (!clock->has_value) {
407 /*
408 * Clock belongs to a non-writer mode trace and thus
409 * this function is disabled.
410 */
411 goto end;
412 }
413
414 ret = clock->value;
415 end:
416 return ret;
417 }
418
419 int bt_ctf_clock_set_value(struct bt_ctf_clock *clock, uint64_t value)
420 {
421 int ret = 0;
422
423 if (!clock) {
424 ret = -1;
425 goto end;
426 }
427
428 if (!clock->has_value) {
429 /*
430 * Clock belongs to a non-writer mode trace and thus
431 * this function is disabled.
432 */
433 ret = -1;
434 goto end;
435 }
436
437 /* Timestamps are strictly monotonic */
438 if (value < clock->value) {
439 ret = -1;
440 goto end;
441 }
442
443 clock->value = value;
444 end:
445 return ret;
446 }
447
448 void bt_ctf_clock_get(struct bt_ctf_clock *clock)
449 {
450 bt_get(clock);
451 }
452
453 void bt_ctf_clock_put(struct bt_ctf_clock *clock)
454 {
455 bt_put(clock);
456 }
457
458 BT_HIDDEN
459 void bt_ctf_clock_freeze(struct bt_ctf_clock *clock)
460 {
461 if (!clock) {
462 return;
463 }
464
465 clock->frozen = 1;
466 }
467
468 BT_HIDDEN
469 void bt_ctf_clock_serialize(struct bt_ctf_clock *clock,
470 struct metadata_context *context)
471 {
472 unsigned char *uuid;
473
474 if (!clock || !context) {
475 return;
476 }
477
478 uuid = clock->uuid;
479 g_string_append(context->string, "clock {\n");
480 g_string_append_printf(context->string, "\tname = %s;\n",
481 clock->name->str);
482 g_string_append_printf(context->string,
483 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
484 uuid[0], uuid[1], uuid[2], uuid[3],
485 uuid[4], uuid[5], uuid[6], uuid[7],
486 uuid[8], uuid[9], uuid[10], uuid[11],
487 uuid[12], uuid[13], uuid[14], uuid[15]);
488 if (clock->description) {
489 g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
490 clock->description->str);
491 }
492
493 g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
494 clock->frequency);
495 g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
496 clock->precision);
497 g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
498 clock->offset_s);
499 g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
500 clock->offset);
501 g_string_append_printf(context->string, "\tabsolute = %s;\n",
502 clock->absolute ? "TRUE" : "FALSE");
503 g_string_append(context->string, "};\n\n");
504 }
505
506 static
507 void bt_ctf_clock_destroy(struct bt_object *obj)
508 {
509 struct bt_ctf_clock *clock;
510
511 clock = container_of(obj, struct bt_ctf_clock, base);
512 if (clock->name) {
513 g_string_free(clock->name, TRUE);
514 }
515
516 if (clock->description) {
517 g_string_free(clock->description, TRUE);
518 }
519
520 g_free(clock);
521 }
522
523 int64_t bt_ctf_clock_ns_from_value(struct bt_ctf_clock *clock, uint64_t value)
524 {
525 int64_t ns = -1ULL;
526
527 if (!clock) {
528 goto end;
529 }
530
531 /* Initialize nanosecond timestamp to clock's offset in seconds */
532 ns = clock->offset_s * 1000000000;
533
534 /* Add offset in cycles, converted to nanoseconds */
535 ns += ns_from_value(clock->frequency, clock->offset);
536
537 /* Add given value, converter to nanoseconds */
538 ns += ns_from_value(clock->frequency, value);
539
540 end:
541 return ns;
542 }
This page took 0.063607 seconds and 5 git commands to generate.