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