X-Git-Url: https://git.efficios.com/?a=blobdiff_plain;f=formats%2Fctf%2Fir%2Fclock.c;h=e24b864b04e200d02f02f4cb96d4aaad5d7d3333;hb=98a4cbefe4c162067144bf5e1b7341c8dd8767bb;hp=723b860dd6e9d377ccf6e7e0f442358720caa4e4;hpb=83509119a945fc77faff869daaf48627e1c4b3fa;p=babeltrace.git diff --git a/formats/ctf/ir/clock.c b/formats/ctf/ir/clock.c index 723b860d..e24b864b 100644 --- a/formats/ctf/ir/clock.c +++ b/formats/ctf/ir/clock.c @@ -38,28 +38,21 @@ static void bt_ctf_clock_destroy(struct bt_object *obj); BT_HIDDEN -struct bt_ctf_clock *_bt_ctf_clock_create(void) +bool bt_ctf_clock_is_valid(struct bt_ctf_clock *clock) { - struct bt_ctf_clock *clock = g_new0( - struct bt_ctf_clock, 1); - - if (!clock) { - goto end; - } - - clock->precision = 1; - clock->frequency = 1000000000; - bt_object_init(clock, bt_ctf_clock_destroy); -end: - return clock; + return clock && clock->name; } -BT_HIDDEN int bt_ctf_clock_set_name(struct bt_ctf_clock *clock, const char *name) { int ret = 0; + if (!clock || clock->frozen) { + ret = -1; + goto end; + } + if (bt_ctf_validate_identifier(name)) { ret = -1; goto end; @@ -82,23 +75,35 @@ end: struct bt_ctf_clock *bt_ctf_clock_create(const char *name) { int ret; - struct bt_ctf_clock *clock = NULL; + struct bt_ctf_clock *clock = g_new0(struct bt_ctf_clock, 1); - clock = _bt_ctf_clock_create(); if (!clock) { goto error; } - ret = bt_ctf_clock_set_name(clock, name); - if (ret) { - goto error; + clock->precision = 1; + clock->frequency = 1000000000; + bt_object_init(clock, bt_ctf_clock_destroy); + + if (name) { + ret = bt_ctf_clock_set_name(clock, name); + if (ret) { + goto error; + } } - ret = babeltrace_uuid_generate(clock->uuid); + ret = bt_uuid_generate(clock->uuid); if (ret) { goto error; } + /* + * For backward compatibility reasons, a fresh clock can have + * a value because it could be added to a trace created by a + * CTF writer. As soon as this clock is added to a non-writer + * trace, then its value/time functions will be disabled. + */ + clock->has_value = 1; clock->uuid_set = 1; return clock; error: @@ -206,20 +211,21 @@ end: return ret; } -uint64_t bt_ctf_clock_get_offset_s(struct bt_ctf_clock *clock) +int bt_ctf_clock_get_offset_s(struct bt_ctf_clock *clock, int64_t *offset_s) { - uint64_t ret = -1ULL; + int ret = 0; - if (!clock) { + if (!clock || !offset_s) { + ret = -1; goto end; } - ret = clock->offset_s; + *offset_s = clock->offset_s; end: return ret; } -int bt_ctf_clock_set_offset_s(struct bt_ctf_clock *clock, uint64_t offset_s) +int bt_ctf_clock_set_offset_s(struct bt_ctf_clock *clock, int64_t offset_s) { int ret = 0; @@ -233,20 +239,21 @@ end: return ret; } -uint64_t bt_ctf_clock_get_offset(struct bt_ctf_clock *clock) +int bt_ctf_clock_get_offset(struct bt_ctf_clock *clock, int64_t *offset) { - uint64_t ret = -1ULL; + int ret = 0; - if (!clock) { + if (!clock || !offset) { + ret = -1; goto end; } - ret = clock->offset; + *offset = clock->offset; end: return ret; } -int bt_ctf_clock_set_offset(struct bt_ctf_clock *clock, uint64_t offset) +int bt_ctf_clock_set_offset(struct bt_ctf_clock *clock, int64_t offset) { int ret = 0; @@ -316,30 +323,55 @@ end: return ret; } -uint64_t bt_ctf_clock_get_time(struct bt_ctf_clock *clock) +uint64_t ns_from_value(uint64_t frequency, uint64_t value) { - uint64_t ret = -1ULL; + uint64_t ns; - if (!clock) { - goto end; + if (frequency == 1000000000) { + ns = value; + } else { + ns = (uint64_t) ((1e9 * (double) value) / (double) frequency); } - ret = clock->time; -end: - return ret; + return ns; } -int bt_ctf_clock_set_time(struct bt_ctf_clock *clock, uint64_t time) +int bt_ctf_clock_set_time(struct bt_ctf_clock *clock, int64_t time) { int ret = 0; + int64_t value; /* Timestamps are strictly monotonic */ - if (!clock || time < clock->time) { + if (!clock) { ret = -1; goto end; } - clock->time = time; + + if (!clock->has_value) { + /* + * Clock belongs to a non-writer mode trace and thus + * this function is disabled. + */ + ret = -1; + goto end; + } + + /* Common case where cycles are actually nanoseconds */ + if (clock->frequency == 1000000000) { + value = time; + } else { + value = (uint64_t) (((double) time * + (double) clock->frequency) / 1e9); + } + + if (clock->value > value) { + /* Timestamps must be strictly monotonic. */ + ret = -1; + goto end; + } + + clock->value = value; end: return ret; } @@ -402,6 +434,21 @@ void bt_ctf_clock_serialize(struct bt_ctf_clock *clock, g_string_append(context->string, "};\n\n"); } +BT_HIDDEN +int bt_ctf_clock_get_value(struct bt_ctf_clock *clock, uint64_t *value) +{ + int ret = 0; + + if (!clock || !value) { + ret = -1; + goto end; + } + + *value = clock->value; +end: + return ret; +} + static void bt_ctf_clock_destroy(struct bt_object *obj) { @@ -418,3 +465,79 @@ void bt_ctf_clock_destroy(struct bt_object *obj) g_free(clock); } + +static +void bt_ctf_clock_value_destroy(struct bt_object *obj) +{ + struct bt_ctf_clock_value *value; + + if (!obj) { + return; + } + + value = container_of(obj, struct bt_ctf_clock_value, base); + bt_put(value->clock_class); + g_free(value); +} + +struct bt_ctf_clock_value *bt_ctf_clock_value_create( + struct bt_ctf_clock *clock, uint64_t value) +{ + struct bt_ctf_clock_value *ret = NULL; + + if (!clock) { + goto end; + } + + ret = g_new0(struct bt_ctf_clock_value, 1); + if (!ret) { + goto end; + } + + bt_object_init(ret, bt_ctf_clock_value_destroy); + ret->clock_class = bt_get(clock); + ret->value = value; +end: + return ret; +} + +int bt_ctf_clock_value_get_value( + struct bt_ctf_clock_value *clock_value, uint64_t *raw_value) +{ + int ret = 0; + + if (!clock_value || !raw_value) { + ret = -1; + goto end; + } + + *raw_value = clock_value->value; +end: + return ret; +} + +int bt_ctf_clock_value_get_value_ns_from_epoch(struct bt_ctf_clock_value *value, + int64_t *ret_value_ns) +{ + int ret = 0; + int64_t ns; + + if (!value || !ret_value_ns) { + ret = -1; + goto end; + } + + /* Initialize nanosecond timestamp to clock's offset in seconds. */ + ns = value->clock_class->offset_s * 1000000000; + + /* Add offset in cycles, converted to nanoseconds. */ + ns += ns_from_value(value->clock_class->frequency, + value->clock_class->offset); + + /* Add given value, converter to nanoseconds. */ + ns += ns_from_value(value->clock_class->frequency, value->value); + + *ret_value_ns = ns; +end: + return ret; +}