summaryrefslogtreecommitdiff
path: root/src/nm-logging.h
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-01-16 16:40:45 +0100
committerThomas Haller <thaller@redhat.com>2019-02-05 08:18:08 +0100
commitfcfd4f4ff29b1399da5e88da32787725a8d193a8 (patch)
tree99719a035a5a9d66db622f81ee576041ee5ea21a /src/nm-logging.h
parent834c092b51d6bb1f4e0ef4c1eedb018acd9a0b3b (diff)
downloadNetworkManager-fcfd4f4ff29b1399da5e88da32787725a8d193a8.tar.gz
logging: make nm-logging thread-safe
NetworkManager is single-threaded and uses a mainloop. However, sometimes we may need multiple threads. For example, we will need to write sysctl values asynchronously, using the glib thread-pool. For that to work, we also need to switch the network-namespace of the thread-pool thread. We want to use NMPNetns for that. Hence it's better to have NMPNetns thread-safe, instead of coming up with a duplicate implementation. But NMPNetns may want to log, so we also need nm-logging thread-safe. In general, code under "shared/nm-utils" and nm-logging should be usable from multiple threads. It's simpler to make this code thread-safe than re-implementing it. Also, it's a bad limitation to be unable to log from other threads. If there is an error, the best we can often do is to log about it. Make nm-logging thread-safe. Actually, we only need to be able to log from multiple threads. We don't need to setup or configure logging from multiple threads. This restriction allows us to access logging from the main-thread without any thread-synchronization (because all changes in the logging setup are also done from the main-thread). So, while logging from other threads requires a mutex, logging from the main-thread is lock-free.
Diffstat (limited to 'src/nm-logging.h')
-rw-r--r--src/nm-logging.h31
1 files changed, 28 insertions, 3 deletions
diff --git a/src/nm-logging.h b/src/nm-logging.h
index e7b307c23e..a824890a1c 100644
--- a/src/nm-logging.h
+++ b/src/nm-logging.h
@@ -54,10 +54,12 @@ LOGD_IP_from_af (int addr_family)
/* A wrapper for the _nm_log_impl() function that adds call site information.
* Contrary to nm_log(), it unconditionally calls the function without
* checking whether logging for the given level and domain is enabled. */
-#define _nm_log(level, domain, error, ifname, con_uuid, ...) \
+#define _nm_log_mt(mt_require_locking, level, domain, error, ifname, con_uuid, ...) \
G_STMT_START { \
- _nm_log_impl (__FILE__, __LINE__, \
+ _nm_log_impl (__FILE__, \
+ __LINE__, \
_NM_LOG_FUNC, \
+ (mt_require_locking), \
(level), \
(domain), \
(error), \
@@ -66,6 +68,9 @@ LOGD_IP_from_af (int addr_family)
""__VA_ARGS__); \
} G_STMT_END
+#define _nm_log(level, domain, error, ifname, con_uuid, ...) \
+ _nm_log_mt (!(NM_THREAD_SAFE_ON_MAIN_THREAD), level, domain, error, ifname, con_uuid, __VA_ARGS__)
+
/* nm_log() only evaluates its argument list after checking
* whether logging for the given level/domain is enabled. */
#define nm_log(level, domain, ifname, con_uuid, ...) \
@@ -138,15 +143,35 @@ _nm_log_ptr_is_debug (NMLogLevel level)
const char *nm_logging_level_to_string (void);
const char *nm_logging_domains_to_string (void);
+/*****************************************************************************/
+
extern NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL];
+
static inline gboolean
-nm_logging_enabled (NMLogLevel level, NMLogDomain domain)
+_nm_logging_enabled_lockfree (NMLogLevel level, NMLogDomain domain)
{
nm_assert (((guint) level) < G_N_ELEMENTS (_nm_logging_enabled_state));
return (((guint) level) < G_N_ELEMENTS (_nm_logging_enabled_state))
&& !!(_nm_logging_enabled_state[level] & domain);
}
+gboolean _nm_logging_enabled_locking (NMLogLevel level, NMLogDomain domain);
+
+static inline gboolean
+nm_logging_enabled_mt (gboolean mt_require_locking, NMLogLevel level, NMLogDomain domain)
+{
+ if (mt_require_locking)
+ return _nm_logging_enabled_locking (level, domain);
+
+ NM_ASSERT_ON_MAIN_THREAD ();
+ return _nm_logging_enabled_lockfree (level, domain);
+}
+
+#define nm_logging_enabled(level, domain) \
+ nm_logging_enabled_mt (!(NM_THREAD_SAFE_ON_MAIN_THREAD), level, domain)
+
+/*****************************************************************************/
+
NMLogLevel nm_logging_get_level (NMLogDomain domain);
const char *nm_logging_all_levels_to_string (void);