From 33b563d60bb08300f2879a7c67f5f6483ccf3943 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Tue, 23 Mar 2021 11:58:52 -0400 Subject: [PATCH 1/1] clock override: introduce getter API for lttng tools Currently, the lttng session daemon reimplements its own copy of struct lttng_trace_clock, which is pretty bad as ABI go. Implement getter functions for each of the clock callback instead. This refactoring needs to be introduced with a matching commit to use the new ABI in LTTng tools. Move the implementation of the clock frequency, uuid, name and description default callbacks (for monotonic clock) to lttng-ust. This allow to hide the previously exposed "lttng_trace_clock" public symbol. Rename this internal symbol to lttng_ust_trace_clock for prefix consistency. Rename struct lttng_trace_clock to struct lttng_ust_trace_clock for similar reasons. Signed-off-by: Mathieu Desnoyers Change-Id: I55825f0c0f5372a68aaaf06fb8dbd256cf248f2c --- include/lttng/ust-clock.h | 31 +++++--- liblttng-ust/clock.h | 7 +- liblttng-ust/lttng-clock.c | 149 ++++++++++++++++++++++++++++++++----- 3 files changed, 155 insertions(+), 32 deletions(-) diff --git a/include/lttng/ust-clock.h b/include/lttng/ust-clock.h index 44b249b0..d608a933 100644 --- a/include/lttng/ust-clock.h +++ b/include/lttng/ust-clock.h @@ -16,36 +16,47 @@ * success. */ +typedef uint64_t (*lttng_ust_clock_read64_function)(void); +typedef uint64_t (*lttng_ust_clock_freq_function)(void); +typedef int (*lttng_ust_clock_uuid_function)(char *uuid); +typedef const char *(*lttng_ust_clock_name_function)(void); +typedef const char *(*lttng_ust_clock_description_function)(void); + /* - * Set clock override read callback. This callback should return the + * Set/Get clock override read callback. This callback should return the * current clock time (a 64-bit monotonic counter). */ -int lttng_ust_trace_clock_set_read64_cb(uint64_t (*read64)(void)); +int lttng_ust_trace_clock_set_read64_cb(lttng_ust_clock_read64_function read64_cb); +int lttng_ust_trace_clock_get_read64_cb(lttng_ust_clock_read64_function *read64_cb); /* - * Set clock override frequency callback. This callback should return + * Set/Get clock override frequency callback. This callback should return * the frequency of the clock in cycles per second. */ -int lttng_ust_trace_clock_set_freq_cb(uint64_t (*freq)(void)); +int lttng_ust_trace_clock_set_freq_cb(lttng_ust_clock_freq_function freq_cb); +int lttng_ust_trace_clock_get_freq_cb(lttng_ust_clock_freq_function *freq_cb); /* - * Set clock override unique identifier. + * Set/Get clock override unique identifier. * LTTNG_UST_UUID_STR_LEN is the maximum length of uuid string. Includes * final \0. */ #define LTTNG_UST_UUID_STR_LEN 37 -int lttng_ust_trace_clock_set_uuid_cb(int (*uuid)(char *uuid)); +int lttng_ust_trace_clock_set_uuid_cb(lttng_ust_clock_uuid_function uuid_cb); +int lttng_ust_trace_clock_get_uuid_cb(lttng_ust_clock_uuid_function *uuid_cb); /* - * Set clock override name. + * Set/Get clock override name. */ -int lttng_ust_trace_clock_set_name_cb(const char *(*name)(void)); +int lttng_ust_trace_clock_set_name_cb(lttng_ust_clock_name_function name_cb); +int lttng_ust_trace_clock_get_name_cb(lttng_ust_clock_name_function *name_cb); /* - * Set clock override description. + * Set/Get clock override description. */ -int lttng_ust_trace_clock_set_description_cb(const char *(*description)(void)); +int lttng_ust_trace_clock_set_description_cb(lttng_ust_clock_description_function description_cb); +int lttng_ust_trace_clock_get_description_cb(lttng_ust_clock_description_function *description_cb); /* * Use the clock override rather than the default clock. diff --git a/liblttng-ust/clock.h b/liblttng-ust/clock.h index b68e563f..824df431 100644 --- a/liblttng-ust/clock.h +++ b/liblttng-ust/clock.h @@ -19,7 +19,7 @@ #include "lttng-ust-uuid.h" -struct lttng_trace_clock { +struct lttng_ust_trace_clock { uint64_t (*read64)(void); uint64_t (*freq)(void); int (*uuid)(char *uuid); @@ -27,7 +27,8 @@ struct lttng_trace_clock { const char *(*description)(void); }; -extern struct lttng_trace_clock *lttng_trace_clock; +__attribute__((visibility("hidden"))) +extern struct lttng_ust_trace_clock *lttng_ust_trace_clock; void lttng_ust_clock_init(void); @@ -48,7 +49,7 @@ uint64_t trace_clock_read64_monotonic(void) static __inline__ uint64_t trace_clock_read64(void) { - struct lttng_trace_clock *ltc = CMM_LOAD_SHARED(lttng_trace_clock); + struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock); if (caa_likely(!ltc)) { return trace_clock_read64_monotonic(); diff --git a/liblttng-ust/lttng-clock.c b/liblttng-ust/lttng-clock.c index 93a5075d..27ecccd9 100644 --- a/liblttng-ust/lttng-clock.c +++ b/liblttng-ust/lttng-clock.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -17,57 +18,167 @@ #include "clock.h" #include "getenv.h" -struct lttng_trace_clock *lttng_trace_clock; +struct lttng_ust_trace_clock *lttng_ust_trace_clock; static -struct lttng_trace_clock user_tc; +struct lttng_ust_trace_clock user_tc; static void *clock_handle; -int lttng_ust_trace_clock_set_read64_cb(uint64_t (*read64)(void)) +static +uint64_t trace_clock_freq_monotonic(void) { - if (CMM_LOAD_SHARED(lttng_trace_clock)) + return 1000000000ULL; +} + +static +int trace_clock_uuid_monotonic(char *uuid) +{ + int ret = 0; + size_t len; + FILE *fp; + + /* + * boot_id needs to be read once before being used concurrently + * to deal with a Linux kernel race. A fix is proposed for + * upstream, but the work-around is needed for older kernels. + */ + fp = fopen("/proc/sys/kernel/random/boot_id", "r"); + if (!fp) { + return -ENOENT; + } + len = fread(uuid, 1, LTTNG_UST_UUID_STR_LEN - 1, fp); + if (len < LTTNG_UST_UUID_STR_LEN - 1) { + ret = -EINVAL; + goto end; + } + uuid[LTTNG_UST_UUID_STR_LEN - 1] = '\0'; +end: + fclose(fp); + return ret; +} + +static +const char *trace_clock_name_monotonic(void) +{ + return "monotonic"; +} + +static +const char *trace_clock_description_monotonic(void) +{ + return "Monotonic Clock"; +} + +int lttng_ust_trace_clock_set_read64_cb(lttng_ust_clock_read64_function read64_cb) +{ + if (CMM_LOAD_SHARED(lttng_ust_trace_clock)) return -EBUSY; - user_tc.read64 = read64; + user_tc.read64 = read64_cb; + return 0; +} + +int lttng_ust_trace_clock_get_read64_cb(lttng_ust_clock_read64_function *read64_cb) +{ + struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock); + + if (caa_likely(!ltc)) { + *read64_cb = &trace_clock_read64_monotonic; + } else { + cmm_read_barrier_depends(); /* load ltc before content */ + *read64_cb = ltc->read64; + } return 0; } -int lttng_ust_trace_clock_set_freq_cb(uint64_t (*freq)(void)) +int lttng_ust_trace_clock_set_freq_cb(lttng_ust_clock_freq_function freq_cb) { - if (CMM_LOAD_SHARED(lttng_trace_clock)) + if (CMM_LOAD_SHARED(lttng_ust_trace_clock)) return -EBUSY; - user_tc.freq = freq; + user_tc.freq = freq_cb; return 0; } -int lttng_ust_trace_clock_set_uuid_cb(int (*uuid)(char *uuid)) +int lttng_ust_trace_clock_get_freq_cb(lttng_ust_clock_freq_function *freq_cb) { - if (CMM_LOAD_SHARED(lttng_trace_clock)) + struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock); + + if (caa_likely(!ltc)) { + *freq_cb = &trace_clock_freq_monotonic; + } else { + cmm_read_barrier_depends(); /* load ltc before content */ + *freq_cb = ltc->freq; + } + return 0; +} + +int lttng_ust_trace_clock_set_uuid_cb(lttng_ust_clock_uuid_function uuid_cb) +{ + if (CMM_LOAD_SHARED(lttng_ust_trace_clock)) return -EBUSY; - user_tc.uuid = uuid; + user_tc.uuid = uuid_cb; + return 0; +} + +int lttng_ust_trace_clock_get_uuid_cb(lttng_ust_clock_uuid_function *uuid_cb) +{ + struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock); + + if (caa_likely(!ltc)) { + *uuid_cb = &trace_clock_uuid_monotonic; + } else { + cmm_read_barrier_depends(); /* load ltc before content */ + *uuid_cb = ltc->uuid; + } return 0; } -int lttng_ust_trace_clock_set_name_cb(const char *(*name)(void)) +int lttng_ust_trace_clock_set_name_cb(lttng_ust_clock_name_function name_cb) { - if (CMM_LOAD_SHARED(lttng_trace_clock)) + if (CMM_LOAD_SHARED(lttng_ust_trace_clock)) return -EBUSY; - user_tc.name = name; + user_tc.name = name_cb; return 0; } -int lttng_ust_trace_clock_set_description_cb(const char *(*description)(void)) +int lttng_ust_trace_clock_get_name_cb(lttng_ust_clock_name_function *name_cb) { - if (CMM_LOAD_SHARED(lttng_trace_clock)) + struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock); + + if (caa_likely(!ltc)) { + *name_cb = &trace_clock_name_monotonic; + } else { + cmm_read_barrier_depends(); /* load ltc before content */ + *name_cb = ltc->name; + } + return 0; +} + +int lttng_ust_trace_clock_set_description_cb(lttng_ust_clock_description_function description_cb) +{ + if (CMM_LOAD_SHARED(lttng_ust_trace_clock)) return -EBUSY; - user_tc.description = description; + user_tc.description = description_cb; + return 0; +} + +int lttng_ust_trace_clock_get_description_cb(lttng_ust_clock_description_function *description_cb) +{ + struct lttng_ust_trace_clock *ltc = CMM_LOAD_SHARED(lttng_ust_trace_clock); + + if (caa_likely(!ltc)) { + *description_cb = &trace_clock_description_monotonic; + } else { + cmm_read_barrier_depends(); /* load ltc before content */ + *description_cb = ltc->description; + } return 0; } int lttng_ust_enable_trace_clock_override(void) { - if (CMM_LOAD_SHARED(lttng_trace_clock)) + if (CMM_LOAD_SHARED(lttng_ust_trace_clock)) return -EBUSY; if (!user_tc.read64) return -EINVAL; @@ -79,7 +190,7 @@ int lttng_ust_enable_trace_clock_override(void) return -EINVAL; /* Use default uuid cb when NULL */ cmm_smp_mb(); /* Store callbacks before trace clock */ - CMM_STORE_SHARED(lttng_trace_clock, &user_tc); + CMM_STORE_SHARED(lttng_ust_trace_clock, &user_tc); return 0; } -- 2.34.1