* Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*/
+#include <urcu/compiler.h>
+#include <urcu/system.h>
+
#include "common/logging.h"
-volatile enum lttng_ust_log_level lttng_ust_log_level;
+int lttng_ust_log_level = LTTNG_UST_LOG_LEVEL_UNKNOWN;
-void lttng_ust_logging_init(void)
+/*
+ * Initialize the global log level from the "LTTNG_UST_DEBUG" environment
+ * variable.
+ *
+ * This could end up being called concurently by multiple threads but doesn't
+ * require a mutex since the input is invariant across threads and the result
+ * will be the same.
+ *
+ * Return the current log level to save the caller a second read of the global
+ * log level.
+ */
+int lttng_ust_logging_init(void)
{
char *lttng_ust_debug;
+ int current_log_level;
+
+ current_log_level = CMM_LOAD_SHARED(lttng_ust_log_level);
+
+ /*
+ * Check early if we are initialized, this is unlikely as it's already tested
+ * in lttng_ust_debug_enabled before performing lazy initialization.
+ */
+ if (caa_unlikely(current_log_level != LTTNG_UST_LOG_LEVEL_UNKNOWN))
+ goto end;
+
+ /*
+ * This getenv is not part of lttng_ust_getenv() because logging is
+ * used in the getenv initialization and thus logging must be
+ * initialized prior to getenv.
+ */
+ lttng_ust_debug = getenv("LTTNG_UST_DEBUG");
+
+ /*
+ * If the LTTNG_UST_DEBUG environment variable is defined, print all
+ * messages, otherwise print nothing.
+ */
+ if (lttng_ust_debug)
+ current_log_level = LTTNG_UST_LOG_LEVEL_DEBUG;
+ else
+ current_log_level = LTTNG_UST_LOG_LEVEL_SILENT;
+
+ /* Initialize the log level */
+ CMM_STORE_SHARED(lttng_ust_log_level, current_log_level);
- if (lttng_ust_log_level == LTTNG_UST_LOG_LEVEL_UNKNOWN) {
- /*
- * This getenv is not part of lttng_ust_getenv() because it
- * is required to print ERR() performed during getenv
- * initialization.
- */
- lttng_ust_debug = getenv("LTTNG_UST_DEBUG");
- if (lttng_ust_debug)
- lttng_ust_log_level = LTTNG_UST_LOG_LEVEL_DEBUG;
- else
- lttng_ust_log_level = LTTNG_UST_LOG_LEVEL_NORMAL;
- }
+end:
+ return current_log_level;
}
#include <stdio.h>
#include <lttng/ust-utils.h>
+#include <urcu/compiler.h>
+#include <urcu/system.h>
#include "common/patient.h"
#include "common/compat/tid.h"
enum lttng_ust_log_level {
LTTNG_UST_LOG_LEVEL_UNKNOWN = 0,
- LTTNG_UST_LOG_LEVEL_NORMAL,
+ LTTNG_UST_LOG_LEVEL_SILENT,
LTTNG_UST_LOG_LEVEL_DEBUG,
};
-extern volatile enum lttng_ust_log_level lttng_ust_log_level
+extern int lttng_ust_log_level /* enum lttng_ust_log_level */
__attribute__((visibility("hidden")));
-void lttng_ust_logging_init(void)
+/*
+ * Initialize the global log level from the "LTTNG_UST_DEBUG" environment
+ * variable.
+ *
+ * This could end up being called concurrently by multiple threads but doesn't
+ * require a mutex since the input is invariant across threads and the result
+ * will be the same.
+ *
+ * Return the current log level to save the caller a second read of the global
+ * log level.
+ */
+int lttng_ust_logging_init(void)
__attribute__((visibility("hidden")));
#ifdef LTTNG_UST_DEBUG
-static inline bool lttng_ust_logging_debug_enabled(void)
+static inline
+bool lttng_ust_logging_debug_enabled(void)
{
return true;
}
#else /* #ifdef LTTNG_UST_DEBUG */
-static inline bool lttng_ust_logging_debug_enabled(void)
+static inline
+bool lttng_ust_logging_debug_enabled(void)
{
- return lttng_ust_log_level == LTTNG_UST_LOG_LEVEL_DEBUG;
+ int current_log_level;
+
+ current_log_level = CMM_LOAD_SHARED(lttng_ust_log_level);
+
+ /* If the global log level is unknown, lazy-initialize it. */
+ if (caa_unlikely(current_log_level == LTTNG_UST_LOG_LEVEL_UNKNOWN))
+ current_log_level = lttng_ust_logging_init();
+
+ return current_log_level == LTTNG_UST_LOG_LEVEL_DEBUG;
}
-#endif /* #else #ifdef LTTNG_UST_DEBUG */
+#endif /* #ifdef LTTNG_UST_DEBUG */
/*
* The default component for error messages.
static
void lttng_ust_common_init(void)
{
- /* Initialize logging for liblttng-ust-common */
- lttng_ust_logging_init();
-
/*
* Initialize the fd-tracker, other libraries using it should also call
* this in their constructor in case it gets executed before this one.
static
void ustctl_init(void)
{
- lttng_ust_logging_init();
- lttng_ust_getenv_init(); /* Needs lttng_ust_logging_init() to be completed. */
lttng_ust_clock_init();
lttng_ust_ring_buffer_clients_init();
lttng_ust_counter_clients_init();
#endif
static int (*__lttng_ust_plibc_dlclose)(void *handle);
-static
-void _lttng_ust_dl_init(void)
- __attribute__((constructor));
-static
-void _lttng_ust_dl_init(void)
-{
- lttng_ust_logging_init();
-}
-
static
void *_lttng_ust_dl_libc_dlopen(const char *filename, int flags)
{
* sessiond (otherwise leading to errors when trying to create
* sessiond before the init functions are completed).
*/
+
+ /*
+ * Both the logging and getenv lazy-initialization uses getenv()
+ * internally and thus needs to be explicitly initialized in
+ * liblttng-ust before we start any threads as an unsuspecting normally
+ * single threaded application using liblttng-ust could be using
+ * setenv() which is not thread-safe.
+ */
lttng_ust_logging_init();
- lttng_ust_getenv_init(); /* Needs lttng_ust_logging_init() to be completed. */
+ lttng_ust_getenv_init();
+
lttng_ust_tp_init();
lttng_ust_init_fd_tracker();
lttng_ust_clock_init();