sessiond: Move trace_ust_clock to a clock_attributes_sample class
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 2 May 2022 19:35:40 +0000 (15:35 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Mon, 13 Jun 2022 20:34:46 +0000 (16:34 -0400)
Move trace clock functions to a class that samples the clock's
attributes on creation. This makes it easier to implement trace format
agnostic serialization facilities in follow-up patches.

Change-Id: Id75b2c6e00779710e02691da107b2e93bf33ff12
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/bin/lttng-sessiond/Makefile.am
src/bin/lttng-sessiond/ust-clock.cpp [new file with mode: 0644]
src/bin/lttng-sessiond/ust-clock.hpp
src/bin/lttng-sessiond/ust-metadata.cpp

index 0fdd6775aaf74173d70c9939cb13e2503fddff82..5b5047f4306b48a04d2b8b0daaa4aaea8a578135 100644 (file)
@@ -62,7 +62,8 @@ liblttng_sessiond_common_la_SOURCES = utils.cpp utils.hpp \
 if HAVE_LIBLTTNG_UST_CTL
 liblttng_sessiond_common_la_SOURCES += trace-ust.cpp ust-registry.cpp ust-app.cpp \
                        ust-consumer.cpp ust-consumer.hpp notify-apps.cpp \
-                       ust-metadata.cpp ust-clock.hpp agent-thread.cpp agent-thread.hpp \
+                       ust-metadata.cpp ust-clock.hpp ust-clock.cpp \
+                       agent-thread.cpp agent-thread.hpp \
                        ust-field-utils.hpp ust-field-utils.cpp \
                        ust-sigbus.cpp \
                        ust-registry-session.cpp \
diff --git a/src/bin/lttng-sessiond/ust-clock.cpp b/src/bin/lttng-sessiond/ust-clock.cpp
new file mode 100644 (file)
index 0000000..3d853ad
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2010 Pierre-Marc Fournier
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#include "ust-clock.hpp"
+
+#include <common/time.hpp>
+#include <common/exception.hpp>
+
+#define CLOCK_OFFSET_SAMPLE_COUNT              10
+
+namespace {
+struct offset_sample {
+       /* correlation offset */
+       lttng::ust::clock_attributes_sample::scycles_t offset;
+       /* lower is better */
+       lttng::ust::clock_attributes_sample::cycles_t measure_delta;
+};
+
+lttng::ust::clock_attributes_sample::cycles_t sample_clock_read64()
+{
+       lttng_ust_clock_read64_function read64_cb;
+
+       if (lttng_ust_trace_clock_get_read64_cb(&read64_cb)) {
+               LTTNG_THROW_ERROR("Failed to get clock sample callback");
+       }
+
+       return read64_cb();
+}
+
+lttng::ust::clock_attributes_sample::cycles_t sample_clock_frequency()
+{
+       lttng_ust_clock_freq_function get_freq_cb;
+
+       if (lttng_ust_trace_clock_get_freq_cb(&get_freq_cb)) {
+               LTTNG_THROW_ERROR("Failed to get clock frequency callback");
+       }
+
+       return get_freq_cb();
+}
+
+nonstd::optional<lttng_uuid> sample_clock_uuid()
+{
+       lttng_ust_clock_uuid_function get_uuid_cb;
+
+       if (lttng_ust_trace_clock_get_uuid_cb(&get_uuid_cb)) {
+               return nonstd::nullopt;
+       }
+
+       char uuid_str[LTTNG_UUID_STR_LEN];
+       if (get_uuid_cb(uuid_str)) {
+               return nonstd::nullopt;
+       }
+
+       lttng_uuid uuid;
+       if (lttng_uuid_from_str(uuid_str, uuid)) {
+               LTTNG_THROW_ERROR("Failed to parse UUID from string");
+       }
+
+       return nonstd::optional<lttng_uuid>{uuid};
+}
+
+const char *sample_clock_name()
+{
+       lttng_ust_clock_name_function get_name_cb;
+
+       if (lttng_ust_trace_clock_get_name_cb(&get_name_cb)) {
+               LTTNG_THROW_ERROR("Failed to get clock name callback");
+       }
+
+       const auto name = get_name_cb();
+       if (!name) {
+               LTTNG_THROW_ERROR("Invalid clock name returned by LTTng-UST `lttng_ust_clock_name_function`");
+       }
+
+       return name;
+}
+
+const char *sample_clock_description()
+{
+       lttng_ust_clock_description_function get_description_cb;
+
+       if (lttng_ust_trace_clock_get_description_cb(&get_description_cb)) {
+               LTTNG_THROW_ERROR("Failed to get clock description callback");
+       }
+
+       const auto description = get_description_cb();
+       if (!description) {
+               LTTNG_THROW_ERROR("Invalid clock description returned by LTTng-UST `lttng_ust_clock_description_function`");
+       }
+
+       return description;
+}
+
+/*
+ * The offset between monotonic and realtime clock can be negative if
+ * the system sets the REALTIME clock to 0 after boot.
+ */
+void measure_single_clock_offset(struct offset_sample *sample)
+{
+       lttng::ust::clock_attributes_sample::cycles_t monotonic_avg, monotonic[2], measure_delta,
+                       realtime;
+       const auto tcf = sample_clock_frequency();
+       struct timespec rts = { 0, 0 };
+
+       monotonic[0] = sample_clock_read64();
+       if (lttng_clock_gettime(CLOCK_REALTIME, &rts)) {
+               LTTNG_THROW_POSIX("Failed to sample time from clock", errno);
+       }
+
+       monotonic[1] = sample_clock_read64();
+       measure_delta = monotonic[1] - monotonic[0];
+       if (measure_delta > sample->measure_delta) {
+               /*
+                * Discard value if it took longer to read than the best
+                * sample so far.
+                */
+               return;
+       }
+
+       monotonic_avg = (monotonic[0] + monotonic[1]) >> 1;
+       realtime = (lttng::ust::clock_attributes_sample::cycles_t) rts.tv_sec * tcf;
+       if (tcf == NSEC_PER_SEC) {
+               realtime += rts.tv_nsec;
+       } else {
+               realtime += (lttng::ust::clock_attributes_sample::cycles_t) rts.tv_nsec * tcf /
+                               NSEC_PER_SEC;
+       }
+
+       sample->offset = (lttng::ust::clock_attributes_sample::scycles_t) realtime - monotonic_avg;
+       sample->measure_delta = measure_delta;
+}
+
+/*
+ * Approximation of NTP time of day to clock monotonic correlation,
+ * taken at start of trace. Keep the measurement that took the less time
+ * to complete, thus removing imprecision caused by preemption.
+ * May return a negative offset.
+ */
+lttng::ust::clock_attributes_sample::scycles_t measure_clock_offset(void)
+{
+       struct offset_sample offset_best_sample = {
+               .offset = 0,
+               .measure_delta = UINT64_MAX,
+       };
+
+       for (auto i = 0; i < CLOCK_OFFSET_SAMPLE_COUNT; i++) {
+               measure_single_clock_offset(&offset_best_sample);
+       }
+
+       return offset_best_sample.offset;
+}
+}
+
+lttng::ust::clock_attributes_sample::clock_attributes_sample() :
+        _name{sample_clock_name()},
+        _description{sample_clock_description()},
+        _uuid{sample_clock_uuid()},
+       _offset{measure_clock_offset()},
+       _frequency{sample_clock_frequency()}
+{
+}
index 3807f40a3127c5348c26d6222ed8abfc81264b55..7b9034173b34ba861680104b3d89c8ba8149262e 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2010 Pierre-Marc Fournier
  * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
  * SPDX-License-Identifier: GPL-2.0-only
  *
 #define _UST_CLOCK_H
 
 #include <common/compat/time.hpp>
-#include <sys/time.h>
-#include <stdint.h>
+#include <common/uuid.hpp>
+#include <vendor/optional.hpp>
+
+#include <lttng/ust-clock.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <stdio.h>
-#include <urcu/system.h>
+#include <string>
+#include <sys/time.h>
 #include <urcu/arch.h>
-#include <lttng/ust-clock.h>
-
-#include <common/uuid.hpp>
-
-static __inline__
-uint64_t trace_clock_read64(void)
-{
-       uint64_t clock_value = 0;
-       lttng_ust_clock_read64_function read64_cb;
-
-       if (lttng_ust_trace_clock_get_read64_cb(&read64_cb)) {
-               goto end;
-       }
-
-       clock_value = read64_cb();
-end:
-       return clock_value;
-}
-
-static __inline__
-uint64_t trace_clock_freq(void)
-{
-       uint64_t frequency = 0;
-       lttng_ust_clock_freq_function get_freq_cb;
-
-       if (lttng_ust_trace_clock_get_freq_cb(&get_freq_cb)) {
-               goto end;
-       }
-
-       frequency = get_freq_cb();
-end:
-       return frequency;
-}
-
-static __inline__
-int trace_clock_uuid(char *uuid)
-{
-       int ret;
-       lttng_ust_clock_uuid_function get_uuid_cb;
-
-       if (lttng_ust_trace_clock_get_uuid_cb(&get_uuid_cb)) {
-               ret = -EINVAL;
-               goto end;
-       }
-
-       ret = get_uuid_cb(uuid);
-end:
-       return ret;
-
-}
-
-static __inline__
-const char *trace_clock_name(void)
-{
-       const char *name;
-       lttng_ust_clock_name_function get_name_cb;
+#include <urcu/system.h>
 
-       if (lttng_ust_trace_clock_get_name_cb(&get_name_cb)) {
-               name = NULL;
-               goto end;
-       }
+namespace lttng {
+namespace ust {
 
-       name = get_name_cb();
-end:
-       return name;
-}
+class clock_attributes_sample {
+public:
+       using cycles_t = uint64_t;
+       using scycles_t = int64_t;
 
-static __inline__
-const char *trace_clock_description(void)
-{
-       const char *description;
-       lttng_ust_clock_description_function get_description_cb;
+       clock_attributes_sample();
 
-       if (lttng_ust_trace_clock_get_description_cb(&get_description_cb)) {
-               description = NULL;
-               goto end;
-       }
+       const std::string _name;
+       const std::string _description;
+       const nonstd::optional<lttng_uuid> _uuid;
+       const scycles_t _offset;
+       const cycles_t _frequency;
+};
 
-       description = get_description_cb();
-end:
-       return description;
-}
+} /* namespace ust */
+} /* namespace lttng */
 
 #endif /* _UST_CLOCK_H */
index 64c48cb2dda34ac0bccdca60989e4f30078baec0..edbad778372023b1aee27a48b5240b99d80eccc9 100644 (file)
@@ -6,31 +6,23 @@
  */
 
 #define _LGPL_SOURCE
-#include <stdint.h>
-#include <string.h>
+#include <inttypes.h>
+#include <limits.h>
 #include <stdarg.h>
+#include <stdint.h>
 #include <stdio.h>
-#include <limits.h>
+#include <string.h>
 #include <unistd.h>
-#include <inttypes.h>
+#include <vector>
+
 #include <common/common.hpp>
+#include <common/exception.hpp>
 #include <common/time.hpp>
-#include <vector>
+#include <common/uuid.hpp>
 
-#include "ust-registry.hpp"
-#include "ust-clock.hpp"
 #include "ust-app.hpp"
-
-#define NR_CLOCK_OFFSET_SAMPLES                10
-
-namespace {
-struct offset_sample {
-       /* correlation offset */
-       int64_t offset;
-       /* lower is better */
-       uint64_t measure_delta;
-};
-} /* namespace */
+#include "ust-clock.hpp"
+#include "ust-registry.hpp"
 
 static
 int _lttng_field_statedump(ust_registry_session *session,
@@ -1057,67 +1049,6 @@ int _lttng_event_header_declare(ust_registry_session *session)
        );
 }
 
