diff options
Diffstat (limited to 'dbus')
-rw-r--r-- | dbus/dbus-bus.c | 61 | ||||
-rw-r--r-- | dbus/dbus-connection.c | 41 | ||||
-rw-r--r-- | dbus/dbus-connection.h | 8 | ||||
-rw-r--r-- | dbus/dbus-dataslot.c | 100 | ||||
-rw-r--r-- | dbus/dbus-dataslot.h | 16 | ||||
-rw-r--r-- | dbus/dbus-server.c | 29 | ||||
-rw-r--r-- | dbus/dbus-server.h | 4 |
7 files changed, 137 insertions, 122 deletions
diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index dee9b9f7..6ab1eccc 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -56,12 +56,9 @@ typedef struct unsigned int is_well_known : 1; /**< Is one of the well-known connections in our global array */ } BusData; -/** The slot we have reserved to store BusData +/** The slot we have reserved to store BusData. */ -static int bus_data_slot = -1; -/** Number of connections using the slot - */ -static int bus_data_slot_refcount = 0; +static dbus_int32_t bus_data_slot = -1; /** Number of bus types */ #define N_BUS_TYPES 3 @@ -194,50 +191,6 @@ init_connections_unlocked (void) return initialized; } -static dbus_bool_t -data_slot_ref (void) -{ - _DBUS_LOCK (bus); - - if (bus_data_slot < 0) - { - bus_data_slot = dbus_connection_allocate_data_slot (); - - if (bus_data_slot < 0) - { - _DBUS_UNLOCK (bus); - return FALSE; - } - - _dbus_assert (bus_data_slot_refcount == 0); - } - - bus_data_slot_refcount += 1; - - _DBUS_UNLOCK (bus); - - return TRUE; -} - -static void -data_slot_unref (void) -{ - _DBUS_LOCK (bus); - - _dbus_assert (bus_data_slot_refcount > 0); - _dbus_assert (bus_data_slot >= 0); - - bus_data_slot_refcount -= 1; - - if (bus_data_slot_refcount == 0) - { - dbus_connection_free_data_slot (bus_data_slot); - bus_data_slot = -1; - } - - _DBUS_UNLOCK (bus); -} - static void bus_data_free (void *data) { @@ -262,7 +215,7 @@ bus_data_free (void *data) dbus_free (bd->base_service); dbus_free (bd); - data_slot_unref (); + dbus_connection_free_data_slot (&bus_data_slot); } static BusData* @@ -270,7 +223,7 @@ ensure_bus_data (DBusConnection *connection) { BusData *bd; - if (!data_slot_ref ()) + if (!dbus_connection_allocate_data_slot (&bus_data_slot)) return NULL; bd = dbus_connection_get_data (connection, bus_data_slot); @@ -279,7 +232,7 @@ ensure_bus_data (DBusConnection *connection) bd = dbus_new0 (BusData, 1); if (bd == NULL) { - data_slot_unref (); + dbus_connection_free_data_slot (&bus_data_slot); return NULL; } @@ -289,7 +242,7 @@ ensure_bus_data (DBusConnection *connection) bus_data_free)) { dbus_free (bd); - data_slot_unref (); + dbus_connection_free_data_slot (&bus_data_slot); return NULL; } @@ -297,7 +250,7 @@ ensure_bus_data (DBusConnection *connection) } else { - data_slot_unref (); + dbus_connection_free_data_slot (&bus_data_slot); } return bd; diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index d877a0b4..01b2a7bf 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2933,34 +2933,41 @@ _DBUS_DEFINE_GLOBAL_LOCK (connection_slots); * Allocates an integer ID to be used for storing application-specific * data on any DBusConnection. The allocated ID may then be used * with dbus_connection_set_data() and dbus_connection_get_data(). - * If allocation fails, -1 is returned. Again, the allocated - * slot is global, i.e. all DBusConnection objects will + * The passed-in slot must be initialized to -1, and is filled in + * with the slot ID. If the passed-in slot is not -1, it's assumed + * to be already allocated, and its refcount is incremented. + * + * The allocated slot is global, i.e. all DBusConnection objects will * have a slot with the given integer ID reserved. * - * @returns -1 on failure, otherwise the data slot ID + * @param slot_p address of a global variable storing the slot + * @returns #FALSE on failure (no memory) */ -int -dbus_connection_allocate_data_slot (void) +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)); + _DBUS_LOCK_NAME (connection_slots), + slot_p); } /** * Deallocates a global ID for connection data slots. - * dbus_connection_get_data() and dbus_connection_set_data() - * may no longer be used with this slot. - * Existing data stored on existing DBusConnection objects - * will be freed when the connection is finalized, - * but may not be retrieved (and may only be replaced - * if someone else reallocates the slot). + * dbus_connection_get_data() and dbus_connection_set_data() may no + * longer be used with this slot. Existing data stored on existing + * DBusConnection objects will be freed when the connection is + * finalized, but may not be retrieved (and may only be replaced if + * someone else reallocates the slot). When the refcount on the + * passed-in slot reaches 0, it is set to -1. * - * @param slot the slot to deallocate + * @param slot_p address storing the slot to deallocate */ void -dbus_connection_free_data_slot (int slot) +dbus_connection_free_data_slot (dbus_int32_t *slot_p) { - _dbus_data_slot_allocator_free (&slot_allocator, slot); + _dbus_return_if_fail (*slot_p >= 0); + + _dbus_data_slot_allocator_free (&slot_allocator, slot_p); } /** @@ -2978,7 +2985,7 @@ dbus_connection_free_data_slot (int slot) */ dbus_bool_t dbus_connection_set_data (DBusConnection *connection, - int slot, + dbus_int32_t slot, void *data, DBusFreeFunction free_data_func) { @@ -3018,7 +3025,7 @@ dbus_connection_set_data (DBusConnection *connection, */ void* dbus_connection_get_data (DBusConnection *connection, - int slot) + dbus_int32_t slot) { void *res; diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index c2206cd3..9f4dd7ae 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -172,14 +172,14 @@ void dbus_connection_unregister_handler (DBusConnection *connection, int n_messages); -int dbus_connection_allocate_data_slot (void); -void dbus_connection_free_data_slot (int slot); +dbus_bool_t dbus_connection_allocate_data_slot (dbus_int32_t *slot_p); +void dbus_connection_free_data_slot (dbus_int32_t *slot_p); dbus_bool_t dbus_connection_set_data (DBusConnection *connection, - int slot, + dbus_int32_t slot, void *data, DBusFreeFunction free_data_func); void* dbus_connection_get_data (DBusConnection *connection, - int slot); + dbus_int32_t slot); void dbus_connection_set_change_sigpipe (dbus_bool_t will_modify_sigpipe); diff --git a/dbus/dbus-dataslot.c b/dbus/dbus-dataslot.c index def864e4..defe9345 100644 --- a/dbus/dbus-dataslot.c +++ b/dbus/dbus-dataslot.c @@ -53,24 +53,25 @@ _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator) /** * Allocates an integer ID to be used for storing data - * in a #DBusDataSlotList. - * - * @todo all over the code we have foo_slot and foo_slot_refcount, - * would be better to add an interface for that to - * DBusDataSlotAllocator so it isn't cut-and-pasted everywhere. + * in a #DBusDataSlotList. If the value at *slot_id_p is + * not -1, this function just increments the refcount for + * the existing slot ID. If the value is -1, a new slot ID + * is allocated and stored at *slot_id_p. * * @param allocator the allocator * @param mutex the lock for this allocator - * @returns the integer ID, or -1 on failure + * @param slot_id_p address to fill with the slot ID + * @returns #TRUE on success */ -int +dbus_bool_t _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, - DBusMutex *mutex) + DBusMutex *mutex, + dbus_int32_t *slot_id_p) { - int slot; + dbus_int32_t slot; if (!dbus_mutex_lock (mutex)) - return -1; + return FALSE; if (allocator->n_allocated_slots == 0) { @@ -79,15 +80,30 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, } else _dbus_assert (allocator->lock == mutex); + + if (*slot_id_p >= 0) + { + slot = *slot_id_p; + + _dbus_assert (slot < allocator->n_allocated_slots); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); + + allocator->allocated_slots[slot].refcount += 1; + + goto out; + } + + _dbus_assert (*slot_id_p < 0); if (allocator->n_used_slots < allocator->n_allocated_slots) { slot = 0; while (slot < allocator->n_allocated_slots) { - if (allocator->allocated_slots[slot] < 0) + if (allocator->allocated_slots[slot].slot_id < 0) { - allocator->allocated_slots[slot] = slot; + allocator->allocated_slots[slot].slot_id = slot; + allocator->allocated_slots[slot].refcount = 1; allocator->n_used_slots += 1; break; } @@ -98,11 +114,11 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, } else { - int *tmp; + DBusAllocatedSlot *tmp; slot = -1; tmp = dbus_realloc (allocator->allocated_slots, - sizeof (int) * (allocator->n_allocated_slots + 1)); + sizeof (DBusAllocatedSlot) * (allocator->n_allocated_slots + 1)); if (tmp == NULL) goto out; @@ -110,18 +126,24 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, slot = allocator->n_allocated_slots; allocator->n_allocated_slots += 1; allocator->n_used_slots += 1; - allocator->allocated_slots[slot] = slot; + allocator->allocated_slots[slot].slot_id = slot; + allocator->allocated_slots[slot].refcount = 1; } _dbus_assert (slot >= 0); _dbus_assert (slot < allocator->n_allocated_slots); - + _dbus_assert (*slot_id_p < 0); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); + _dbus_assert (allocator->allocated_slots[slot].refcount == 1); + + *slot_id_p = slot; + _dbus_verbose ("Allocated slot %d on allocator %p total %d slots allocated %d used\n", slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots); out: dbus_mutex_unlock (allocator->lock); - return slot; + return slot >= 0; } /** @@ -130,24 +152,37 @@ _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, * existing #DBusDataList objects with this ID will be freed when the * data list is finalized, but may not be retrieved (and may only be * replaced if someone else reallocates the slot). + * The slot value is reset to -1 if this is the last unref. * * @param allocator the allocator - * @param slot the slot to deallocate + * @param slot_id_p address where we store the slot */ void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, - int slot) + dbus_int32_t *slot_id_p) { dbus_mutex_lock (allocator->lock); - _dbus_assert (slot < allocator->n_allocated_slots); - _dbus_assert (allocator->allocated_slots[slot] == slot); + _dbus_assert (*slot_id_p < allocator->n_allocated_slots); + _dbus_assert (allocator->allocated_slots[*slot_id_p].slot_id == *slot_id_p); + _dbus_assert (allocator->allocated_slots[*slot_id_p].refcount > 0); + + allocator->allocated_slots[*slot_id_p].refcount -= 1; + + if (allocator->allocated_slots[*slot_id_p].refcount > 0) + { + dbus_mutex_unlock (allocator->lock); + return; + } + + /* refcount is 0, free the slot */ + _dbus_verbose ("Freeing slot %d on allocator %p total %d allocated %d used\n", + *slot_id_p, allocator, allocator->n_allocated_slots, allocator->n_used_slots); + + allocator->allocated_slots[*slot_id_p].slot_id = -1; + *slot_id_p = -1; - allocator->allocated_slots[slot] = -1; allocator->n_used_slots -= 1; - - _dbus_verbose ("Freed slot %d on allocator %p total %d allocated %d used\n", - slot, allocator, allocator->n_allocated_slots, allocator->n_used_slots); if (allocator->n_used_slots == 0) { @@ -211,7 +246,7 @@ _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator, if (!dbus_mutex_lock (allocator->lock)) return FALSE; _dbus_assert (slot < allocator->n_allocated_slots); - _dbus_assert (allocator->allocated_slots[slot] == slot); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); dbus_mutex_unlock (allocator->lock); #endif @@ -270,7 +305,7 @@ _dbus_data_slot_list_get (DBusDataSlotAllocator *allocator, return FALSE; _dbus_assert (slot >= 0); _dbus_assert (slot < allocator->n_allocated_slots); - _dbus_assert (allocator->allocated_slots[slot] == slot); + _dbus_assert (allocator->allocated_slots[slot].slot_id == slot); dbus_mutex_unlock (allocator->lock); #endif @@ -355,7 +390,11 @@ _dbus_data_slot_test (void) * allocation, but it simplifies things to rely on it * here. */ - if (_dbus_data_slot_allocator_alloc (&allocator, mutex) != i) + dbus_int32_t tmp = -1; + + _dbus_data_slot_allocator_alloc (&allocator, mutex, &tmp); + + if (tmp != i) _dbus_assert_not_reached ("did not allocate slots in numeric order\n"); ++i; @@ -411,7 +450,10 @@ _dbus_data_slot_test (void) i = 0; while (i < N_SLOTS) { - _dbus_data_slot_allocator_free (&allocator, i); + dbus_int32_t tmp = i; + + _dbus_data_slot_allocator_free (&allocator, &tmp); + _dbus_assert (tmp == -1); ++i; } diff --git a/dbus/dbus-dataslot.h b/dbus/dbus-dataslot.h index d4357325..6f591eb5 100644 --- a/dbus/dbus-dataslot.h +++ b/dbus/dbus-dataslot.h @@ -39,9 +39,16 @@ struct DBusDataSlot DBusFreeFunction free_data_func; /**< Free the application data */ }; +typedef struct DBusAllocatedSlot DBusAllocatedSlot; +struct DBusAllocatedSlot +{ + dbus_int32_t slot_id; /**< ID of this slot */ + int refcount; /**< Number of uses of the slot */ +}; + struct DBusDataSlotAllocator { - int *allocated_slots; /**< Allocated slots */ + DBusAllocatedSlot *allocated_slots; /**< Allocated slots */ int n_allocated_slots; /**< number of slots malloc'd */ int n_used_slots; /**< number of slots used */ DBusMutex *lock; /**< thread lock */ @@ -54,10 +61,11 @@ struct DBusDataSlotList }; dbus_bool_t _dbus_data_slot_allocator_init (DBusDataSlotAllocator *allocator); -int _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, - DBusMutex *mutex); +dbus_bool_t _dbus_data_slot_allocator_alloc (DBusDataSlotAllocator *allocator, + DBusMutex *mutex, + int *slot_id_p); void _dbus_data_slot_allocator_free (DBusDataSlotAllocator *allocator, - int slot_id); + int *slot_id_p); void _dbus_data_slot_list_init (DBusDataSlotList *list); dbus_bool_t _dbus_data_slot_list_set (DBusDataSlotAllocator *allocator, DBusDataSlotList *list, diff --git a/dbus/dbus-server.c b/dbus/dbus-server.c index 4007d7a5..1c9d53f0 100644 --- a/dbus/dbus-server.c +++ b/dbus/dbus-server.c @@ -666,17 +666,22 @@ _DBUS_DEFINE_GLOBAL_LOCK (server_slots); * Allocates an integer ID to be used for storing application-specific * data on any DBusServer. The allocated ID may then be used * with dbus_server_set_data() and dbus_server_get_data(). - * If allocation fails, -1 is returned. Again, the allocated - * slot is global, i.e. all DBusServer objects will - * have a slot with the given integer ID reserved. - * - * @returns -1 on failure, otherwise the data slot ID + * The slot must be initialized with -1. If a nonnegative + * slot is passed in, the refcount is incremented on that + * slot, rather than creating a new slot. + * + * The allocated slot is global, i.e. all DBusServer objects will have + * a slot with the given integer ID reserved. + * + * @param slot_p address of global variable storing the slot ID + * @returns #FALSE on no memory */ -int -dbus_server_allocate_data_slot (void) +dbus_bool_t +dbus_server_allocate_data_slot (dbus_int32_t *slot_p) { return _dbus_data_slot_allocator_alloc (&slot_allocator, - _DBUS_LOCK_NAME (server_slots)); + _DBUS_LOCK_NAME (server_slots), + slot_p); } /** @@ -688,14 +693,14 @@ dbus_server_allocate_data_slot (void) * but may not be retrieved (and may only be replaced * if someone else reallocates the slot). * - * @param slot the slot to deallocate + * @param slot_p address of the slot to deallocate */ void -dbus_server_free_data_slot (int slot) +dbus_server_free_data_slot (dbus_int32_t *slot_p) { - _dbus_return_if_fail (slot >= 0); + _dbus_return_if_fail (*slot_p >= 0); - _dbus_data_slot_allocator_free (&slot_allocator, slot); + _dbus_data_slot_allocator_free (&slot_allocator, slot_p); } /** diff --git a/dbus/dbus-server.h b/dbus/dbus-server.h index 5527f1ec..c2a0ca0f 100644 --- a/dbus/dbus-server.h +++ b/dbus/dbus-server.h @@ -65,8 +65,8 @@ dbus_bool_t dbus_server_set_timeout_functions (DBusServer * dbus_bool_t dbus_server_set_auth_mechanisms (DBusServer *server, const char **mechanisms); -int dbus_server_allocate_data_slot (void); -void dbus_server_free_data_slot (int slot); +dbus_bool_t dbus_server_allocate_data_slot (dbus_int32_t *slot_p); +void dbus_server_free_data_slot (dbus_int32_t *slot_p); dbus_bool_t dbus_server_set_data (DBusServer *server, int slot, void *data, |