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