Change-Id: Idebb709fe4dd5501dfe657ea23fc6a67a65ce1ff
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
#include <stdbool.h>
#include <stddef.h>
#include <sys/types.h>
#include <stdbool.h>
#include <stddef.h>
#include <sys/types.h>
#include <urcu/system.h>
#include "common/logging.h"
#include "common/macros.h"
#include <urcu/system.h>
#include "common/logging.h"
#include "common/macros.h"
-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[] = {
/*
static struct lttng_env lttng_env[] = {
/*
- 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();
+ }
+
+ 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];
for (i = 0; i < LTTNG_ARRAY_SIZE(lttng_env); i++) {
struct lttng_env *e = <tng_env[i];
}
e->value = getenv(e->key);
}
}
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);
CMM_STORE_SHARED(lttng_ust_getenv_is_init, 1);
+end_init:
+ pthread_mutex_unlock(<tng_ust_getenv_init_mutex);