Move the clock plugin implementation to liblttng-ust-common
[lttng-ust.git] / src / lib / lttng-ust-common / clock.c
1 /*
2 * SPDX-License-Identifier: LGPL-2.1-only
3 *
4 * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 */
6
7 #define _LGPL_SOURCE
8 #include <dlfcn.h>
9 #include <stdlib.h>
10 #include <stdint.h>
11 #include <stdio.h>
12
13 #include <lttng/ust-clock.h>
14 #include <lttng/ust-events.h>
15 #include <urcu/system.h>
16 #include <urcu/arch.h>
17
18 #include "common/logging.h"
19 #include "common/getenv.h"
20
21 #include "lib/lttng-ust-common/clock.h"
22
23 struct lttng_ust_trace_clock *lttng_ust_trace_clock;
24
25 static
26 struct lttng_ust_trace_clock user_tc;
27
28 static
29 void *clock_handle;
30
31 static
32 uint64_t trace_clock_freq_monotonic(void)
33 {
34 return 1000000000ULL;
35 }
36
37 static
38 int trace_clock_uuid_monotonic(char *uuid)
39 {
40 int ret = 0;
41 size_t len;
42 FILE *fp;
43
44 /*
45 * boot_id needs to be read once before being used concurrently
46 * to deal with a Linux kernel race. A fix is proposed for
47 * upstream, but the work-around is needed for older kernels.
48 */
49 fp = fopen("/proc/sys/kernel/random/boot_id", "r");
50 if (!fp) {
51 return -ENOENT;
52 }
53 len = fread(uuid, 1, LTTNG_UST_UUID_STR_LEN - 1, fp);
54 if (len < LTTNG_UST_UUID_STR_LEN - 1) {
55 ret = -EINVAL;
56 goto end;
57 }
58 uuid[LTTNG_UST_UUID_STR_LEN - 1] = '\0';
59 end:
60 fclose(fp);
61 return ret;
62 }
63
64 static
65 const char *trace_clock_name_monotonic(void)
66 {
67 return "monotonic";
68 }
69
70 static
71 const char *trace_clock_description_monotonic(void)
72 {
73 return "Monotonic Clock";
74 }
75
76 int lttng_ust_trace_clock_set_read64_cb(lttng_ust_clock_read64_function read64_cb)
77 {
78 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
79 return -EBUSY;
80 user_tc.read64 = read64_cb;
81 return 0;
82 }
83
84 int lttng_ust_trace_clock_get_read64_cb(lttng_ust_clock_read64_function *read64_cb)
85 {
86 struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock);
87
88 if (caa_likely(!ltc)) {
89 *read64_cb = &trace_clock_read64_monotonic;
90 } else {
91 cmm_read_barrier_depends(); /* load ltc before content */
92 *read64_cb = ltc->read64;
93 }
94 return 0;
95 }
96
97 int lttng_ust_trace_clock_set_freq_cb(lttng_ust_clock_freq_function freq_cb)
98 {
99 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
100 return -EBUSY;
101 user_tc.freq = freq_cb;
102 return 0;
103 }
104
105 int lttng_ust_trace_clock_get_freq_cb(lttng_ust_clock_freq_function *freq_cb)
106 {
107 struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock);
108
109 if (caa_likely(!ltc)) {
110 *freq_cb = &trace_clock_freq_monotonic;
111 } else {
112 cmm_read_barrier_depends(); /* load ltc before content */
113 *freq_cb = ltc->freq;
114 }
115 return 0;
116 }
117
118 int lttng_ust_trace_clock_set_uuid_cb(lttng_ust_clock_uuid_function uuid_cb)
119 {
120 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
121 return -EBUSY;
122 user_tc.uuid = uuid_cb;
123 return 0;
124 }
125
126 int lttng_ust_trace_clock_get_uuid_cb(lttng_ust_clock_uuid_function *uuid_cb)
127 {
128 struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock);
129
130 if (caa_likely(!ltc)) {
131 *uuid_cb = &trace_clock_uuid_monotonic;
132 } else {
133 cmm_read_barrier_depends(); /* load ltc before content */
134 *uuid_cb = ltc->uuid;
135 }
136 return 0;
137 }
138
139 int lttng_ust_trace_clock_set_name_cb(lttng_ust_clock_name_function name_cb)
140 {
141 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
142 return -EBUSY;
143 user_tc.name = name_cb;
144 return 0;
145 }
146
147 int lttng_ust_trace_clock_get_name_cb(lttng_ust_clock_name_function *name_cb)
148 {
149 struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock);
150
151 if (caa_likely(!ltc)) {
152 *name_cb = &trace_clock_name_monotonic;
153 } else {
154 cmm_read_barrier_depends(); /* load ltc before content */
155 *name_cb = ltc->name;
156 }
157 return 0;
158 }
159
160 int lttng_ust_trace_clock_set_description_cb(lttng_ust_clock_description_function description_cb)
161 {
162 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
163 return -EBUSY;
164 user_tc.description = description_cb;
165 return 0;
166 }
167
168 int lttng_ust_trace_clock_get_description_cb(lttng_ust_clock_description_function *description_cb)
169 {
170 struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock);
171
172 if (caa_likely(!ltc)) {
173 *description_cb = &trace_clock_description_monotonic;
174 } else {
175 cmm_read_barrier_depends(); /* load ltc before content */
176 *description_cb = ltc->description;
177 }
178 return 0;
179 }
180
181 int lttng_ust_enable_trace_clock_override(void)
182 {
183 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
184 return -EBUSY;
185 if (!user_tc.read64)
186 return -EINVAL;
187 if (!user_tc.freq)
188 return -EINVAL;
189 if (!user_tc.name)
190 return -EINVAL;
191 if (!user_tc.description)
192 return -EINVAL;
193 /* Use default uuid cb when NULL */
194 cmm_smp_mb(); /* Store callbacks before trace clock */
195 CMM_STORE_SHARED(lttng_ust_trace_clock, &user_tc);
196 return 0;
197 }
198
199 void lttng_ust_clock_init(void)
200 {
201 const char *libname;
202 void (*libinit)(void);
203
204 if (clock_handle)
205 return;
206 libname = lttng_ust_getenv("LTTNG_UST_CLOCK_PLUGIN");
207 if (!libname)
208 return;
209 clock_handle = dlopen(libname, RTLD_NOW);
210 if (!clock_handle) {
211 PERROR("Cannot load LTTng UST clock override library %s",
212 libname);
213 return;
214 }
215 dlerror();
216 libinit = (void (*)(void)) dlsym(clock_handle,
217 "lttng_ust_clock_plugin_init");
218 if (!libinit) {
219 PERROR("Cannot find LTTng UST clock override library %s initialization function lttng_ust_clock_plugin_init()",
220 libname);
221 return;
222 }
223 libinit();
224 }
This page took 0.033293 seconds and 4 git commands to generate.