#define BT_LOG_TAG "CLOCK-CLASS"
#include <babeltrace/lib-logging-internal.h>
+#include <babeltrace/compat/uuid-internal.h>
#include <babeltrace/ctf-ir/clock-class-internal.h>
#include <babeltrace/ctf-ir/utils.h>
#include <babeltrace/ref.h>
#include <babeltrace/compiler-internal.h>
#include <babeltrace/types.h>
+#include <babeltrace/compat/string-internal.h>
#include <inttypes.h>
#include <babeltrace/object-internal.h>
}
if (clock_class->frozen) {
- BT_LOGW("Invalid parameter: clock class is frozen: addr=%p",
- clock_class);
+ BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
ret = -1;
goto end;
}
if (bt_ctf_validate_identifier(name)) {
BT_LOGE("Clock class's name is not a valid CTF identifier: "
- "clock-class-addr=%p, name=\"%s\"",
+ "addr=%p, name=\"%s\"",
clock_class, name);
ret = -1;
goto end;
}
}
- BT_LOGV("Set clock class's name: clock-class-addr=%p, name=\"%s\"",
+ BT_LOGV("Set clock class's name: addr=%p, name=\"%s\"",
clock_class, name);
end:
return ret;
}
-struct bt_ctf_clock_class *bt_ctf_clock_class_create(const char *name)
+static
+bool validate_freq(struct bt_ctf_clock_class *clock_class,
+ const char *name, uint64_t freq)
+{
+ bool is_valid = true;
+
+ if (freq == -1ULL || freq == 0) {
+ BT_LOGW("Invalid parameter: frequency is invalid: "
+ "addr=%p, name=\"%s\", freq=%" PRIu64,
+ clock_class, name, freq);
+ is_valid = false;
+ goto end;
+ }
+
+end:
+ return is_valid;
+}
+
+struct bt_ctf_clock_class *bt_ctf_clock_class_create(const char *name,
+ uint64_t freq)
{
int ret;
- struct bt_ctf_clock_class *clock_class;
+ struct bt_ctf_clock_class *clock_class = NULL;
BT_LOGD("Creating default clock class object: name=\"%s\"",
name);
+
+ if (!validate_freq(NULL, name, freq)) {
+ /* validate_freq() logs errors */
+ goto error;
+ }
+
clock_class = g_new0(struct bt_ctf_clock_class, 1);
if (!clock_class) {
BT_LOGE_STR("Failed to allocate one clock class.");
}
clock_class->precision = 1;
- clock_class->frequency = 1000000000;
+ clock_class->frequency = freq;
bt_object_init(clock_class, bt_ctf_clock_class_destroy);
if (name) {
ret = bt_ctf_clock_class_set_name(clock_class, name);
if (ret) {
BT_LOGE("Cannot set clock class's name: "
- "clock-class-addr=%p, name=\"%s\"",
+ "addr=%p, name=\"%s\"",
clock_class, name);
goto error;
}
}
- ret = bt_uuid_generate(clock_class->uuid);
- if (ret) {
- BT_LOGE_STR("Failed to generate a UUID.");
- goto error;
- }
-
- clock_class->uuid_set = 1;
- BT_LOGD("Created clock class object: addr=%p", clock_class);
+ BT_LOGD("Created clock class object: addr=%p, name=\"%s\"",
+ clock_class, name);
return clock_class;
error:
BT_PUT(clock_class);
if (!clock_class || !desc) {
BT_LOGW("Invalid parameter: clock class or description is NULL: "
- "clock-class-addr=%p, desc-addr=%p",
- clock_class, desc);
+ "clock-class-addr=%p, name=\"%s\", desc-addr=%p",
+ clock_class, bt_ctf_clock_class_get_name(clock_class),
+ desc);
ret = -1;
goto end;
}
if (clock_class->frozen) {
- BT_LOGW("Invalid parameter: clock class is frozen: addr=%p",
- clock_class);
+ BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
ret = -1;
goto end;
}
clock_class->description = g_string_new(desc);
ret = clock_class->description ? 0 : -1;
- BT_LOGV("Set clock class's description: clock-class-addr=%p, desc=\"%s\"",
- clock_class, desc);
+ BT_LOGV("Set clock class's description: addr=%p, "
+ "name=\"%s\", desc=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class), desc);
end:
return ret;
}
{
int ret = 0;
- if (!clock_class || freq == -1ULL) {
+ if (!clock_class) {
BT_LOGW("Invalid parameter: clock class is NULL or frequency is invalid: "
- "clock-class-addr=%p, freq=%" PRIu64,
- clock_class, freq);
+ "addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
ret = -1;
goto end;
}
+ if (!validate_freq(clock_class, bt_ctf_clock_class_get_name(clock_class),
+ freq)) {
+ /* validate_freq() logs errors */
+ goto end;
+ }
+
if (clock_class->frozen) {
- BT_LOGW("Invalid parameter: clock class is frozen: addr=%p",
- clock_class);
+ BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
ret = -1;
goto end;
}
clock_class->frequency = freq;
- BT_LOGV("Set clock class's frequency: clock-class-addr=%p, freq=%" PRIu64,
- clock_class, freq);
+ BT_LOGV("Set clock class's frequency: addr=%p, name=\"%s\", freq=%" PRIu64,
+ clock_class, bt_ctf_clock_class_get_name(clock_class), freq);
end:
return ret;
}
if (!clock_class || precision == -1ULL) {
BT_LOGW("Invalid parameter: clock class is NULL or precision is invalid: "
- "clock-class-addr=%p, precision=%" PRIu64,
- clock_class, precision);
+ "addr=%p, name=\"%s\", precision=%" PRIu64,
+ clock_class, bt_ctf_clock_class_get_name(clock_class),
+ precision);
ret = -1;
goto end;
}
if (clock_class->frozen) {
- BT_LOGW("Invalid parameter: clock class is frozen: addr=%p",
- clock_class);
+ BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
ret = -1;
goto end;
}
clock_class->precision = precision;
- BT_LOGV("Set clock class's precision: clock-class-addr=%p, precision=%" PRIu64,
- clock_class, precision);
+ BT_LOGV("Set clock class's precision: addr=%p, name=\"%s\", precision=%" PRIu64,
+ clock_class, bt_ctf_clock_class_get_name(clock_class),
+ precision);
end:
return ret;
}
if (!clock_class || !offset_s) {
BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
- "clock-class-addr=%p, offset-addr=%p",
- clock_class, offset_s);
+ "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
+ clock_class, bt_ctf_clock_class_get_name(clock_class),
+ offset_s);
ret = -1;
goto end;
}
}
if (clock_class->frozen) {
- BT_LOGW("Invalid parameter: clock class is frozen: addr=%p",
- clock_class);
+ BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
ret = -1;
goto end;
}
clock_class->offset_s = offset_s;
- BT_LOGV("Set clock class's offset (seconds): clock-class-addr=%p, offset-s=%" PRId64,
- clock_class, offset_s);
+ BT_LOGV("Set clock class's offset (seconds): "
+ "addr=%p, name=\"%s\", offset-s=%" PRId64,
+ clock_class, bt_ctf_clock_class_get_name(clock_class),
+ offset_s);
end:
return ret;
}
if (!clock_class || !offset) {
BT_LOGW("Invalid parameter: clock class or offset pointer is NULL: "
- "clock-class-addr=%p, offset-addr=%p",
- clock_class, offset);
+ "clock-class-addr=%p, name=\"%s\", offset-addr=%p",
+ clock_class, bt_ctf_clock_class_get_name(clock_class),
+ offset);
ret = -1;
goto end;
}
}
if (clock_class->frozen) {
- BT_LOGW("Invalid parameter: clock class is frozen: addr=%p",
- clock_class);
+ BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
ret = -1;
goto end;
}
clock_class->offset = offset;
- BT_LOGV("Set clock class's offset (cycles): clock-class-addr=%p, offset-cycles=%" PRId64,
- clock_class, offset);
+ BT_LOGV("Set clock class's offset (cycles): addr=%p, name=\"%s\", offset-cycles=%" PRId64,
+ clock_class, bt_ctf_clock_class_get_name(clock_class), offset);
end:
return ret;
}
}
if (clock_class->frozen) {
- BT_LOGW("Invalid parameter: clock class is frozen: addr=%p",
- clock_class);
+ BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
ret = -1;
goto end;
}
clock_class->absolute = !!is_absolute;
- BT_LOGV("Set clock class's absolute flag: clock-class-addr=%p, is-absolute=%d",
- clock_class, !!is_absolute);
+ BT_LOGV("Set clock class's absolute flag: addr=%p, name=\"%s\", is-absolute=%d",
+ clock_class, bt_ctf_clock_class_get_name(clock_class),
+ is_absolute);
end:
return ret;
}
}
if (!clock_class->uuid_set) {
- BT_LOGV("Clock class's UUID is not set: clock-class-addr=%p",
- clock_class);
+ BT_LOGV("Clock class's UUID is not set: addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
ret = NULL;
goto end;
}
if (!clock_class || !uuid) {
BT_LOGW("Invalid parameter: clock class or UUID is NULL: "
- "clock-class-addr=%p, uuid-addr=%p",
- clock_class, uuid);
+ "clock-class-addr=%p, name=\"%s\", uuid-addr=%p",
+ clock_class, bt_ctf_clock_class_get_name(clock_class),
+ uuid);
ret = -1;
goto end;
}
if (clock_class->frozen) {
- BT_LOGW("Invalid parameter: clock class is frozen: addr=%p",
- clock_class);
+ BT_LOGW("Invalid parameter: clock class is frozen: addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
ret = -1;
goto end;
}
- memcpy(clock_class->uuid, uuid, sizeof(uuid_t));
+ memcpy(clock_class->uuid, uuid, BABELTRACE_UUID_LEN);
clock_class->uuid_set = 1;
- BT_LOGV("Set clock class's UUID: clock-class-addr=%p, "
+ BT_LOGV("Set clock class's UUID: addr=%p, name=\"%s\", "
"uuid=\"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\"",
- clock_class,
+ clock_class, bt_ctf_clock_class_get_name(clock_class),
(unsigned int) uuid[0],
(unsigned int) uuid[1],
(unsigned int) uuid[2],
if (frequency == 1000000000) {
ns = value;
} else {
- ns = (uint64_t) ((1e9 * (double) value) / (double) frequency);
+ double dblres = ((1e9 * (double) value) / (double) frequency);
+
+ if (dblres >= (double) UINT64_MAX) {
+ /* Overflows uint64_t */
+ ns = -1ULL;
+ } else {
+ ns = (uint64_t) dblres;
+ }
}
return ns;
}
if (!clock_class->frozen) {
- BT_LOGD("Freezing clock class: addr=%p", clock_class);
+ BT_LOGD("Freezing clock class: addr=%p, name=\"%s\"",
+ clock_class, bt_ctf_clock_class_get_name(clock_class));
clock_class->frozen = 1;
}
}
unsigned char *uuid;
BT_LOGD("Serializing clock class's metadata: clock-class-addr=%p, "
- "metadata-context-addr=%p", clock_class, context);
+ "name=\"%s\", metadata-context-addr=%p", clock_class,
+ bt_ctf_clock_class_get_name(clock_class), context);
if (!clock_class || !context) {
BT_LOGW("Invalid parameter: clock class or metadata context is NULL: "
- "clock-class-addr=%p, metadata-context-addr=%p",
- clock_class, context);
+ "clock-class-addr=%p, name=\"%s\", metadata-context-addr=%p",
+ clock_class, bt_ctf_clock_class_get_name(clock_class),
+ context);
return;
}
g_string_append(context->string, "clock {\n");
g_string_append_printf(context->string, "\tname = %s;\n",
clock_class->name->str);
- g_string_append_printf(context->string,
- "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
- uuid[0], uuid[1], uuid[2], uuid[3],
- uuid[4], uuid[5], uuid[6], uuid[7],
- uuid[8], uuid[9], uuid[10], uuid[11],
- uuid[12], uuid[13], uuid[14], uuid[15]);
+
+ if (clock_class->uuid_set) {
+ g_string_append_printf(context->string,
+ "\tuuid = \"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x\";\n",
+ uuid[0], uuid[1], uuid[2], uuid[3],
+ uuid[4], uuid[5], uuid[6], uuid[7],
+ uuid[8], uuid[9], uuid[10], uuid[11],
+ uuid[12], uuid[13], uuid[14], uuid[15]);
+ }
+
if (clock_class->description) {
g_string_append_printf(context->string, "\tdescription = \"%s\";\n",
clock_class->description->str);
g_string_append_printf(context->string, "\toffset = %" PRIu64 ";\n",
clock_class->offset);
g_string_append_printf(context->string, "\tabsolute = %s;\n",
- clock_class->absolute ? "TRUE" : "FALSE");
+ clock_class->absolute ? "true" : "false");
g_string_append(context->string, "};\n\n");
}
{
struct bt_ctf_clock_class *clock_class;
- BT_LOGD("Destroying clock class: addr=%p", obj);
clock_class = container_of(obj, struct bt_ctf_clock_class, base);
+ BT_LOGD("Destroying clock class: addr=%p, name=\"%s\"",
+ obj, bt_ctf_clock_class_get_name(clock_class));
if (clock_class->name) {
g_string_free(clock_class->name, TRUE);
}
{
struct bt_ctf_clock_value *value;
- BT_LOGD("Destroying clock value: addr=%p", obj);
-
if (!obj) {
return;
}
value = container_of(obj, struct bt_ctf_clock_value, base);
+ BT_LOGD("Destroying clock value: addr=%p, clock-class-addr=%p, "
+ "clock-class-name=\"%s\"", obj, value->clock_class,
+ bt_ctf_clock_class_get_name(value->clock_class));
bt_put(value->clock_class);
g_free(value);
}
+static
+void set_ns_from_epoch(struct bt_ctf_clock_value *clock_value)
+{
+ struct bt_ctf_clock_class *clock_class = clock_value->clock_class;
+ int64_t diff;
+ int64_t s_ns;
+ uint64_t u_ns;
+ uint64_t cycles;
+
+ /* Initialize nanosecond timestamp to clock's offset in seconds */
+ if (clock_class->offset_s <= (INT64_MIN / 1000000000) ||
+ clock_class->offset_s >= (INT64_MAX / 1000000000)) {
+ /*
+ * Overflow: offset in seconds converted to nanoseconds
+ * is outside the int64_t range.
+ */
+ clock_value->ns_from_epoch_overflows = true;
+ goto end;
+ }
+
+ clock_value->ns_from_epoch = clock_class->offset_s * (int64_t) 1000000000;
+
+ /* Add offset in cycles */
+ if (clock_class->offset < 0) {
+ cycles = (uint64_t) (-clock_class->offset);
+ } else {
+ cycles = (uint64_t) clock_class->offset;
+ }
+
+ u_ns = ns_from_value(clock_class->frequency, cycles);
+
+ if (u_ns == -1ULL || u_ns >= INT64_MAX) {
+ /*
+ * Overflow: offset in cycles converted to nanoseconds
+ * is outside the int64_t range.
+ */
+ clock_value->ns_from_epoch_overflows = true;
+ goto end;
+ }
+
+ s_ns = (int64_t) u_ns;
+ assert(s_ns >= 0);
+
+ if (clock_class->offset < 0) {
+ if (clock_value->ns_from_epoch >= 0) {
+ /*
+ * Offset in cycles is negative so it must also
+ * be negative once converted to nanoseconds.
+ */
+ s_ns = -s_ns;
+ goto offset_ok;
+ }
+
+ diff = clock_value->ns_from_epoch - INT64_MIN;
+
+ if (s_ns >= diff) {
+ /*
+ * Overflow: current timestamp in nanoseconds
+ * plus the offset in cycles converted to
+ * nanoseconds is outside the int64_t range.
+ */
+ clock_value->ns_from_epoch_overflows = true;
+ goto end;
+ }
+
+ /*
+ * Offset in cycles is negative so it must also be
+ * negative once converted to nanoseconds.
+ */
+ s_ns = -s_ns;
+ } else {
+ if (clock_value->ns_from_epoch <= 0) {
+ goto offset_ok;
+ }
+
+ diff = INT64_MAX - clock_value->ns_from_epoch;
+
+ if (s_ns >= diff) {
+ /*
+ * Overflow: current timestamp in nanoseconds
+ * plus the offset in cycles converted to
+ * nanoseconds is outside the int64_t range.
+ */
+ clock_value->ns_from_epoch_overflows = true;
+ goto end;
+ }
+ }
+
+offset_ok:
+ clock_value->ns_from_epoch += s_ns;
+
+ /* Add clock value (cycles) */
+ u_ns = ns_from_value(clock_class->frequency, clock_value->value);
+
+ if (u_ns == -1ULL || u_ns >= INT64_MAX) {
+ /*
+ * Overflow: value converted to nanoseconds is outside
+ * the int64_t range.
+ */
+ clock_value->ns_from_epoch_overflows = true;
+ goto end;
+ }
+
+ s_ns = (int64_t) u_ns;
+ assert(s_ns >= 0);
+
+ /* Clock value (cycles) is always positive */
+ if (clock_value->ns_from_epoch <= 0) {
+ goto value_ok;
+ }
+
+ diff = INT64_MAX - clock_value->ns_from_epoch;
+
+ if (s_ns >= diff) {
+ /*
+ * Overflow: current timestamp in nanoseconds plus the
+ * clock value converted to nanoseconds is outside the
+ * int64_t range.
+ */
+ clock_value->ns_from_epoch_overflows = true;
+ goto end;
+ }
+
+value_ok:
+ clock_value->ns_from_epoch += s_ns;
+
+end:
+ if (clock_value->ns_from_epoch_overflows) {
+ clock_value->ns_from_epoch = 0;
+ }
+}
+
struct bt_ctf_clock_value *bt_ctf_clock_value_create(
struct bt_ctf_clock_class *clock_class, uint64_t value)
{
struct bt_ctf_clock_value *ret = NULL;
BT_LOGD("Creating clock value object: clock-class-addr=%p, "
- "value=%" PRIu64, clock_class, value);
+ "clock-class-name=\"%s\", value=%" PRIu64, clock_class,
+ bt_ctf_clock_class_get_name(clock_class), value);
if (!clock_class) {
BT_LOGW_STR("Invalid parameter: clock class is NULL.");
bt_object_init(ret, bt_ctf_clock_value_destroy);
ret->clock_class = bt_get(clock_class);
ret->value = value;
- BT_LOGD("Created clock value object: addr=%p", ret);
+ set_ns_from_epoch(ret);
+ BT_LOGD("Created clock value object: clock-value-addr=%p, "
+ "clock-class-addr=%p, clock-class-name=\"%s\", "
+ "ns-from-epoch=%" PRId64 ", ns-from-epoch-overflows=%d",
+ ret, clock_class, bt_ctf_clock_class_get_name(clock_class),
+ ret->ns_from_epoch, ret->ns_from_epoch_overflows);
+
end:
return ret;
}
int64_t *ret_value_ns)
{
int ret = 0;
- int64_t ns;
if (!value || !ret_value_ns) {
BT_LOGW("Invalid parameter: clock value or return value pointer is NULL: "
goto end;
}
- /* Initialize nanosecond timestamp to clock's offset in seconds. */
- ns = value->clock_class->offset_s * (int64_t) 1000000000;
-
- /* Add offset in cycles, converted to nanoseconds. */
- ns += ns_from_value(value->clock_class->frequency,
- value->clock_class->offset);
+ if (value->ns_from_epoch_overflows) {
+ BT_LOGW("Clock value converted to nanoseconds from Epoch overflows the signed 64-bit integer range: "
+ "clock-value-addr=%p, "
+ "clock-class-offset-s=%" PRId64 ", "
+ "clock-class-offset-cycles=%" PRId64 ", "
+ "value=%" PRIu64,
+ value, value->clock_class->offset_s,
+ value->clock_class->offset,
+ value->value);
+ ret = -1;
+ goto end;
+ }
- /* Add given value, converter to nanoseconds. */
- ns += ns_from_value(value->clock_class->frequency, value->value);
+ *ret_value_ns = value->ns_from_epoch;
- *ret_value_ns = ns;
end:
return ret;
}