From 0db20e45b71f4624f7268c5ba46ace4850f978df Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 15 Apr 2013 21:31:44 +0100 Subject: [PATCH 8/8] Add a statically-initialized implementation of _dbus_global_lock() on glibc systems --- dbus/dbus-sysdeps-pthread.c | 53 ++++++++++++++++++++++++++++++++++++++++++ dbus/dbus-threads-internal.h | 6 +++++ dbus/dbus-threads.c | 14 +++++++++++ 3 files changed, 73 insertions(+) diff --git a/dbus/dbus-sysdeps-pthread.c b/dbus/dbus-sysdeps-pthread.c index 47e7c0f..2115eb8 100644 --- a/dbus/dbus-sysdeps-pthread.c +++ b/dbus/dbus-sysdeps-pthread.c @@ -308,3 +308,56 @@ _dbus_threads_unlock_platform_specific (void) { pthread_mutex_unlock (&init_mutex); } + +#ifdef DBUS_HAVE_STATIC_RECURSIVE_MUTEXES + +static pthread_mutex_t global_locks[] = { + /* 0-4 */ + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + /* 5-9 */ + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + /* 10-11 */ + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP, + PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP +}; + +_DBUS_STATIC_ASSERT (_DBUS_N_ELEMENTS (global_locks) == _DBUS_N_GLOBAL_LOCKS); + +dbus_bool_t +_dbus_global_lock (DBusGlobalMutex mutex) +{ + _dbus_global_lock_cannot_fail (mutex); + return TRUE; +} + +void +_dbus_global_lock_cannot_fail (DBusGlobalMutex mutex) +{ + /* No initialization is needed. */ + _dbus_assert (mutex >= 0); + _dbus_assert (mutex < _DBUS_N_GLOBAL_LOCKS); + + PTHREAD_CHECK ("pthread_mutex_lock", + pthread_mutex_lock (&(global_locks[mutex]))); +} + +dbus_bool_t +_dbus_global_unlock (DBusGlobalMutex mutex) +{ + /* No initialization is needed. */ + _dbus_assert (mutex >= 0); + _dbus_assert (mutex < _DBUS_N_GLOBAL_LOCKS); + + PTHREAD_CHECK ("pthread_mutex_unlock", + pthread_mutex_unlock (&(global_locks[mutex]))); +} + +#endif diff --git a/dbus/dbus-threads-internal.h b/dbus/dbus-threads-internal.h index 79a0be9..3df4547 100644 --- a/dbus/dbus-threads-internal.h +++ b/dbus/dbus-threads-internal.h @@ -58,6 +58,12 @@ typedef enum { _DBUS_LOCK_INVALID = 10000 } DBusGlobalMutex; +/* glibc can implement global locks without needing an initialization step, + * which improves our thread-safety-by-default further. */ +#if defined(__GLIBC__) && defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) +# define DBUS_HAVE_STATIC_RECURSIVE_MUTEXES 1 +#endif + /** * A mutex which is recursive if possible, else non-recursive. * This is typically recursive, but that cannot be relied upon. diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c index f4c068e..e67454d 100644 --- a/dbus/dbus-threads.c +++ b/dbus/dbus-threads.c @@ -301,6 +301,18 @@ _dbus_condvar_wake_one (DBusCondVar *cond) _dbus_platform_condvar_wake_one (cond); } +#ifdef DBUS_HAVE_STATIC_RECURSIVE_MUTEXES + +static dbus_bool_t +init_global_locks (void) +{ + return TRUE; +} + +/* implementations in dbus-sysdeps-pthread.c */ + +#else /* !defined(DBUS_HAVE_STATIC_RECURSIVE_MUTEXES) */ + /* All NULL-initialized (ISO C guarantees that partial initializers * work like that). */ static DBusRMutex *global_locks[_DBUS_N_GLOBAL_LOCKS] = { NULL }; @@ -409,6 +421,8 @@ _dbus_global_unlock (DBusGlobalMutex mutex) _dbus_platform_rmutex_unlock (global_locks[mutex]); } +#endif /* !defined(DBUS_HAVE_STATIC_RECURSIVE_MUTEXES) */ + /** * Initialize threading in a platform-specific way. * -- 1.7.10.4