From b3647fb885288c63d21478ea9a9c85685bc5c5f2 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=A9mie=20Galarneau?= Date: Mon, 2 May 2022 15:35:40 -0400 Subject: [PATCH] sessiond: Move trace_ust_clock to a clock_attributes_sample class MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 --- src/bin/lttng-sessiond/Makefile.am | 3 +- src/bin/lttng-sessiond/ust-clock.cpp | 167 ++++++++++++++++++++ src/bin/lttng-sessiond/ust-clock.hpp | 104 +++---------- src/bin/lttng-sessiond/ust-metadata.cpp | 193 ++++++++---------------- 4 files changed, 256 insertions(+), 211 deletions(-) create mode 100644 src/bin/lttng-sessiond/ust-clock.cpp diff --git a/src/bin/lttng-sessiond/Makefile.am b/src/bin/lttng-sessiond/Makefile.am index 0fdd6775a..5b5047f43 100644 --- a/src/bin/lttng-sessiond/Makefile.am +++ b/src/bin/lttng-sessiond/Makefile.am @@ -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 index 000000000..3d853ad50 --- /dev/null +++ b/src/bin/lttng-sessiond/ust-clock.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2010 Pierre-Marc Fournier + * Copyright (C) 2011 Mathieu Desnoyers + * Copyright (C) 2022 Jérémie Galarneau + * + * SPDX-License-Identifier: GPL-2.0-only + * + */ + +#include "ust-clock.hpp" + +#include +#include + +#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 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{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()} +{ +} diff --git a/src/bin/lttng-sessiond/ust-clock.hpp b/src/bin/lttng-sessiond/ust-clock.hpp index 3807f40a3..7b9034173 100644 --- a/src/bin/lttng-sessiond/ust-clock.hpp +++ b/src/bin/lttng-sessiond/ust-clock.hpp @@ -1,6 +1,7 @@ /* * Copyright (C) 2010 Pierre-Marc Fournier * Copyright (C) 2011 Mathieu Desnoyers + * Copyright (C) 2022 Jérémie Galarneau * * SPDX-License-Identifier: GPL-2.0-only * @@ -10,93 +11,36 @@ #define _UST_CLOCK_H #include -#include -#include +#include +#include + +#include #include +#include #include -#include +#include +#include #include -#include - -#include - -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 - 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 _uuid; + const scycles_t _offset; + const cycles_t _frequency; +}; - description = get_description_cb(); -end: - return description; -} +} /* namespace ust */ +} /* namespace lttng */ #endif /* _UST_CLOCK_H */ diff --git a/src/bin/lttng-sessiond/ust-metadata.cpp b/src/bin/lttng-sessiond/ust-metadata.cpp index 64c48cb2d..edbad7783 100644 --- a/src/bin/lttng-sessiond/ust-metadata.cpp +++ b/src/bin/lttng-sessiond/ust-metadata.cpp @@ -6,31 +6,23 @@ */ #define _LGPL_SOURCE -#include -#include +#include +#include #include +#include #include -#include +#include #include -#include +#include + #include +#include #include -#include +#include -#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; } -- 2.34.1