Commit | Line | Data |
---|---|---|
ac0c6bdd PP |
1 | /* |
2 | * clock.c | |
3 | * | |
4 | * Babeltrace CTF IR - Clock | |
5 | * | |
6 | * Copyright 2013, 2014 Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
7 | * Copyright 2017 Philippe Proulx <pproulx@efficios.com> | |
8 | * | |
9 | * Author: Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
10 | * | |
11 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
12 | * of this software and associated documentation files (the "Software"), to deal | |
13 | * in the Software without restriction, including without limitation the rights | |
14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
15 | * copies of the Software, and to permit persons to whom the Software is | |
16 | * furnished to do so, subject to the following conditions: | |
17 | * | |
18 | * The above copyright notice and this permission notice shall be included in | |
19 | * all copies or substantial portions of the Software. | |
20 | * | |
21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
27 | * SOFTWARE. | |
28 | */ | |
29 | ||
f6ccaed9 PP |
30 | #define BT_LOG_TAG "CTF-WRITER-CLOCK" |
31 | #include <babeltrace/lib-logging-internal.h> | |
32 | ||
ac0c6bdd | 33 | #include <babeltrace/ctf-writer/clock-internal.h> |
3dca2276 | 34 | #include <babeltrace/ctf-writer/writer-internal.h> |
ac0c6bdd PP |
35 | #include <babeltrace/ctf-ir/clock-class.h> |
36 | #include <babeltrace/ctf-ir/clock-class-internal.h> | |
37 | #include <babeltrace/ctf-ir/utils.h> | |
75c3fca1 | 38 | #include <babeltrace/compat/uuid-internal.h> |
ac0c6bdd PP |
39 | #include <babeltrace/ref.h> |
40 | #include <babeltrace/object-internal.h> | |
3d9990ac | 41 | #include <babeltrace/compiler-internal.h> |
f6ccaed9 | 42 | #include <babeltrace/assert-internal.h> |
ac0c6bdd PP |
43 | #include <inttypes.h> |
44 | ||
45 | static | |
46 | void bt_ctf_clock_destroy(struct bt_object *obj); | |
47 | ||
48 | struct bt_ctf_clock *bt_ctf_clock_create(const char *name) | |
49 | { | |
75c3fca1 | 50 | int ret; |
ac0c6bdd | 51 | struct bt_ctf_clock *clock = NULL; |
75c3fca1 | 52 | unsigned char cc_uuid[BABELTRACE_UUID_LEN]; |
ac0c6bdd | 53 | |
f6ccaed9 | 54 | BT_ASSERT_PRE_NON_NULL(name, "Name"); |
ac0c6bdd | 55 | clock = g_new0(struct bt_ctf_clock, 1); |
ac0c6bdd PP |
56 | if (!clock) { |
57 | goto error; | |
58 | } | |
59 | ||
3fea54f6 | 60 | bt_object_init_shared(&clock->base, bt_ctf_clock_destroy); |
ac0c6bdd | 61 | clock->value = 0; |
f3534905 PP |
62 | |
63 | /* Pre-2.0.0 backward compatibility: default frequency is 1 GHz */ | |
3dca2276 | 64 | clock->clock_class = (void *) bt_clock_class_create(name, 1000000000); |
ac0c6bdd PP |
65 | if (!clock->clock_class) { |
66 | goto error; | |
67 | } | |
75c3fca1 PP |
68 | |
69 | /* Automatically set clock class's UUID. */ | |
70 | ret = bt_uuid_generate(cc_uuid); | |
71 | if (ret) { | |
72 | goto error; | |
73 | } | |
74 | ||
3dca2276 PP |
75 | ret = bt_clock_class_set_uuid(BT_TO_COMMON(clock->clock_class), |
76 | cc_uuid); | |
f6ccaed9 | 77 | BT_ASSERT(ret == 0); |
ac0c6bdd PP |
78 | return clock; |
79 | ||
80 | error: | |
81 | BT_PUT(clock); | |
82 | return clock; | |
83 | } | |
84 | ||
85 | const char *bt_ctf_clock_get_name(struct bt_ctf_clock *clock) | |
86 | { | |
f6ccaed9 | 87 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 | 88 | return bt_clock_class_get_name(BT_TO_COMMON(clock->clock_class)); |
ac0c6bdd PP |
89 | } |
90 | ||
91 | const char *bt_ctf_clock_get_description(struct bt_ctf_clock *clock) | |
92 | { | |
f6ccaed9 | 93 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 | 94 | return bt_clock_class_get_description(BT_TO_COMMON(clock->clock_class)); |
ac0c6bdd PP |
95 | } |
96 | ||
97 | int bt_ctf_clock_set_description(struct bt_ctf_clock *clock, const char *desc) | |
98 | { | |
f6ccaed9 | 99 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 PP |
100 | return bt_clock_class_set_description(BT_TO_COMMON(clock->clock_class), |
101 | desc); | |
ac0c6bdd PP |
102 | } |
103 | ||
104 | uint64_t bt_ctf_clock_get_frequency(struct bt_ctf_clock *clock) | |
105 | { | |
f6ccaed9 | 106 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 | 107 | return bt_clock_class_get_frequency(BT_TO_COMMON(clock->clock_class)); |
ac0c6bdd PP |
108 | } |
109 | ||
110 | int bt_ctf_clock_set_frequency(struct bt_ctf_clock *clock, uint64_t freq) | |
111 | { | |
f6ccaed9 | 112 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 PP |
113 | return bt_clock_class_set_frequency(BT_TO_COMMON(clock->clock_class), |
114 | freq); | |
ac0c6bdd PP |
115 | } |
116 | ||
117 | uint64_t bt_ctf_clock_get_precision(struct bt_ctf_clock *clock) | |
118 | { | |
f6ccaed9 | 119 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 | 120 | return bt_clock_class_get_precision(BT_TO_COMMON(clock->clock_class)); |
ac0c6bdd PP |
121 | } |
122 | ||
123 | int bt_ctf_clock_set_precision(struct bt_ctf_clock *clock, uint64_t precision) | |
124 | { | |
f6ccaed9 | 125 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 PP |
126 | return bt_clock_class_set_precision(BT_TO_COMMON(clock->clock_class), |
127 | precision); | |
ac0c6bdd PP |
128 | } |
129 | ||
130 | int bt_ctf_clock_get_offset_s(struct bt_ctf_clock *clock, int64_t *offset_s) | |
131 | { | |
f6ccaed9 | 132 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 PP |
133 | return bt_clock_class_get_offset_s(BT_TO_COMMON(clock->clock_class), |
134 | offset_s); | |
ac0c6bdd PP |
135 | } |
136 | ||
137 | int bt_ctf_clock_set_offset_s(struct bt_ctf_clock *clock, int64_t offset_s) | |
138 | { | |
f6ccaed9 | 139 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 PP |
140 | return bt_clock_class_set_offset_s(BT_TO_COMMON(clock->clock_class), |
141 | offset_s); | |
ac0c6bdd PP |
142 | } |
143 | ||
144 | int bt_ctf_clock_get_offset(struct bt_ctf_clock *clock, int64_t *offset) | |
145 | { | |
f6ccaed9 | 146 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 PP |
147 | return bt_clock_class_get_offset_cycles(BT_TO_COMMON(clock->clock_class), |
148 | offset); | |
ac0c6bdd PP |
149 | } |
150 | ||
151 | int bt_ctf_clock_set_offset(struct bt_ctf_clock *clock, int64_t offset) | |
152 | { | |
f6ccaed9 | 153 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 PP |
154 | return bt_clock_class_set_offset_cycles(BT_TO_COMMON(clock->clock_class), |
155 | offset); | |
ac0c6bdd PP |
156 | } |
157 | ||
158 | int bt_ctf_clock_get_is_absolute(struct bt_ctf_clock *clock) | |
159 | { | |
f6ccaed9 | 160 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 | 161 | return bt_clock_class_is_absolute(BT_TO_COMMON(clock->clock_class)); |
ac0c6bdd PP |
162 | } |
163 | ||
164 | int bt_ctf_clock_set_is_absolute(struct bt_ctf_clock *clock, int is_absolute) | |
165 | { | |
f6ccaed9 | 166 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 PP |
167 | return bt_clock_class_set_is_absolute(BT_TO_COMMON(clock->clock_class), |
168 | is_absolute); | |
ac0c6bdd PP |
169 | } |
170 | ||
171 | const unsigned char *bt_ctf_clock_get_uuid(struct bt_ctf_clock *clock) | |
172 | { | |
f6ccaed9 | 173 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 | 174 | return bt_clock_class_get_uuid(BT_TO_COMMON(clock->clock_class)); |
ac0c6bdd PP |
175 | } |
176 | ||
177 | int bt_ctf_clock_set_uuid(struct bt_ctf_clock *clock, const unsigned char *uuid) | |
178 | { | |
f6ccaed9 | 179 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 | 180 | return bt_clock_class_set_uuid(BT_TO_COMMON(clock->clock_class), uuid); |
ac0c6bdd PP |
181 | } |
182 | ||
183 | int bt_ctf_clock_set_time(struct bt_ctf_clock *clock, int64_t time) | |
184 | { | |
ac0c6bdd | 185 | int64_t value; |
3dca2276 | 186 | struct bt_clock_class *cc; |
ac0c6bdd | 187 | |
f6ccaed9 | 188 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
3dca2276 | 189 | cc = BT_TO_COMMON(clock->clock_class); |
ac0c6bdd PP |
190 | |
191 | /* Common case where cycles are actually nanoseconds */ | |
3dca2276 | 192 | if (cc->frequency == 1000000000) { |
ac0c6bdd PP |
193 | value = time; |
194 | } else { | |
195 | value = (uint64_t) (((double) time * | |
3dca2276 | 196 | (double) cc->frequency) / 1e9); |
ac0c6bdd PP |
197 | } |
198 | ||
f6ccaed9 PP |
199 | BT_ASSERT_PRE(clock->value <= value, |
200 | "CTF writer clock value must be updated monotonically: " | |
201 | "prev-value=%" PRId64 ", new-value=%" PRId64, | |
202 | clock->value, value); | |
ac0c6bdd | 203 | clock->value = value; |
f6ccaed9 | 204 | return 0; |
ac0c6bdd PP |
205 | } |
206 | ||
ac0c6bdd PP |
207 | BT_HIDDEN |
208 | int bt_ctf_clock_get_value(struct bt_ctf_clock *clock, uint64_t *value) | |
209 | { | |
f6ccaed9 PP |
210 | BT_ASSERT_PRE_NON_NULL(clock, "CTF writer clock"); |
211 | BT_ASSERT_PRE_NON_NULL(value, "Value"); | |
ac0c6bdd | 212 | *value = clock->value; |
f6ccaed9 | 213 | return 0; |
ac0c6bdd PP |
214 | } |
215 | ||
216 | static | |
217 | void bt_ctf_clock_destroy(struct bt_object *obj) | |
218 | { | |
219 | struct bt_ctf_clock *clock; | |
220 | ||
221 | clock = container_of(obj, struct bt_ctf_clock, base); | |
3dca2276 | 222 | bt_put(BT_TO_COMMON(clock->clock_class)); |
ac0c6bdd PP |
223 | g_free(clock); |
224 | } | |
3dca2276 PP |
225 | |
226 | BT_HIDDEN | |
227 | void bt_ctf_clock_class_serialize(struct bt_ctf_clock_class *clock_class, | |
228 | struct metadata_context *context) | |
229 | { | |
230 | unsigned char *uuid; | |
231 | ||
232 | BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, " | |
233 | "name=\"%s\", metadata-context-addr=%p", clock_class, | |
234 | bt_clock_class_get_name(BT_TO_COMMON(clock_class)), | |
235 | context); | |
236 | ||
237 | if (!clock_class || !context) { | |
238 | BT_LOGW("Invalid parameter: clock class or metadata context is NULL: " | |
239 | "clock-class-addr=%p, name=\"%s\", metadata-context-addr=%p", | |
240 | clock_class, | |
241 | bt_clock_class_get_name(BT_TO_COMMON(clock_class)), | |
242 | context); | |
243 | return; | |
244 | } | |
245 | ||
246 | uuid = clock_class->common.uuid; | |
247 | g_string_append(context->string, "clock {\n"); | |
248 | g_string_append_printf(context->string, "\tname = %s;\n", | |
249 | clock_class->common.name->str); | |
250 | ||
251 | if (clock_class->common.uuid_set) { | |
252 | g_string_append_printf(context->string, | |
253 | "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n", | |
254 | uuid[0], uuid[1], uuid[2], uuid[3], | |
255 | uuid[4], uuid[5], uuid[6], uuid[7], | |
256 | uuid[8], uuid[9], uuid[10], uuid[11], | |
257 | uuid[12], uuid[13], uuid[14], uuid[15]); | |
258 | } | |
259 | ||
260 | if (clock_class->common.description) { | |
261 | g_string_append_printf(context->string, "\tdescription = \"%s\";\n", | |
262 | clock_class->common.description->str); | |
263 | } | |
264 | ||
265 | g_string_append_printf(context->string, "\tfreq = %" PRIu64 ";\n", | |
266 | clock_class->common.frequency); | |
267 | g_string_append_printf(context->string, "\tprecision = %" PRIu64 ";\n", | |
268 | clock_class->common.precision); | |
269 | g_string_append_printf(context->string, "\toffset_s = %" PRIu64 ";\n", | |
270 | clock_class->common.offset_s); | |
271 | g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n", | |
272 | clock_class->common.offset); | |
273 | g_string_append_printf(context->string, "\tabsolute = %s;\n", | |
274 | clock_class->common.absolute ? "true" : "false"); | |
275 | g_string_append(context->string, "};\n\n"); | |
276 | } | |
277 | ||
278 | struct bt_ctf_clock_class *bt_ctf_clock_class_create(const char *name, | |
279 | uint64_t freq) | |
280 | { | |
281 | return BT_FROM_COMMON(bt_clock_class_create(name, freq)); | |
282 | } | |
283 | ||
284 | const char *bt_ctf_clock_class_get_name( | |
285 | struct bt_ctf_clock_class *clock_class) | |
286 | { | |
287 | return bt_clock_class_get_name(BT_TO_COMMON(clock_class)); | |
288 | } | |
289 | ||
290 | int bt_ctf_clock_class_set_name(struct bt_ctf_clock_class *clock_class, | |
291 | const char *name) | |
292 | { | |
293 | return bt_clock_class_set_name(BT_TO_COMMON(clock_class), name); | |
294 | } | |
295 | ||
296 | const char *bt_ctf_clock_class_get_description( | |
297 | struct bt_ctf_clock_class *clock_class) | |
298 | { | |
299 | return bt_clock_class_get_description(BT_TO_COMMON(clock_class)); | |
300 | } | |
301 | ||
302 | int bt_ctf_clock_class_set_description( | |
303 | struct bt_ctf_clock_class *clock_class, | |
304 | const char *desc) | |
305 | { | |
306 | return bt_clock_class_set_description(BT_TO_COMMON(clock_class), desc); | |
307 | } | |
308 | ||
309 | uint64_t bt_ctf_clock_class_get_frequency( | |
310 | struct bt_ctf_clock_class *clock_class) | |
311 | { | |
312 | return bt_clock_class_get_frequency(BT_TO_COMMON(clock_class)); | |
313 | } | |
314 | ||
315 | int bt_ctf_clock_class_set_frequency( | |
316 | struct bt_ctf_clock_class *clock_class, uint64_t freq) | |
317 | { | |
318 | return bt_clock_class_set_frequency(BT_TO_COMMON(clock_class), freq); | |
319 | } | |
320 | ||
321 | uint64_t bt_ctf_clock_class_get_precision( | |
322 | struct bt_ctf_clock_class *clock_class) | |
323 | { | |
324 | return bt_clock_class_get_precision(BT_TO_COMMON(clock_class)); | |
325 | } | |
326 | ||
327 | int bt_ctf_clock_class_set_precision( | |
328 | struct bt_ctf_clock_class *clock_class, uint64_t precision) | |
329 | { | |
330 | return bt_clock_class_set_precision(BT_TO_COMMON(clock_class), | |
331 | precision); | |
332 | } | |
333 | ||
334 | int bt_ctf_clock_class_get_offset_s( | |
335 | struct bt_ctf_clock_class *clock_class, int64_t *seconds) | |
336 | { | |
337 | return bt_clock_class_get_offset_s(BT_TO_COMMON(clock_class), seconds); | |
338 | } | |
339 | ||
340 | int bt_ctf_clock_class_set_offset_s( | |
341 | struct bt_ctf_clock_class *clock_class, int64_t seconds) | |
342 | { | |
343 | return bt_clock_class_set_offset_s(BT_TO_COMMON(clock_class), seconds); | |
344 | } | |
345 | ||
346 | int bt_ctf_clock_class_get_offset_cycles( | |
347 | struct bt_ctf_clock_class *clock_class, int64_t *cycles) | |
348 | { | |
349 | return bt_clock_class_get_offset_cycles(BT_TO_COMMON(clock_class), | |
350 | cycles); | |
351 | } | |
352 | ||
353 | int bt_ctf_clock_class_set_offset_cycles( | |
354 | struct bt_ctf_clock_class *clock_class, int64_t cycles) | |
355 | { | |
356 | return bt_clock_class_set_offset_cycles(BT_TO_COMMON(clock_class), | |
357 | cycles); | |
358 | } | |
359 | ||
360 | bt_bool bt_ctf_clock_class_is_absolute( | |
361 | struct bt_ctf_clock_class *clock_class) | |
362 | { | |
363 | return bt_clock_class_is_absolute(BT_TO_COMMON(clock_class)); | |
364 | } | |
365 | ||
366 | int bt_ctf_clock_class_set_is_absolute( | |
367 | struct bt_ctf_clock_class *clock_class, bt_bool is_absolute) | |
368 | { | |
369 | return bt_clock_class_set_is_absolute(BT_TO_COMMON(clock_class), | |
370 | is_absolute); | |
371 | } | |
372 | ||
373 | const unsigned char *bt_ctf_clock_class_get_uuid( | |
374 | struct bt_ctf_clock_class *clock_class) | |
375 | { | |
376 | return bt_clock_class_get_uuid(BT_TO_COMMON(clock_class)); | |
377 | } | |
378 | ||
379 | int bt_ctf_clock_class_set_uuid(struct bt_ctf_clock_class *clock_class, | |
380 | const unsigned char *uuid) | |
381 | { | |
382 | return bt_clock_class_set_uuid(BT_TO_COMMON(clock_class), uuid); | |
383 | } |