summaryrefslogtreecommitdiffstats
path: root/dbus
diff options
context:
space:
mode:
Diffstat (limited to 'dbus')
-rw-r--r--dbus/dbus-bus.c61
-rw-r--r--dbus/dbus-connection.c41
-rw-r--r--dbus/dbus-connection.h8
-rw-r--r--dbus/dbus-dataslot.c100
-rw-r--r--dbus/dbus-dataslot.h16
-rw-r--r--dbus/dbus-server.c29
-rw-r--r--dbus/dbus-server.h4
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,