docs: Add supported versions and fix-backport policy
[lttng-tools.git] / src / bin / lttng-sessiond / ust-clock-class.cpp
CommitLineData
b3647fb8
JG
1/*
2 * Copyright (C) 2010 Pierre-Marc Fournier
3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * Copyright (C) 2022 Jérémie Galarneau <jeremie.galarneau@efficios.com>
5 *
6 * SPDX-License-Identifier: GPL-2.0-only
7 *
8 */
9
d7bfb9b0 10#include "ust-clock-class.hpp"
b3647fb8 11
b3647fb8 12#include <common/exception.hpp>
28ab034a 13#include <common/time.hpp>
b3647fb8 14
d7bfb9b0
JG
15#include <lttng/ust-clock.h>
16
28ab034a 17#define CLOCK_OFFSET_SAMPLE_COUNT 10
b3647fb8 18
d7bfb9b0
JG
19namespace lst = lttng::sessiond::trace;
20
b3647fb8
JG
21namespace {
22struct offset_sample {
23 /* correlation offset */
d7bfb9b0 24 lst::clock_class::scycles_t offset;
b3647fb8 25 /* lower is better */
d7bfb9b0 26 lst::clock_class::cycles_t measure_delta;
b3647fb8
JG
27};
28
d7bfb9b0 29lst::clock_class::cycles_t sample_clock_read64()
b3647fb8
JG
30{
31 lttng_ust_clock_read64_function read64_cb;
32
33 if (lttng_ust_trace_clock_get_read64_cb(&read64_cb)) {
34 LTTNG_THROW_ERROR("Failed to get clock sample callback");
35 }
36
37 return read64_cb();
38}
39
d7bfb9b0 40lst::clock_class::cycles_t sample_clock_frequency()
b3647fb8
JG
41{
42 lttng_ust_clock_freq_function get_freq_cb;
43
44 if (lttng_ust_trace_clock_get_freq_cb(&get_freq_cb)) {
45 LTTNG_THROW_ERROR("Failed to get clock frequency callback");
46 }
47
48 return get_freq_cb();
49}
50
51nonstd::optional<lttng_uuid> sample_clock_uuid()
52{
53 lttng_ust_clock_uuid_function get_uuid_cb;
54
55 if (lttng_ust_trace_clock_get_uuid_cb(&get_uuid_cb)) {
56 return nonstd::nullopt;
57 }
58
59 char uuid_str[LTTNG_UUID_STR_LEN];
60 if (get_uuid_cb(uuid_str)) {
61 return nonstd::nullopt;
62 }
63
64 lttng_uuid uuid;
65 if (lttng_uuid_from_str(uuid_str, uuid)) {
66 LTTNG_THROW_ERROR("Failed to parse UUID from string");
67 }
68
28ab034a 69 return nonstd::optional<lttng_uuid>{ uuid };
b3647fb8
JG
70}
71
72const char *sample_clock_name()
73{
74 lttng_ust_clock_name_function get_name_cb;
75
76 if (lttng_ust_trace_clock_get_name_cb(&get_name_cb)) {
77 LTTNG_THROW_ERROR("Failed to get clock name callback");
78 }
79
80 const auto name = get_name_cb();
81 if (!name) {
28ab034a
JG
82 LTTNG_THROW_ERROR(
83 "Invalid clock name returned by LTTng-UST `lttng_ust_clock_name_function`");
b3647fb8
JG
84 }
85
86 return name;
87}
88
89const char *sample_clock_description()
90{
91 lttng_ust_clock_description_function get_description_cb;
92
93 if (lttng_ust_trace_clock_get_description_cb(&get_description_cb)) {
94 LTTNG_THROW_ERROR("Failed to get clock description callback");
95 }
96
97 const auto description = get_description_cb();
98 if (!description) {
28ab034a
JG
99 LTTNG_THROW_ERROR(
100 "Invalid clock description returned by LTTng-UST `lttng_ust_clock_description_function`");
b3647fb8
JG
101 }
102
103 return description;
104}
105
106/*
107 * The offset between monotonic and realtime clock can be negative if
108 * the system sets the REALTIME clock to 0 after boot.
109 */
110void measure_single_clock_offset(struct offset_sample *sample)
111{
28ab034a 112 lst::clock_class::cycles_t monotonic_avg, monotonic[2], measure_delta, realtime;
b3647fb8
JG
113 const auto tcf = sample_clock_frequency();
114 struct timespec rts = { 0, 0 };
115
116 monotonic[0] = sample_clock_read64();
117 if (lttng_clock_gettime(CLOCK_REALTIME, &rts)) {
118 LTTNG_THROW_POSIX("Failed to sample time from clock", errno);
119 }
120
121 monotonic[1] = sample_clock_read64();
122 measure_delta = monotonic[1] - monotonic[0];
123 if (measure_delta > sample->measure_delta) {
124 /*
125 * Discard value if it took longer to read than the best
126 * sample so far.
127 */
128 return;
129 }
130
131 monotonic_avg = (monotonic[0] + monotonic[1]) >> 1;
d7bfb9b0 132 realtime = (lst::clock_class::cycles_t) rts.tv_sec * tcf;
b3647fb8
JG
133 if (tcf == NSEC_PER_SEC) {
134 realtime += rts.tv_nsec;
135 } else {
28ab034a 136 realtime += (lst::clock_class::cycles_t) rts.tv_nsec * tcf / NSEC_PER_SEC;
b3647fb8
JG
137 }
138
d7bfb9b0 139 sample->offset = (lst::clock_class::scycles_t) realtime - monotonic_avg;
b3647fb8
JG
140 sample->measure_delta = measure_delta;
141}
142
143/*
144 * Approximation of NTP time of day to clock monotonic correlation,
145 * taken at start of trace. Keep the measurement that took the less time
146 * to complete, thus removing imprecision caused by preemption.
147 * May return a negative offset.
148 */
cd9adb8b 149lst::clock_class::scycles_t measure_clock_offset()
b3647fb8
JG
150{
151 struct offset_sample offset_best_sample = {
152 .offset = 0,
153 .measure_delta = UINT64_MAX,
154 };
155
156 for (auto i = 0; i < CLOCK_OFFSET_SAMPLE_COUNT; i++) {
157 measure_single_clock_offset(&offset_best_sample);
158 }
159
160 return offset_best_sample.offset;
161}
d7bfb9b0
JG
162} /* namespace */
163
164lttng::sessiond::ust::clock_class::clock_class() :
165 lst::clock_class(sample_clock_name(),
28ab034a
JG
166 sample_clock_description(),
167 sample_clock_uuid(),
168 measure_clock_offset(),
169 sample_clock_frequency())
b3647fb8
JG
170{
171}
This page took 0.044475 seconds and 4 git commands to generate.