From 61ca6d06c97a2171dc9b7a655109e0cb14b63070 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Tue, 16 Apr 2013 15:39:54 +0100 Subject: [PATCH 6/6] Replace individual global-lock variables with an array of DBusRMutex * This means we can use a much simpler code structure in data-slot allocators: instead of giving them a DBusRMutex ** at first-allocation, we can just give them an index into the array, which can be done statically. It doesn't make us any more thread-safe-by-default - the mutexes will only actually be used if threads were already initialized - but it's substantially better than nothing. These locks really do have to be recursive: for instance, internal_bus_get() calls dbus_bus_register() under the bus lock, and dbus_bus_register() can call _dbus_connection_close_possibly_shared(), which takes the bus lock. --- Doxyfile.in | 1 - cmake/Doxyfile.cmake | 1 - dbus/dbus-bus.c | 13 ------ dbus/dbus-connection.c | 7 ++-- dbus/dbus-dataslot.c | 62 +++++++++------------------- dbus/dbus-dataslot.h | 8 ++-- dbus/dbus-internals.c | 19 +-------- dbus/dbus-internals.h | 59 +++++++++++++++------------ dbus/dbus-list.c | 2 +- dbus/dbus-memory.c | 18 ++++++--- dbus/dbus-message.c | 7 ++-- dbus/dbus-pending-call.c | 5 +-- dbus/dbus-server.c | 6 +-- dbus/dbus-sysdeps.c | 2 - dbus/dbus-threads.c | 100 +++++++++++++++++++++------------------------- 15 files changed, 126 insertions(+), 184 deletions(-) diff --git a/Doxyfile.in b/Doxyfile.in index afac639..f0a37ed 100644 --- a/Doxyfile.in +++ b/Doxyfile.in @@ -147,7 +147,6 @@ PREDEFINED = "DBUS_BEGIN_DECLS=" \ "DBUS_END_DECLS=" \ "DOXYGEN_SHOULD_SKIP_THIS" \ "DBUS_GNUC_DEPRECATED=" \ - "_DBUS_DEFINE_GLOBAL_LOCK(name)=" \ "_DBUS_GNUC_PRINTF(from,to)=" SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- diff --git a/cmake/Doxyfile.cmake b/cmake/Doxyfile.cmake index e00984e..3c63d95 100644 --- a/cmake/Doxyfile.cmake +++ b/cmake/Doxyfile.cmake @@ -147,7 +147,6 @@ PREDEFINED = "DBUS_BEGIN_DECLS=" \ "DBUS_END_DECLS=" \ "DOXYGEN_SHOULD_SKIP_THIS" \ "DBUS_GNUC_DEPRECATED=" \ - "_DBUS_DEFINE_GLOBAL_LOCK(name)=" \ "_DBUS_GNUC_PRINTF(from,to)=" \ "DBUS_EXPORT=" SKIP_FUNCTION_MACROS = YES diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index 6f81c74..4a6ffb1 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -95,19 +95,6 @@ static DBusBusType activation_bus_type = DBUS_BUS_STARTER; static dbus_bool_t initialized = FALSE; -/** - * Lock for globals in this file - */ -_DBUS_DEFINE_GLOBAL_LOCK (bus); - -/** - * Global lock covering all BusData on any connection. The bet is - * that some lock contention is better than more memory - * for a per-connection lock, but it's tough to imagine it mattering - * either way. - */ -_DBUS_DEFINE_GLOBAL_LOCK (bus_datas); - static void addresses_shutdown_func (void *data) { diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 66315b3..03ee066 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -1531,7 +1531,7 @@ _dbus_connection_handle_watch (DBusWatch *watch, return retval; } -_DBUS_DEFINE_GLOBAL_LOCK (shared_connections); +/* Protected by _DBUS_LOCK (shared_connections) */ static DBusHashTable *shared_connections = NULL; static DBusList *shared_connections_no_guid = NULL; @@ -5852,8 +5852,8 @@ dbus_connection_list_registered (DBusConnection *connection, return retval; } -static DBusDataSlotAllocator slot_allocator; -_DBUS_DEFINE_GLOBAL_LOCK (connection_slots); +static DBusDataSlotAllocator slot_allocator = + _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (connection_slots)); /** * Allocates an integer ID to be used for storing application-specific @@ -5873,7 +5873,6 @@ dbus_bool_t dbus_connection_allocate_data_slot (dbus_int32_t *slot_p) { return _dbus_data_slot_allocator_alloc (&slot_allocator, - &_DBUS_LOCK_NAME (connection_slots), slot_p); } diff --git a/dbus/dbus-dataslot.c b/dbus/dbus-dataslot.c index 0369612..b3c8090 100644 --- a/dbus/dbus-dataslot.c +++ b/dbus/dbus-dataslot.c @@ -43,13 +43,14 @@ * @param allocator the allocator to initialize */ dbus_bool_t -_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator) +_dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator, + DBusGlobalLock lock) { allocator->allocated_slots = NULL; allocator->n_allocated_slots = 0; allocator->n_used_slots = 0; - allocator->lock_loc = NULL; - + allocator->lock = lock; + return TRUE; } @@ -61,29 +62,16 @@ _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator) * is allocated and stored at *slot_id_p. * * @param allocator the allocator - * @param mutex_loc the location lock for this allocator * @param slot_id_p address to fill with the slot ID * @returns #TRUE on success */ dbus_bool_t _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, - DBusRMutex **mutex_loc, dbus_int32_t *slot_id_p) { dbus_int32_t slot; - _dbus_rmutex_lock (*mutex_loc); - - if (allocator->n_allocated_slots == 0) - { - _dbus_assert (allocator->lock_loc == NULL); - allocator->lock_loc = mutex_loc; - } - else if (allocator->lock_loc != mutex_loc) - { - _dbus_warn_check_failed ("D-Bus threads were initialized after first using the D-Bus library. If your application does not directly initialize threads or use D-Bus, keep in mind that some library or plugin may have used D-Bus or initialized threads behind your back. You can often fix this problem by calling dbus_init_threads() or dbus_g_threads_init() early in your main() method, before D-Bus is used.\n"); - _dbus_assert_not_reached ("exiting"); - } + _dbus_lock (allocator->lock); if (*slot_id_p >= 0) { @@ -146,7 +134,7 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots); out: - _dbus_rmutex_unlock (*(allocator->lock_loc)); + _dbus_unlock (allocator->lock); return slot >= 0; } @@ -165,7 +153,7 @@ void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, dbus_int32_t *slot_id_p) { - _dbus_rmutex_lock (*(allocator->lock_loc)); + _dbus_lock (allocator->lock); _dbus_assert (*slot_id_p < allocator->n_allocated_slots); _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p); @@ -175,7 +163,7 @@ _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, if (allocator->allocated_slots[*slot_id_p].refcount > 0) { - _dbus_rmutex_unlock (*(allocator->lock_loc)); + _dbus_unlock (allocator->lock); return; } @@ -190,19 +178,12 @@ _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, if (allocator->n_used_slots == 0) { - DBusRMutex **mutex_loc = allocator->lock_loc; - dbus_free (allocator->allocated_slots); allocator->allocated_slots = NULL; allocator->n_allocated_slots = 0; - allocator->lock_loc = NULL; - - _dbus_rmutex_unlock (*mutex_loc); - } - else - { - _dbus_rmutex_unlock (*(allocator->lock_loc)); } + + _dbus_unlock (allocator->lock); } /** @@ -247,10 +228,10 @@ _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator, * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts * are disabled, since then the asserts are empty. */ - _dbus_rmutex_lock (*(allocator->lock_loc)); + _dbus_lock (allocator->lock); _dbus_assert (slot < allocator->n_allocated_slots); _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); - _dbus_rmutex_unlock (*(allocator->lock_loc)); + _dbus_unlock (allocator->lock); #endif if (slot >= list->n_slots) @@ -304,11 +285,11 @@ _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator, * be e.g. realloc()ing allocated_slots. We avoid doing this if asserts * are disabled, since then the asserts are empty. */ - _dbus_rmutex_lock (*(allocator->lock_loc)); + _dbus_lock (allocator->lock); _dbus_assert (slot >= 0); _dbus_assert (slot < allocator->n_allocated_slots); _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); - _dbus_rmutex_unlock (*(allocator->lock_loc)); + _dbus_unlock (allocator->lock); #endif if (slot >= list->n_slots) @@ -384,17 +365,12 @@ _dbus_data_slot_test (void) int i; DBusFreeFunction old_free_func; void *old_data; - DBusRMutex *mutex; - - if (!_dbus_data_slot_allocator_init (&allocator)) + + if (!_dbus_data_slot_allocator_init (&allocator, _DBUS_LOCK_server_slots)) _dbus_assert_not_reached ("no memory for allocator"); _dbus_data_slot_list_init (&list); - _dbus_rmutex_new_at_location (&mutex); - if (mutex == NULL) - _dbus_assert_not_reached ("failed to alloc mutex"); - #define N_SLOTS 100 i = 0; @@ -405,8 +381,8 @@ _dbus_data_slot_test (void) * here. */ dbus_int32_t tmp = -1; - - _dbus_data_slot_allocator_alloc (&allocator, &mutex, &tmp); + + _dbus_data_slot_allocator_alloc (&allocator, &tmp); if (tmp != i) _dbus_assert_not_reached ("did not allocate slots in numeric order\n"); @@ -471,8 +447,6 @@ _dbus_data_slot_test (void) ++i; } - _dbus_rmutex_free_at_location (&mutex); - return TRUE; } diff --git a/dbus/dbus-dataslot.h b/dbus/dbus-dataslot.h index 3d9d5ed..1e04fcb 100644 --- a/dbus/dbus-dataslot.h +++ b/dbus/dbus-dataslot.h @@ -57,9 +57,11 @@ struct DBusDataSlotAllocator DBusAllocatedSlot *allocated_slots; /**< Allocated slots */ int n_allocated_slots; /**< number of slots malloc'd */ int n_used_slots; /**< number of slots used */ - DBusRMutex **lock_loc; /**< location of thread lock */ + DBusGlobalLock lock; /**< index of thread lock */ }; +#define _DBUS_DATA_SLOT_ALLOCATOR_INIT(x) { NULL, 0, 0, x } + /** * Data structure that stores the actual user data set at a given * slot. @@ -70,9 +72,9 @@ struct DBusDataSlotList int n_slots; /**< Slots we have storage for in data_slots */ }; -dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator); +dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator, + DBusGlobalLock lock); dbus_bool_t _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, - DBusRMutex **mutex_loc, int *slot_id_p); void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, int *slot_id_p); diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c index 0e5d807..1a36734 100644 --- a/dbus/dbus-internals.c +++ b/dbus/dbus-internals.c @@ -163,23 +163,6 @@ */ /** - * @def _DBUS_DEFINE_GLOBAL_LOCK - * - * Defines a global lock variable with the given name. - * The lock must be added to the list to initialize - * in dbus_threads_init(). - */ - -/** - * @def _DBUS_DECLARE_GLOBAL_LOCK - * - * Expands to declaration of a global lock defined - * with _DBUS_DEFINE_GLOBAL_LOCK. - * The lock must be added to the list to initialize - * in dbus_threads_init(). - */ - -/** * @def _DBUS_LOCK * * Locks a global lock @@ -847,7 +830,7 @@ _dbus_read_uuid_file (const DBusString *filename, } } -_DBUS_DEFINE_GLOBAL_LOCK (machine_uuid); +/* Protected by _DBUS_LOCK (machine_uuid) */ static int machine_uuid_initialized_generation = 0; static DBusGUID machine_uuid; diff --git a/dbus/dbus-internals.h b/dbus/dbus-internals.h index 382630d..d0a1089 100644 --- a/dbus/dbus-internals.h +++ b/dbus/dbus-internals.h @@ -293,35 +293,42 @@ dbus_bool_t _dbus_test_oom_handling (const char *description, #endif /* !DBUS_BUILD_TESTS */ typedef void (* DBusShutdownFunction) (void *data); -dbus_bool_t _dbus_register_shutdown_func (DBusShutdownFunction function, - void *data); +dbus_bool_t _dbus_register_shutdown_func (DBusShutdownFunction function, + void *data); +dbus_bool_t _dbus_register_shutdown_func_unlocked (DBusShutdownFunction function, + void *data); extern int _dbus_current_generation; -/* Thread initializers */ -#define _DBUS_LOCK_NAME(name) _dbus_lock_##name -#define _DBUS_DECLARE_GLOBAL_LOCK(name) extern DBusRMutex *_dbus_lock_##name -#define _DBUS_DEFINE_GLOBAL_LOCK(name) DBusRMutex *_dbus_lock_##name -#define _DBUS_LOCK(name) _dbus_rmutex_lock (_dbus_lock_##name) -#define _DBUS_UNLOCK(name) _dbus_rmutex_unlock (_dbus_lock_##name) - -/* index 0-4 */ -_DBUS_DECLARE_GLOBAL_LOCK (list); -_DBUS_DECLARE_GLOBAL_LOCK (connection_slots); -_DBUS_DECLARE_GLOBAL_LOCK (pending_call_slots); -_DBUS_DECLARE_GLOBAL_LOCK (server_slots); -_DBUS_DECLARE_GLOBAL_LOCK (message_slots); -/* index 5-9 */ -_DBUS_DECLARE_GLOBAL_LOCK (bus); -_DBUS_DECLARE_GLOBAL_LOCK (bus_datas); -_DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs); -_DBUS_DECLARE_GLOBAL_LOCK (system_users); -_DBUS_DECLARE_GLOBAL_LOCK (message_cache); -/* index 10-11 */ -_DBUS_DECLARE_GLOBAL_LOCK (shared_connections); -_DBUS_DECLARE_GLOBAL_LOCK (machine_uuid); - -#define _DBUS_N_GLOBAL_LOCKS (12) +/* The weird case convention is to avoid having to change all the callers, + * which would be quite a mega-patch. */ +typedef enum +{ + /* index 0-4 */ + _DBUS_LOCK_list, + _DBUS_LOCK_connection_slots, + _DBUS_LOCK_pending_call_slots, + _DBUS_LOCK_server_slots, + _DBUS_LOCK_message_slots, + /* index 5-9 */ + _DBUS_LOCK_bus, + _DBUS_LOCK_bus_datas, + _DBUS_LOCK_shutdown_funcs, + _DBUS_LOCK_system_users, + _DBUS_LOCK_message_cache, + /* index 10-11 */ + _DBUS_LOCK_shared_connections, + _DBUS_LOCK_machine_uuid, + + _DBUS_N_GLOBAL_LOCKS +} DBusGlobalLock; + +void _dbus_lock (DBusGlobalLock lock); +void _dbus_unlock (DBusGlobalLock lock); + +#define _DBUS_LOCK_NAME(name) _DBUS_LOCK_##name +#define _DBUS_LOCK(name) _dbus_lock (_DBUS_LOCK_##name) +#define _DBUS_UNLOCK(name) _dbus_unlock (_DBUS_LOCK_##name) dbus_bool_t _dbus_threads_init_debug (void); diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c index 7e11cc8..e5a4940 100644 --- a/dbus/dbus-list.c +++ b/dbus/dbus-list.c @@ -35,8 +35,8 @@ * Types and functions related to DBusList. */ +/* Protected by _DBUS_LOCK (list) */ static DBusMemPool *list_pool; -_DBUS_DEFINE_GLOBAL_LOCK (list); /** * @defgroup DBusListInternals Linked list implementation details diff --git a/dbus/dbus-memory.c b/dbus/dbus-memory.c index 317e37e..a13b951 100644 --- a/dbus/dbus-memory.c +++ b/dbus/dbus-memory.c @@ -795,7 +795,7 @@ struct ShutdownClosure void *data; /**< Data for function */ }; -_DBUS_DEFINE_GLOBAL_LOCK (shutdown_funcs); +/* Protected by _DBUS_LOCK (shutdown_funcs) */ static ShutdownClosure *registered_globals = NULL; /** @@ -810,6 +810,18 @@ dbus_bool_t _dbus_register_shutdown_func (DBusShutdownFunction func, void *data) { + dbus_bool_t ok; + + _DBUS_LOCK (shutdown_funcs); + ok = _dbus_register_shutdown_func_unlocked (func, data); + _DBUS_UNLOCK (shutdown_funcs); + return ok; +} + +dbus_bool_t +_dbus_register_shutdown_func_unlocked (DBusShutdownFunction func, + void *data) +{ ShutdownClosure *c; c = dbus_new (ShutdownClosure, 1); @@ -820,13 +832,9 @@ _dbus_register_shutdown_func (DBusShutdownFunction func, c->func = func; c->data = data; - _DBUS_LOCK (shutdown_funcs); - c->next = registered_globals; registered_globals = c; - _DBUS_UNLOCK (shutdown_funcs); - return TRUE; } diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 619bc69..bc2380f 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -506,7 +506,7 @@ _dbus_message_set_signature (DBusMessage *message, /** Avoid caching too many messages */ #define MAX_MESSAGE_CACHE_SIZE 5 -_DBUS_DEFINE_GLOBAL_LOCK (message_cache); +/* Protected by _DBUS_LOCK (message_cache) */ static DBusMessage *message_cache[MAX_MESSAGE_CACHE_SIZE]; static int message_cache_count = 0; static dbus_bool_t message_cache_shutdown_registered = FALSE; @@ -4423,8 +4423,8 @@ _dbus_message_loader_get_max_message_unix_fds (DBusMessageLoader *loader) return loader->max_message_unix_fds; } -static DBusDataSlotAllocator slot_allocator; -_DBUS_DEFINE_GLOBAL_LOCK (message_slots); +static DBusDataSlotAllocator slot_allocator = + _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (message_slots)); /** * Allocates an integer ID to be used for storing application-specific @@ -4444,7 +4444,6 @@ dbus_bool_t dbus_message_allocate_data_slot (dbus_int32_t *slot_p) { return _dbus_data_slot_allocator_alloc (&slot_allocator, - &_DBUS_LOCK_NAME (message_slots), slot_p); } diff --git a/dbus/dbus-pending-call.c b/dbus/dbus-pending-call.c index 62c6c74..1604408 100644 --- a/dbus/dbus-pending-call.c +++ b/dbus/dbus-pending-call.c @@ -489,8 +489,8 @@ _dbus_pending_call_get_completed_unlocked (DBusPendingCall *pending) return pending->completed; } -static DBusDataSlotAllocator slot_allocator; -_DBUS_DEFINE_GLOBAL_LOCK (pending_call_slots); +static DBusDataSlotAllocator slot_allocator = + _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (pending_call_slots)); /** * Stores a pointer on a #DBusPendingCall, along @@ -768,7 +768,6 @@ dbus_pending_call_allocate_data_slot (dbus_int32_t *slot_p) _dbus_return_val_if_fail (slot_p != NULL, FALSE); return _dbus_data_slot_allocator_alloc (&slot_allocator, - &_DBUS_LOCK_NAME (pending_call_slots), slot_p); } diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index b62c2b4..e021266 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -1071,9 +1071,8 @@ dbus_server_set_auth_mechanisms (DBusServer *server, return TRUE; } - -static DBusDataSlotAllocator slot_allocator; -_DBUS_DEFINE_GLOBAL_LOCK (server_slots); +static DBusDataSlotAllocator slot_allocator = + _DBUS_DATA_SLOT_ALLOCATOR_INIT (_DBUS_LOCK_NAME (server_slots)); /** * Allocates an integer ID to be used for storing application-specific @@ -1093,7 +1092,6 @@ dbus_bool_t dbus_server_allocate_data_slot (dbus_int32_t *slot_p) { return _dbus_data_slot_allocator_alloc (&slot_allocator, - (DBusRMutex **)&_DBUS_LOCK_NAME (server_slots), slot_p); } diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 4e14ac3..0fbf9e7 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -46,8 +46,6 @@ #include #endif -_DBUS_DEFINE_GLOBAL_LOCK (system_users); - #ifdef DBUS_WIN #include #elif (defined __APPLE__) diff --git a/dbus/dbus-threads.c b/dbus/dbus-threads.c index 43676bc..297a7e4 100644 --- a/dbus/dbus-threads.c +++ b/dbus/dbus-threads.c @@ -343,23 +343,19 @@ _dbus_condvar_wake_one (DBusCondVar *cond) _dbus_platform_condvar_wake_one (cond); } +static DBusRMutex *global_locks[_DBUS_N_GLOBAL_LOCKS] = { NULL }; + static void -shutdown_global_locks (void *data) +shutdown_global_locks (void *nil) { - DBusRMutex ***locks = data; int i; - i = 0; - while (i < _DBUS_N_GLOBAL_LOCKS) + for (i = 0; i < _DBUS_N_GLOBAL_LOCKS; i++) { - if (*(locks[i]) != NULL) - _dbus_platform_rmutex_free (*(locks[i])); - - *(locks[i]) = NULL; - ++i; + _dbus_assert (global_locks[i] != NULL); + _dbus_platform_rmutex_free (global_locks[i]); + global_locks[i] = NULL; } - - dbus_free (locks); } static void @@ -483,67 +479,60 @@ init_uninitialized_locks (void) } static dbus_bool_t -init_locks (void) +init_global_locks (void) { int i; - DBusRMutex ***dynamic_global_locks; - DBusRMutex **global_locks[] = { -#define LOCK_ADDR(name) (& _dbus_lock_##name) - LOCK_ADDR (list), - LOCK_ADDR (connection_slots), - LOCK_ADDR (pending_call_slots), - LOCK_ADDR (server_slots), - LOCK_ADDR (message_slots), - LOCK_ADDR (bus), - LOCK_ADDR (bus_datas), - LOCK_ADDR (shutdown_funcs), - LOCK_ADDR (system_users), - LOCK_ADDR (message_cache), - LOCK_ADDR (shared_connections), - LOCK_ADDR (machine_uuid) -#undef LOCK_ADDR - }; - - _DBUS_STATIC_ASSERT (_DBUS_N_ELEMENTS (global_locks) == _DBUS_N_GLOBAL_LOCKS); - - i = 0; - - dynamic_global_locks = dbus_new (DBusRMutex**, _DBUS_N_GLOBAL_LOCKS); - if (dynamic_global_locks == NULL) - goto failed; - - while (i < _DBUS_N_ELEMENTS (global_locks)) + dbus_bool_t ok; + + for (i = 0; i < _DBUS_N_GLOBAL_LOCKS; i++) { - *global_locks[i] = _dbus_platform_rmutex_new (); + _dbus_assert (global_locks[i] == NULL); + + global_locks[i] = _dbus_platform_rmutex_new (); - if (*global_locks[i] == NULL) + if (global_locks[i] == NULL) goto failed; + } - dynamic_global_locks[i] = global_locks[i]; + _dbus_lock (_DBUS_LOCK_NAME (shutdown_funcs)); + ok = _dbus_register_shutdown_func_unlocked (shutdown_global_locks, NULL); + _dbus_unlock (_DBUS_LOCK_NAME (shutdown_funcs)); - ++i; - } - - if (!_dbus_register_shutdown_func (shutdown_global_locks, - dynamic_global_locks)) + if (!ok) goto failed; - if (!init_uninitialized_locks ()) - goto failed; - return TRUE; failed: - dbus_free (dynamic_global_locks); - for (i = i - 1; i >= 0; i--) { - _dbus_platform_rmutex_free (*global_locks[i]); - *global_locks[i] = NULL; + _dbus_platform_rmutex_free (global_locks[i]); + global_locks[i] = NULL; } + return FALSE; } +void +_dbus_lock (DBusGlobalLock lock) +{ + _dbus_assert (lock >= 0); + _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS); + + if (thread_init_generation == _dbus_current_generation) + _dbus_platform_rmutex_lock (global_locks[lock]); +} + +void +_dbus_unlock (DBusGlobalLock lock) +{ + _dbus_assert (lock >= 0); + _dbus_assert (lock < _DBUS_N_GLOBAL_LOCKS); + + if (thread_init_generation == _dbus_current_generation) + _dbus_platform_rmutex_unlock (global_locks[lock]); +} + /** @} */ /* end of internals */ /** @@ -587,7 +576,8 @@ dbus_threads_init (const DBusThreadFunctions *functions) } if (!_dbus_threads_init_platform_specific() || - !init_locks ()) + !init_global_locks () || + !init_uninitialized_locks ()) { _dbus_threads_unlock_platform_specific (); return FALSE; -- 1.7.10.4