From: Mathieu Desnoyers Date: Fri, 16 Apr 2021 16:02:01 +0000 (-0400) Subject: getenv: make getenv helper init state mt-safe X-Git-Tag: v2.13.0-rc1~90 X-Git-Url: http://git.liburcu.org/?a=commitdiff_plain;ds=sidebyside;h=042dbbc86aaf0d25b4922ecf268f406d31cd8986;p=lttng-ust.git getenv: make getenv helper init state mt-safe Change-Id: Idebb709fe4dd5501dfe657ea23fc6a67a65ce1ff Signed-off-by: Mathieu Desnoyers --- diff --git a/src/common/getenv.c b/src/common/getenv.c index 23029508..bc7a4d4a 100644 --- a/src/common/getenv.c +++ b/src/common/getenv.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "common/logging.h" #include "common/macros.h" @@ -25,8 +26,9 @@ struct lttng_env { char *value; }; -static -int lttng_ust_getenv_is_init = 0; +/* lttng_ust_getenv_init_mutex provides mutual exclusion for initialization. */ +static pthread_mutex_t lttng_ust_getenv_init_mutex = PTHREAD_MUTEX_INITIALIZER; +static int lttng_ust_getenv_is_init = 0; static struct lttng_env lttng_env[] = { /* @@ -88,8 +90,25 @@ void lttng_ust_getenv_init(void) { size_t i; - if (CMM_LOAD_SHARED(lttng_ust_getenv_is_init)) + /* + * Return early if the init has already completed. + */ + if (CMM_LOAD_SHARED(lttng_ust_getenv_is_init)) { + /* + * Load lttng_ust_getenv_is_init before reading environment cache. + */ + cmm_smp_rmb(); return; + } + + pthread_mutex_lock(<tng_ust_getenv_init_mutex); + + /* + * Check again if the init has completed in another thread now that we + * have acquired the mutex. + */ + if (lttng_ust_getenv_is_init) + goto end_init; for (i = 0; i < LTTNG_ARRAY_SIZE(lttng_env); i++) { struct lttng_env *e = <tng_env[i]; @@ -101,5 +120,12 @@ void lttng_ust_getenv_init(void) } e->value = getenv(e->key); } + + /* + * Store environment cache before setting lttng_ust_getenv_is_init to 1. + */ + cmm_smp_wmb(); CMM_STORE_SHARED(lttng_ust_getenv_is_init, 1); +end_init: + pthread_mutex_unlock(<tng_ust_getenv_init_mutex); }