Move getenv to libcommon
[lttng-ust.git] / src / lib / lttng-ust / lttng-clock.c
CommitLineData
e11fcffc 1/*
c0c0989a 2 * SPDX-License-Identifier: LGPL-2.1-only
e11fcffc 3 *
c0c0989a 4 * Copyright (C) 2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
e11fcffc
MD
5 */
6
3fbec7dc 7#define _LGPL_SOURCE
e11fcffc
MD
8#include <error.h>
9#include <dlfcn.h>
10#include <stdlib.h>
fb31eb73 11#include <stdint.h>
33b563d6 12#include <stdio.h>
9d315d6d 13
e11fcffc
MD
14#include <lttng/ust-clock.h>
15#include <urcu/system.h>
16#include <urcu/arch.h>
17
9d315d6d
MJ
18#include "common/logging.h"
19
e11fcffc 20#include "clock.h"
910dcd72 21#include "common/getenv.h"
e11fcffc 22
33b563d6 23struct lttng_ust_trace_clock *lttng_ust_trace_clock;
e11fcffc
MD
24
25static
33b563d6 26struct lttng_ust_trace_clock user_tc;
e11fcffc 27
4bc1ccd7
MD
28static
29void *clock_handle;
30
33b563d6
MD
31static
32uint64_t trace_clock_freq_monotonic(void)
e11fcffc 33{
33b563d6
MD
34 return 1000000000ULL;
35}
36
37static
38int 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';
59end:
60 fclose(fp);
61 return ret;
62}
63
64static
65const char *trace_clock_name_monotonic(void)
66{
67 return "monotonic";
68}
69
70static
71const char *trace_clock_description_monotonic(void)
72{
73 return "Monotonic Clock";
74}
75
76int lttng_ust_trace_clock_set_read64_cb(lttng_ust_clock_read64_function read64_cb)
77{
78 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
e11fcffc 79 return -EBUSY;
33b563d6
MD
80 user_tc.read64 = read64_cb;
81 return 0;
82}
83
84int 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 }
e11fcffc
MD
94 return 0;
95}
96
33b563d6 97int lttng_ust_trace_clock_set_freq_cb(lttng_ust_clock_freq_function freq_cb)
e11fcffc 98{
33b563d6 99 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
e11fcffc 100 return -EBUSY;
33b563d6 101 user_tc.freq = freq_cb;
e11fcffc
MD
102 return 0;
103}
104
33b563d6 105int lttng_ust_trace_clock_get_freq_cb(lttng_ust_clock_freq_function *freq_cb)
e11fcffc 106{
33b563d6
MD
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
118int lttng_ust_trace_clock_set_uuid_cb(lttng_ust_clock_uuid_function uuid_cb)
119{
120 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
e11fcffc 121 return -EBUSY;
33b563d6
MD
122 user_tc.uuid = uuid_cb;
123 return 0;
124}
125
126int 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 }
e11fcffc
MD
136 return 0;
137}
138
33b563d6 139int lttng_ust_trace_clock_set_name_cb(lttng_ust_clock_name_function name_cb)
e11fcffc 140{
33b563d6 141 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
e11fcffc 142 return -EBUSY;
33b563d6 143 user_tc.name = name_cb;
e11fcffc
MD
144 return 0;
145}
146
33b563d6 147int lttng_ust_trace_clock_get_name_cb(lttng_ust_clock_name_function *name_cb)
e11fcffc 148{
33b563d6
MD
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
160int lttng_ust_trace_clock_set_description_cb(lttng_ust_clock_description_function description_cb)
161{
162 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
e11fcffc 163 return -EBUSY;
33b563d6
MD
164 user_tc.description = description_cb;
165 return 0;
166}
167
168int 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 }
e11fcffc
MD
178 return 0;
179}
180
181int lttng_ust_enable_trace_clock_override(void)
182{
33b563d6 183 if (CMM_LOAD_SHARED(lttng_ust_trace_clock))
e11fcffc
MD
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 */
33b563d6 195 CMM_STORE_SHARED(lttng_ust_trace_clock, &user_tc);
e11fcffc
MD
196 return 0;
197}
198
199void lttng_ust_clock_init(void)
200{
201 const char *libname;
e11fcffc
MD
202 void (*libinit)(void);
203
4bc1ccd7
MD
204 if (clock_handle)
205 return;
4c41b460 206 libname = lttng_ust_getenv("LTTNG_UST_CLOCK_PLUGIN");
e11fcffc
MD
207 if (!libname)
208 return;
4bc1ccd7
MD
209 clock_handle = dlopen(libname, RTLD_NOW);
210 if (!clock_handle) {
e11fcffc
MD
211 PERROR("Cannot load LTTng UST clock override library %s",
212 libname);
213 return;
214 }
215 dlerror();
4bc1ccd7 216 libinit = (void (*)(void)) dlsym(clock_handle,
e11fcffc
MD
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.037164 seconds and 4 git commands to generate.