-/*
- * The offset between monotonic and realtime clock can be negative if
- * the system sets the REALTIME clock to 0 after boot.
- */
-static
-int measure_single_clock_offset(struct offset_sample *sample)
-{
-       uint64_t monotonic_avg, monotonic[2], measure_delta, realtime;
-       uint64_t tcf = trace_clock_freq();
-       struct timespec rts = { 0, 0 };
-       int ret;
-
-       monotonic[0] = trace_clock_read64();
-       ret = lttng_clock_gettime(CLOCK_REALTIME, &rts);
-       if (ret < 0) {
-               return ret;
-       }
-       monotonic[1] = trace_clock_read64();
-       measure_delta = monotonic[1] - monotonic[0];
-       if (measure_delta > sample->measure_delta) {
-               /*
-                * Discard value if it took longer to read than the best
-                * sample so far.
-                */
-               return 0;
-       }
-       monotonic_avg = (monotonic[0] + monotonic[1]) >> 1;
-       realtime = (uint64_t) rts.tv_sec * tcf;
-       if (tcf == NSEC_PER_SEC) {
-               realtime += rts.tv_nsec;
-       } else {
-               realtime += (uint64_t) rts.tv_nsec * tcf / NSEC_PER_SEC;
-       }
-       sample->offset = (int64_t) realtime - monotonic_avg;
-       sample->measure_delta = measure_delta;
-       return 0;
-}
-
-/*
- * Approximation of NTP time of day to clock monotonic correlation,
- * taken at start of trace. Keep the measurement that took the less time
- * to complete, thus removing imprecision caused by preemption.
- * May return a negative offset.
- */
-static
-int64_t measure_clock_offset(void)
-{
-       int i;
-       struct offset_sample offset_best_sample = {
-               .offset = 0,
-               .measure_delta = UINT64_MAX,
-       };
-
-       for (i = 0; i < NR_CLOCK_OFFSET_SAMPLES; i++) {
-               if (measure_single_clock_offset(&offset_best_sample)) {
-                       return 0;
-               }
-       }
-       return offset_best_sample.offset;
-}
-
 static
 int print_metadata_session_information(ust_registry_session *registry)
 {
@@ -1211,12 +1142,12 @@ int print_metadata_app_information(ust_registry_session *registry)
  */
 int ust_metadata_session_statedump(ust_registry_session *session)
 {
-       char uuid_s[LTTNG_UUID_STR_LEN], clock_uuid_s[LTTNG_UUID_STR_LEN];
        int ret = 0;
+       char trace_uuid_str[LTTNG_UUID_STR_LEN];
 
        LTTNG_ASSERT(session);
 
-       lttng_uuid_to_str(session->_uuid, uuid_s);
+       lttng_uuid_to_str(session->_uuid, trace_uuid_str);
 
        /* For crash ABI */
        ret = lttng_metadata_printf(session,
@@ -1256,7 +1187,7 @@ int ust_metadata_session_statedump(ust_registry_session *session)
                session->_long_alignment,
                CTF_SPEC_MAJOR,
                CTF_SPEC_MINOR,
-               uuid_s,
+               trace_uuid_str,
                session->_byte_order == BIG_ENDIAN ? "be" : "le"
                );
        if (ret) {
@@ -1303,61 +1234,63 @@ int ust_metadata_session_statedump(ust_registry_session *session)
                goto end;
        }
 
-       ret = lttng_metadata_printf(session,
-               "clock {\n"
-               "       name = \"%s\";\n",
-               trace_clock_name()
-               );
-       if (ret) {
-               goto end;
-       }
+       try {
+               const lttng::ust::clock_attributes_sample clock;
 
-       if (!trace_clock_uuid(clock_uuid_s)) {
                ret = lttng_metadata_printf(session,
-                       "       uuid = \"%s\";\n",
-                       clock_uuid_s
-                       );
+                               "clock {\n"
+                               "       name = \"%s\";\n",
+                               clock._name.c_str());
                if (ret) {
                        goto end;
                }
-       }
 
-       ret = lttng_metadata_printf(session,
-               "       description = \"%s\";\n"
-               "       freq = %" PRIu64 "; /* Frequency, in Hz */\n"
-               "       /* clock value offset from Epoch is: offset * (1/freq) */\n"
-               "       offset = %" PRId64 ";\n"
-               "};\n\n",
-               trace_clock_description(),
-               trace_clock_freq(),
-               measure_clock_offset()
-               );
-       if (ret) {
-               goto end;
-       }
+               if (clock._uuid) {
+                       char clock_uuid_str[LTTNG_UUID_STR_LEN];
 
-       ret = lttng_metadata_printf(session,
-               "typealias integer {\n"
-               "       size = 27; align = 1; signed = false;\n"
-               "       map = clock.%s.value;\n"
-               "} := uint27_clock_monotonic_t;\n"
-               "\n"
-               "typealias integer {\n"
-               "       size = 32; align = %u; signed = false;\n"
-               "       map = clock.%s.value;\n"
-               "} := uint32_clock_monotonic_t;\n"
-               "\n"
-               "typealias integer {\n"
-               "       size = 64; align = %u; signed = false;\n"
-               "       map = clock.%s.value;\n"
-               "} := uint64_clock_monotonic_t;\n\n",
-               trace_clock_name(),
-               session->_uint32_t_alignment,
-               trace_clock_name(),
-               session->_uint64_t_alignment,
-               trace_clock_name()
-               );
-       if (ret) {
+                       lttng_uuid_to_str(*clock._uuid, clock_uuid_str);
+                       ret = lttng_metadata_printf(
+                               session, "      uuid = \"%s\";\n", clock_uuid_str);
+                       if (ret) {
+                               goto end;
+                       }
+               }
+
+               ret = lttng_metadata_printf(session,
+                               "       description = \"%s\";\n"
+                               "       freq = %" PRIu64 "; /* Frequency, in Hz */\n"
+                               "       /* clock value offset from Epoch is: offset * (1/freq) */\n"
+                               "       offset = %" PRId64 ";\n"
+                               "};\n\n",
+                               clock._description.c_str(), clock._frequency, clock._offset);
+               if (ret) {
+                       goto end;
+               }
+
+               ret = lttng_metadata_printf(session,
+                               "typealias integer {\n"
+                               "       size = 27; align = 1; signed = false;\n"
+                               "       map = clock.%s.value;\n"
+                               "} := uint27_clock_monotonic_t;\n"
+                               "\n"
+                               "typealias integer {\n"
+                               "       size = 32; align = %u; signed = false;\n"
+                               "       map = clock.%s.value;\n"
+                               "} := uint32_clock_monotonic_t;\n"
+                               "\n"
+                               "typealias integer {\n"
+                               "       size = 64; align = %u; signed = false;\n"
+                               "       map = clock.%s.value;\n"
+                               "} := uint64_clock_monotonic_t;\n\n",
+                               clock._name.c_str(), session->_uint32_t_alignment,
+                               clock._name.c_str(), session->_uint64_t_alignment,
+                               clock._name.c_str());
+               if (ret) {
+                       goto end;
+               }
+       } catch (const std::exception &ex) {
+               ERR("Failed to serialize clock description: %s", ex.what());
+               ret = -1;
                goto end;
        }
 
This page took 0.035078 seconds and 5 git commands to generate.