9256bc1f26f58ef5cb4f04a8ca9a92d32dc364e7
[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 int64_t value;
369
370 /* Timestamps are strictly monotonic */
371 if (!clock) {
372 ret = -1;
373 goto end;
374 }
375
376
377 if (!clock->has_value) {
378 /*
379 * Clock belongs to a non-writer mode trace and thus
380 * this function is disabled.
381 */
382 ret = -1;
383 goto end;
384 }
385
386 /* Common case where cycles are actually nanoseconds */
387 if (clock->frequency == 1000000000) {
388 value = time;
389 } else {
390 value = (uint64_t) (((double) time *
391 (double) clock->frequency) / 1e9);
392 }
393
394 ret = bt_ctf_clock_set_value(clock, value);
395 end:
396 return ret;
397 }
398
399 uint64_t bt_ctf_clock_get_value(struct bt_ctf_clock *clock)
400 {
401 uint64_t ret = -1ULL;
402
403 if (!clock) {
404 goto end;
405 }
406
407 if (!clock->has_value) {
408 /*
409 * Clock belongs to a non-writer mode trace and thus
410 * this function is disabled.
411 */
412 goto end;
413 }
414
415 ret = clock->value;
416 end:
417 return ret;
418 }
419
420 int bt_ctf_clock_set_value(struct bt_ctf_clock *clock, uint64_t value)
421 {
422 int ret = 0;
423
424 if (!clock) {
425 ret = -1;
426 goto end;
427 }
428
429 if (!clock->has_value) {
430 /*
431 * Clock belongs to a non-writer mode trace and thus
432 * this function is disabled.
433 */
434 ret = -1;
435 goto end;
436 }
437
438 /* Timestamps are strictly monotonic */
439 if (value < clock->value) {
440 ret = -1;
441 goto end;
442 }
443
444 clock->value = value;
445 end:
446 return ret;
447 }
448
449 void bt_ctf_clock_get(struct bt_ctf_clock *clock)
450 {
451 bt_get(clock);
452 }
453
454 void bt_ctf_clock_put(struct bt_ctf_clock *clock)
455 {
456 bt_put(clock);
457 }
458
459 BT_HIDDEN
460 void bt_ctf_clock_freeze(struct bt_ctf_clock *clock)
461 {
462 if (!clock) {
463 return;
464 }
465
466 clock->frozen = 1;
467 }
468
469 BT_HIDDEN
470 void bt_ctf_clock_serialize(struct bt_ctf_clock *clock,
471 struct metadata_context *context)
472 {
473 unsigned char *uuid;
474
475 if (!clock || !context) {
476 return;
477 }
478
479 uuid = clock->uuid;
480 g_string_append(context->string, "clock {\n");
481 g_string_append_printf(context->string, "\tname = %s;\n",
482 clock->name->str);
483 g_string_append_printf(context->string,
484 "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
485 uuid[0], uuid[1], uuid[2], uuid[3],
486 uuid[4], uuid[5], uuid[6], uuid[7],
487 uuid[8], uuid[9], uuid[10], uuid[11],
488 uuid[12], uuid[13], uuid[14], uuid[15]);
489 if (clock->description) {
490 g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
491 clock->description->str);
492 }
493
494 g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n",
495 clock->frequency);
496 g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n",
497 clock->precision);
498 g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n",
499 clock->offset_s);
500 g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
501 clock->offset);
502 g_string_append_printf(context->string, "\tabsolute = %s;\n",
503 clock->absolute ? "TRUE" : "FALSE");
504 g_string_append(context->string, "};\n\n");
505 }
506
507 static
508 void bt_ctf_clock_destroy(struct bt_object *obj)
509 {
510 struct bt_ctf_clock *clock;
511
512 clock = container_of(obj, struct bt_ctf_clock, base);
513 if (clock->name) {
514 g_string_free(clock->name, TRUE);
515 }
516
517 if (clock->description) {
518 g_string_free(clock->description, TRUE);
519 }
520
521 g_free(clock);
522 }
523
524 int64_t bt_ctf_clock_ns_from_value(struct bt_ctf_clock *clock, uint64_t value)
525 {
526 int64_t ns = -1ULL;
527
528 if (!clock) {
529 goto end;
530 }
531
532 /* Initialize nanosecond timestamp to clock's offset in seconds */
533 ns = clock->offset_s * 1000000000;
534
535 /* Add offset in cycles, converted to nanoseconds */
536 ns += ns_from_value(clock->frequency, clock->offset);
537
538 /* Add given value, converter to nanoseconds */
539 ns += ns_from_value(clock->frequency, value);
540
541 end:
542 return ns;
543 }
This page took 0.03875 seconds and 3 git commands to generate.