mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-04-03 03:20:40 +02:00
2003-05-11 Havoc Pennington <hp@pobox.com>
* dbus/dbus-marshal.c (_dbus_marshal_validate_arg): fix to avoid calling _dbus_marshal_validate_arg() for every byte in a byte array, etc. * dbus/dbus-message-handler.c: use atomic reference counting to reduce number of locks slightly; the global lock in here sucks * dbus/dbus-connection.c (_dbus_connection_update_dispatch_status_and_unlock): variant of update_dispatch_status that can be called with lock held; then use in a couple places to reduce locking/unlocking (dbus_connection_send): hold the lock over the whole function instead of acquiring it twice. * dbus/dbus-timeout.c (_dbus_timeout_new): handle OOM * bus/connection.c (bus_connections_setup_connection): fix access to already-freed memory. * dbus/dbus-connection.c: keep a little cache of linked list nodes, to avoid using the global linked list alloc lock in the normal send-message case. Instead we just use the connection lock that we already have to take. * dbus/dbus-list.c (_dbus_list_find_last): new function * dbus/dbus-sysdeps.c (_dbus_atomic_inc, _dbus_atomic_dec): change to use a struct for the atomic type; fix docs, they return value before increment, not after increment. * dbus/dbus-string.c (_dbus_string_append_4_aligned) (_dbus_string_append_8_aligned): new functions to try to microoptimize this operation. (reallocate_for_length): break this out of set_length(), to improve profile info, and also so we can consider inlining the set_length() part. * dbus/dbus-message.c (dbus_message_new_empty_header): init data strings with some preallocation, cuts down on our calls to realloc a fair bit. Though if we can get the "move entire string to empty string" optimization below to kick in here, it would be better. * dbus/dbus-string.c (_dbus_string_move): just call _dbus_string_move_len (_dbus_string_move_len): add a special case for moving an entire string into an empty string; we can just swap the string data instead of doing any reallocs. (_dbus_string_init_preallocated): new function
This commit is contained in:
parent
ab10ae902d
commit
d4e80132af
15 changed files with 679 additions and 283 deletions
51
ChangeLog
51
ChangeLog
|
|
@ -1,3 +1,54 @@
|
|||
2003-05-11 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* dbus/dbus-marshal.c (_dbus_marshal_validate_arg): fix to avoid
|
||||
calling _dbus_marshal_validate_arg() for every byte in a byte
|
||||
array, etc.
|
||||
|
||||
* dbus/dbus-message-handler.c: use atomic reference counting to
|
||||
reduce number of locks slightly; the global lock in here sucks
|
||||
|
||||
* dbus/dbus-connection.c
|
||||
(_dbus_connection_update_dispatch_status_and_unlock): variant of
|
||||
update_dispatch_status that can be called with lock held; then use
|
||||
in a couple places to reduce locking/unlocking
|
||||
(dbus_connection_send): hold the lock over the whole function
|
||||
instead of acquiring it twice.
|
||||
|
||||
* dbus/dbus-timeout.c (_dbus_timeout_new): handle OOM
|
||||
|
||||
* bus/connection.c (bus_connections_setup_connection): fix access
|
||||
to already-freed memory.
|
||||
|
||||
* dbus/dbus-connection.c: keep a little cache of linked list
|
||||
nodes, to avoid using the global linked list alloc lock in the
|
||||
normal send-message case. Instead we just use the connection lock
|
||||
that we already have to take.
|
||||
|
||||
* dbus/dbus-list.c (_dbus_list_find_last): new function
|
||||
|
||||
* dbus/dbus-sysdeps.c (_dbus_atomic_inc, _dbus_atomic_dec):
|
||||
change to use a struct for the atomic type; fix docs,
|
||||
they return value before increment, not after increment.
|
||||
|
||||
* dbus/dbus-string.c (_dbus_string_append_4_aligned)
|
||||
(_dbus_string_append_8_aligned): new functions to try to
|
||||
microoptimize this operation.
|
||||
(reallocate_for_length): break this out of set_length(), to
|
||||
improve profile info, and also so we can consider inlining the
|
||||
set_length() part.
|
||||
|
||||
* dbus/dbus-message.c (dbus_message_new_empty_header): init data
|
||||
strings with some preallocation, cuts down on our calls to realloc
|
||||
a fair bit. Though if we can get the "move entire string to empty
|
||||
string" optimization below to kick in here, it would be better.
|
||||
|
||||
* dbus/dbus-string.c (_dbus_string_move): just call
|
||||
_dbus_string_move_len
|
||||
(_dbus_string_move_len): add a special case for moving
|
||||
an entire string into an empty string; we can just
|
||||
swap the string data instead of doing any reallocs.
|
||||
(_dbus_string_init_preallocated): new function
|
||||
|
||||
2003-05-11 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
Write a "test-profile" that does echo client-server with threads;
|
||||
|
|
|
|||
|
|
@ -533,7 +533,7 @@ bus_connections_setup_connection (BusConnections *connections,
|
|||
|
||||
d->connections = connections;
|
||||
d->connection = connection;
|
||||
|
||||
|
||||
_dbus_get_current_time (&d->connection_tv_sec,
|
||||
&d->connection_tv_usec);
|
||||
|
||||
|
|
@ -643,18 +643,21 @@ bus_connections_setup_connection (BusConnections *connections,
|
|||
|
||||
dbus_connection_set_dispatch_status_function (connection,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
if (!dbus_connection_set_data (connection,
|
||||
connection_data_slot,
|
||||
NULL, NULL))
|
||||
_dbus_assert_not_reached ("failed to set connection data to null");
|
||||
|
||||
if (d->link_in_connection_list != NULL)
|
||||
{
|
||||
_dbus_assert (d->link_in_connection_list->next == NULL);
|
||||
_dbus_assert (d->link_in_connection_list->prev == NULL);
|
||||
_dbus_list_free_link (d->link_in_connection_list);
|
||||
d->link_in_connection_list = NULL;
|
||||
}
|
||||
|
||||
if (!dbus_connection_set_data (connection,
|
||||
connection_data_slot,
|
||||
NULL, NULL))
|
||||
_dbus_assert_not_reached ("failed to set connection data to null");
|
||||
|
||||
/* "d" has now been freed */
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ static dbus_bool_t _dbus_modify_sigpipe = TRUE;
|
|||
*/
|
||||
struct DBusConnection
|
||||
{
|
||||
dbus_atomic_t refcount; /**< Reference count. */
|
||||
DBusAtomic refcount; /**< Reference count. */
|
||||
|
||||
DBusMutex *mutex; /**< Lock on the entire DBusConnection */
|
||||
|
||||
|
|
@ -176,6 +176,10 @@ struct DBusConnection
|
|||
DBusFreeFunction free_dispatch_status_data; /**< free dispatch_status_data */
|
||||
|
||||
DBusDispatchStatus last_dispatch_status; /**< The last dispatch status we reported to the application. */
|
||||
|
||||
DBusList *link_cache; /**< A cache of linked list links to prevent contention
|
||||
* for the global linked list mempool lock
|
||||
*/
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
|
@ -193,11 +197,12 @@ typedef struct
|
|||
|
||||
static void reply_handler_data_free (ReplyHandlerData *data);
|
||||
|
||||
static void _dbus_connection_remove_timeout_locked (DBusConnection *connection,
|
||||
DBusTimeout *timeout);
|
||||
static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
|
||||
static void _dbus_connection_update_dispatch_status_locked (DBusConnection *connection,
|
||||
DBusDispatchStatus new_status);
|
||||
static void _dbus_connection_remove_timeout_locked (DBusConnection *connection,
|
||||
DBusTimeout *timeout);
|
||||
static DBusDispatchStatus _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection);
|
||||
static void _dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
|
||||
DBusDispatchStatus new_status);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -365,6 +370,7 @@ _dbus_connection_get_message_to_send (DBusConnection *connection)
|
|||
/**
|
||||
* Notifies the connection that a message has been sent, so the
|
||||
* message can be removed from the outgoing queue.
|
||||
* Called with the connection lock held.
|
||||
*
|
||||
* @param connection the connection.
|
||||
* @param message the message that was sent.
|
||||
|
|
@ -373,10 +379,18 @@ void
|
|||
_dbus_connection_message_sent (DBusConnection *connection,
|
||||
DBusMessage *message)
|
||||
{
|
||||
_dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
|
||||
_dbus_assert (message == _dbus_list_get_last (&connection->outgoing_messages));
|
||||
DBusList *link;
|
||||
|
||||
_dbus_list_pop_last (&connection->outgoing_messages);
|
||||
_dbus_assert (_dbus_transport_get_is_authenticated (connection->transport));
|
||||
|
||||
link = _dbus_list_get_last_link (&connection->outgoing_messages);
|
||||
_dbus_assert (link != NULL);
|
||||
_dbus_assert (link->data == message);
|
||||
|
||||
/* Save this link in the link cache */
|
||||
_dbus_list_unlink (&connection->outgoing_messages,
|
||||
link);
|
||||
_dbus_list_prepend_link (&connection->link_cache, link);
|
||||
|
||||
connection->n_outgoing -= 1;
|
||||
|
||||
|
|
@ -384,7 +398,10 @@ _dbus_connection_message_sent (DBusConnection *connection,
|
|||
message, dbus_message_get_name (message),
|
||||
connection, connection->n_outgoing);
|
||||
|
||||
_dbus_message_remove_size_counter (message, connection->outgoing_counter);
|
||||
/* Save this link in the link cache also */
|
||||
_dbus_message_remove_size_counter (message, connection->outgoing_counter,
|
||||
&link);
|
||||
_dbus_list_prepend_link (&connection->link_cache, link);
|
||||
|
||||
dbus_message_unref (message);
|
||||
|
||||
|
|
@ -724,7 +741,7 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
|
|||
if (_dbus_modify_sigpipe)
|
||||
_dbus_disable_sigpipe ();
|
||||
|
||||
connection->refcount = 1;
|
||||
connection->refcount.value = 1;
|
||||
connection->mutex = mutex;
|
||||
connection->dispatch_cond = dispatch_cond;
|
||||
connection->io_path_cond = io_path_cond;
|
||||
|
|
@ -800,8 +817,12 @@ _dbus_connection_new_for_transport (DBusTransport *transport)
|
|||
void
|
||||
_dbus_connection_ref_unlocked (DBusConnection *connection)
|
||||
{
|
||||
_dbus_assert (connection->refcount > 0);
|
||||
connection->refcount += 1;
|
||||
#ifdef DBUS_HAVE_ATOMIC_INT
|
||||
_dbus_atomic_inc (&connection->refcount);
|
||||
#else
|
||||
_dbus_assert (connection->refcount.value > 0);
|
||||
connection->refcount.value += 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static dbus_uint32_t
|
||||
|
|
@ -892,10 +913,9 @@ _dbus_connection_handle_watch (DBusWatch *watch,
|
|||
_dbus_connection_release_io_path (connection);
|
||||
|
||||
status = _dbus_connection_get_dispatch_status_unlocked (connection);
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
_dbus_connection_update_dispatch_status_locked (connection, status);
|
||||
/* this calls out to user code */
|
||||
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
|
@ -972,9 +992,9 @@ dbus_connection_ref (DBusConnection *connection)
|
|||
_dbus_atomic_inc (&connection->refcount);
|
||||
#else
|
||||
CONNECTION_LOCK (connection);
|
||||
_dbus_assert (connection->refcount > 0);
|
||||
_dbus_assert (connection->refcount.value > 0);
|
||||
|
||||
connection->refcount += 1;
|
||||
connection->refcount.value += 1;
|
||||
CONNECTION_UNLOCK (connection);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -987,7 +1007,8 @@ free_outgoing_message (void *element,
|
|||
DBusConnection *connection = data;
|
||||
|
||||
_dbus_message_remove_size_counter (message,
|
||||
connection->outgoing_counter);
|
||||
connection->outgoing_counter,
|
||||
NULL);
|
||||
dbus_message_unref (message);
|
||||
}
|
||||
|
||||
|
|
@ -1003,7 +1024,7 @@ _dbus_connection_last_unref (DBusConnection *connection)
|
|||
|
||||
_dbus_verbose ("Finalizing connection %p\n", connection);
|
||||
|
||||
_dbus_assert (connection->refcount == 0);
|
||||
_dbus_assert (connection->refcount.value == 0);
|
||||
|
||||
/* You have to disconnect the connection before unref:ing it. Otherwise
|
||||
* you won't get the disconnected message.
|
||||
|
|
@ -1071,10 +1092,12 @@ _dbus_connection_last_unref (DBusConnection *connection)
|
|||
dbus_message_unref (message);
|
||||
_dbus_list_free_link (connection->disconnect_message_link);
|
||||
}
|
||||
|
||||
_dbus_list_clear (&connection->link_cache);
|
||||
|
||||
dbus_condvar_free (connection->dispatch_cond);
|
||||
dbus_condvar_free (connection->io_path_cond);
|
||||
dbus_condvar_free (connection->message_returned_cond);
|
||||
dbus_condvar_free (connection->message_returned_cond);
|
||||
|
||||
dbus_mutex_free (connection->mutex);
|
||||
|
||||
|
|
@ -1104,17 +1127,17 @@ dbus_connection_unref (DBusConnection *connection)
|
|||
*/
|
||||
|
||||
#ifdef DBUS_HAVE_ATOMIC_INT
|
||||
last_unref = (_dbus_atomic_dec (&connection->refcount) == 0);
|
||||
last_unref = (_dbus_atomic_dec (&connection->refcount) == 1);
|
||||
#else
|
||||
CONNECTION_LOCK (connection);
|
||||
|
||||
_dbus_assert (connection->refcount > 0);
|
||||
_dbus_assert (connection->refcount.value > 0);
|
||||
|
||||
connection->refcount -= 1;
|
||||
last_unref = (connection->refcount == 0);
|
||||
connection->refcount.value -= 1;
|
||||
last_unref = (connection->refcount.value == 0);
|
||||
|
||||
#if 0
|
||||
printf ("unref() connection %p count = %d\n", connection, connection->refcount);
|
||||
printf ("unref() connection %p count = %d\n", connection, connection->refcount.value);
|
||||
#endif
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
|
@ -1203,6 +1226,56 @@ struct DBusPreallocatedSend
|
|||
DBusList *counter_link;
|
||||
};
|
||||
|
||||
static DBusPreallocatedSend*
|
||||
_dbus_connection_preallocate_send_unlocked (DBusConnection *connection)
|
||||
{
|
||||
DBusPreallocatedSend *preallocated;
|
||||
|
||||
_dbus_return_val_if_fail (connection != NULL, NULL);
|
||||
|
||||
preallocated = dbus_new (DBusPreallocatedSend, 1);
|
||||
if (preallocated == NULL)
|
||||
return NULL;
|
||||
|
||||
if (connection->link_cache != NULL)
|
||||
{
|
||||
preallocated->queue_link =
|
||||
_dbus_list_pop_first_link (&connection->link_cache);
|
||||
preallocated->queue_link->data = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
preallocated->queue_link = _dbus_list_alloc_link (NULL);
|
||||
if (preallocated->queue_link == NULL)
|
||||
goto failed_0;
|
||||
}
|
||||
|
||||
if (connection->link_cache != NULL)
|
||||
{
|
||||
preallocated->counter_link =
|
||||
_dbus_list_pop_first_link (&connection->link_cache);
|
||||
preallocated->counter_link->data = connection->outgoing_counter;
|
||||
}
|
||||
else
|
||||
{
|
||||
preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
|
||||
if (preallocated->counter_link == NULL)
|
||||
goto failed_1;
|
||||
}
|
||||
|
||||
_dbus_counter_ref (preallocated->counter_link->data);
|
||||
|
||||
preallocated->connection = connection;
|
||||
|
||||
return preallocated;
|
||||
|
||||
failed_1:
|
||||
_dbus_list_free_link (preallocated->queue_link);
|
||||
failed_0:
|
||||
dbus_free (preallocated);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preallocates resources needed to send a message, allowing the message
|
||||
|
|
@ -1219,37 +1292,15 @@ dbus_connection_preallocate_send (DBusConnection *connection)
|
|||
DBusPreallocatedSend *preallocated;
|
||||
|
||||
_dbus_return_val_if_fail (connection != NULL, NULL);
|
||||
|
||||
preallocated = dbus_new (DBusPreallocatedSend, 1);
|
||||
if (preallocated == NULL)
|
||||
return NULL;
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
|
||||
preallocated->queue_link = _dbus_list_alloc_link (NULL);
|
||||
if (preallocated->queue_link == NULL)
|
||||
goto failed_0;
|
||||
|
||||
preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter);
|
||||
if (preallocated->counter_link == NULL)
|
||||
goto failed_1;
|
||||
|
||||
_dbus_counter_ref (preallocated->counter_link->data);
|
||||
|
||||
preallocated->connection = connection;
|
||||
preallocated =
|
||||
_dbus_connection_preallocate_send_unlocked (connection);
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
|
||||
return preallocated;
|
||||
|
||||
failed_1:
|
||||
_dbus_list_free_link (preallocated->queue_link);
|
||||
failed_0:
|
||||
dbus_free (preallocated);
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1266,43 +1317,23 @@ dbus_connection_free_preallocated_send (DBusConnection *connection,
|
|||
DBusPreallocatedSend *preallocated)
|
||||
{
|
||||
_dbus_return_if_fail (connection != NULL);
|
||||
_dbus_return_if_fail (preallocated != NULL);
|
||||
_dbus_return_if_fail (preallocated != NULL);
|
||||
_dbus_return_if_fail (connection == preallocated->connection);
|
||||
|
||||
|
||||
_dbus_list_free_link (preallocated->queue_link);
|
||||
_dbus_counter_unref (preallocated->counter_link->data);
|
||||
_dbus_list_free_link (preallocated->counter_link);
|
||||
dbus_free (preallocated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message using preallocated resources. This function cannot fail.
|
||||
* It works identically to dbus_connection_send() in other respects.
|
||||
* Preallocated resources comes from dbus_connection_preallocate_send().
|
||||
* This function "consumes" the preallocated resources, they need not
|
||||
* be freed separately.
|
||||
*
|
||||
* @param connection the connection
|
||||
* @param preallocated the preallocated resources
|
||||
* @param message the message to send
|
||||
* @param client_serial return location for client serial assigned to the message
|
||||
*/
|
||||
void
|
||||
dbus_connection_send_preallocated (DBusConnection *connection,
|
||||
DBusPreallocatedSend *preallocated,
|
||||
DBusMessage *message,
|
||||
dbus_uint32_t *client_serial)
|
||||
static void
|
||||
_dbus_connection_send_preallocated_unlocked (DBusConnection *connection,
|
||||
DBusPreallocatedSend *preallocated,
|
||||
DBusMessage *message,
|
||||
dbus_uint32_t *client_serial)
|
||||
{
|
||||
dbus_uint32_t serial;
|
||||
|
||||
_dbus_return_if_fail (connection != NULL);
|
||||
_dbus_return_if_fail (preallocated != NULL);
|
||||
_dbus_return_if_fail (message != NULL);
|
||||
_dbus_return_if_fail (preallocated->connection == connection);
|
||||
_dbus_return_if_fail (dbus_message_get_name (message) != NULL);
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
|
||||
preallocated->queue_link->data = message;
|
||||
_dbus_list_prepend_link (&connection->outgoing_messages,
|
||||
preallocated->queue_link);
|
||||
|
|
@ -1343,8 +1374,37 @@ dbus_connection_send_preallocated (DBusConnection *connection,
|
|||
connection->n_outgoing);
|
||||
|
||||
_dbus_connection_wakeup_mainloop (connection);
|
||||
}
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
/**
|
||||
* Sends a message using preallocated resources. This function cannot fail.
|
||||
* It works identically to dbus_connection_send() in other respects.
|
||||
* Preallocated resources comes from dbus_connection_preallocate_send().
|
||||
* This function "consumes" the preallocated resources, they need not
|
||||
* be freed separately.
|
||||
*
|
||||
* @param connection the connection
|
||||
* @param preallocated the preallocated resources
|
||||
* @param message the message to send
|
||||
* @param client_serial return location for client serial assigned to the message
|
||||
*/
|
||||
void
|
||||
dbus_connection_send_preallocated (DBusConnection *connection,
|
||||
DBusPreallocatedSend *preallocated,
|
||||
DBusMessage *message,
|
||||
dbus_uint32_t *client_serial)
|
||||
{
|
||||
_dbus_return_if_fail (connection != NULL);
|
||||
_dbus_return_if_fail (preallocated != NULL);
|
||||
_dbus_return_if_fail (message != NULL);
|
||||
_dbus_return_if_fail (preallocated->connection == connection);
|
||||
_dbus_return_if_fail (dbus_message_get_name (message) != NULL);
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
_dbus_connection_send_preallocated_unlocked (connection,
|
||||
preallocated,
|
||||
message, client_serial);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1374,15 +1434,22 @@ dbus_connection_send (DBusConnection *connection,
|
|||
|
||||
_dbus_return_val_if_fail (connection != NULL, FALSE);
|
||||
_dbus_return_val_if_fail (message != NULL, FALSE);
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
|
||||
preallocated = dbus_connection_preallocate_send (connection);
|
||||
preallocated = _dbus_connection_preallocate_send_unlocked (connection);
|
||||
if (preallocated == NULL)
|
||||
{
|
||||
CONNECTION_UNLOCK (connection);
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dbus_connection_send_preallocated (connection, preallocated, message, client_serial);
|
||||
_dbus_connection_send_preallocated_unlocked (connection,
|
||||
preallocated,
|
||||
message,
|
||||
client_serial);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1409,10 +1476,9 @@ reply_handler_timeout (void *data)
|
|||
reply_handler_data->timeout_added = FALSE;
|
||||
|
||||
status = _dbus_connection_get_dispatch_status_unlocked (connection);
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
_dbus_connection_update_dispatch_status_locked (connection, status);
|
||||
/* Unlocks, and calls out to user code */
|
||||
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
@ -1711,13 +1777,12 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection,
|
|||
if (reply != NULL)
|
||||
{
|
||||
status = _dbus_connection_get_dispatch_status_unlocked (connection);
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
_dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply %s\n",
|
||||
dbus_message_get_name (reply));
|
||||
|
||||
_dbus_connection_update_dispatch_status_locked (connection, status);
|
||||
/* Unlocks, and calls out to user code */
|
||||
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
|
@ -1771,10 +1836,9 @@ dbus_connection_send_with_reply_and_block (DBusConnection *connection,
|
|||
dbus_set_error (error, DBUS_ERROR_NO_REPLY, "Message did not receive a reply");
|
||||
else
|
||||
dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply");
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
_dbus_connection_update_dispatch_status_locked (connection, status);
|
||||
/* unlocks and calls out to user code */
|
||||
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1806,10 +1870,9 @@ dbus_connection_flush (DBusConnection *connection)
|
|||
-1);
|
||||
|
||||
status = _dbus_connection_get_dispatch_status_unlocked (connection);
|
||||
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
_dbus_connection_update_dispatch_status_locked (connection, status);
|
||||
/* Unlocks and calls out to user code */
|
||||
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
|
||||
}
|
||||
|
||||
/* Call with mutex held. Will drop it while waiting and re-acquire
|
||||
|
|
@ -2052,7 +2115,7 @@ _dbus_connection_release_dispatch (DBusConnection *connection)
|
|||
|
||||
static void
|
||||
_dbus_connection_failed_pop (DBusConnection *connection,
|
||||
DBusList *message_link)
|
||||
DBusList *message_link)
|
||||
{
|
||||
_dbus_list_prepend_link (&connection->incoming_messages,
|
||||
message_link);
|
||||
|
|
@ -2082,14 +2145,15 @@ _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection)
|
|||
}
|
||||
|
||||
static void
|
||||
_dbus_connection_update_dispatch_status_locked (DBusConnection *connection,
|
||||
DBusDispatchStatus new_status)
|
||||
_dbus_connection_update_dispatch_status_and_unlock (DBusConnection *connection,
|
||||
DBusDispatchStatus new_status)
|
||||
{
|
||||
dbus_bool_t changed;
|
||||
DBusDispatchStatusFunction function;
|
||||
void *data;
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
|
||||
/* We have the lock */
|
||||
|
||||
_dbus_connection_ref_unlocked (connection);
|
||||
|
||||
changed = new_status != connection->last_dispatch_status;
|
||||
|
|
@ -2098,7 +2162,8 @@ _dbus_connection_update_dispatch_status_locked (DBusConnection *connection,
|
|||
|
||||
function = connection->dispatch_status_function;
|
||||
data = connection->dispatch_status_data;
|
||||
|
||||
|
||||
/* We drop the lock */
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
if (changed && function)
|
||||
|
|
@ -2166,15 +2231,15 @@ dbus_connection_dispatch (DBusConnection *connection)
|
|||
DBusDispatchStatus status;
|
||||
|
||||
_dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE);
|
||||
|
||||
status = dbus_connection_get_dispatch_status (connection);
|
||||
if (status != DBUS_DISPATCH_DATA_REMAINS)
|
||||
{
|
||||
_dbus_connection_update_dispatch_status_locked (connection, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
CONNECTION_LOCK (connection);
|
||||
status = _dbus_connection_get_dispatch_status_unlocked (connection);
|
||||
if (status != DBUS_DISPATCH_DATA_REMAINS)
|
||||
{
|
||||
/* unlocks and calls out to user code */
|
||||
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
/* We need to ref the connection since the callback could potentially
|
||||
* drop the last ref to it
|
||||
|
|
@ -2195,11 +2260,10 @@ dbus_connection_dispatch (DBusConnection *connection)
|
|||
/* another thread dispatched our stuff */
|
||||
|
||||
_dbus_connection_release_dispatch (connection);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
status = dbus_connection_get_dispatch_status (connection);
|
||||
status = _dbus_connection_get_dispatch_status_unlocked (connection);
|
||||
|
||||
_dbus_connection_update_dispatch_status_locked (connection, status);
|
||||
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
|
||||
|
||||
dbus_connection_unref (connection);
|
||||
|
||||
|
|
@ -2217,10 +2281,12 @@ dbus_connection_dispatch (DBusConnection *connection)
|
|||
if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))
|
||||
{
|
||||
_dbus_connection_release_dispatch (connection);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
_dbus_connection_failed_pop (connection, message_link);
|
||||
|
||||
_dbus_connection_update_dispatch_status_locked (connection, DBUS_DISPATCH_NEED_MEMORY);
|
||||
/* unlocks and calls user code */
|
||||
_dbus_connection_update_dispatch_status_and_unlock (connection,
|
||||
DBUS_DISPATCH_NEED_MEMORY);
|
||||
|
||||
dbus_connection_unref (connection);
|
||||
|
||||
|
|
@ -2320,15 +2386,16 @@ dbus_connection_dispatch (DBusConnection *connection)
|
|||
|
||||
out:
|
||||
_dbus_connection_release_dispatch (connection);
|
||||
CONNECTION_UNLOCK (connection);
|
||||
|
||||
_dbus_list_free_link (message_link);
|
||||
dbus_message_unref (message); /* don't want the message to count in max message limits
|
||||
* in computing dispatch status
|
||||
*/
|
||||
|
||||
status = dbus_connection_get_dispatch_status (connection);
|
||||
status = _dbus_connection_get_dispatch_status_unlocked (connection);
|
||||
|
||||
_dbus_connection_update_dispatch_status_locked (connection, status);
|
||||
/* unlocks and calls user code */
|
||||
_dbus_connection_update_dispatch_status_and_unlock (connection, status);
|
||||
|
||||
dbus_connection_unref (connection);
|
||||
|
||||
|
|
|
|||
|
|
@ -454,20 +454,43 @@ _dbus_list_remove_last (DBusList **list,
|
|||
{
|
||||
DBusList *link;
|
||||
|
||||
link = _dbus_list_find_last (list, data);
|
||||
if (link)
|
||||
{
|
||||
_dbus_list_remove_link (list, link);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a value in the list. Returns the last link
|
||||
* with value equal to the given data pointer.
|
||||
* This is a linear-time operation.
|
||||
* Returns #NULL if no value found that matches.
|
||||
*
|
||||
* @param list address of the list head.
|
||||
* @param data the value to find.
|
||||
* @returns the link if found
|
||||
*/
|
||||
DBusList*
|
||||
_dbus_list_find_last (DBusList **list,
|
||||
void *data)
|
||||
{
|
||||
DBusList *link;
|
||||
|
||||
link = _dbus_list_get_last_link (list);
|
||||
|
||||
while (link != NULL)
|
||||
{
|
||||
if (link->data == data)
|
||||
{
|
||||
_dbus_list_remove_link (list, link);
|
||||
return TRUE;
|
||||
}
|
||||
return link;
|
||||
|
||||
link = _dbus_list_get_prev_link (list, link);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -60,6 +60,8 @@ dbus_bool_t _dbus_list_remove_last (DBusList **list,
|
|||
void *data);
|
||||
void _dbus_list_remove_link (DBusList **list,
|
||||
DBusList *link);
|
||||
DBusList* _dbus_list_find_last (DBusList **list,
|
||||
void *data);
|
||||
void _dbus_list_clear (DBusList **list);
|
||||
DBusList* _dbus_list_get_first_link (DBusList **list);
|
||||
DBusList* _dbus_list_get_last_link (DBusList **list);
|
||||
|
|
|
|||
|
|
@ -430,13 +430,11 @@ marshal_4_octets (DBusString *str,
|
|||
{
|
||||
_dbus_assert (sizeof (value) == 4);
|
||||
|
||||
if (!_dbus_string_align_length (str, sizeof (dbus_uint32_t)))
|
||||
return FALSE;
|
||||
|
||||
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
|
||||
value = DBUS_UINT32_SWAP_LE_BE (value);
|
||||
|
||||
return _dbus_string_append_len (str, (const char *)&value, sizeof (dbus_uint32_t));
|
||||
return _dbus_string_append_4_aligned (str,
|
||||
(const unsigned char *)&value);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
|
|
@ -445,14 +443,12 @@ marshal_8_octets (DBusString *str,
|
|||
DBusOctets8 value)
|
||||
{
|
||||
_dbus_assert (sizeof (value) == 8);
|
||||
|
||||
if (!_dbus_string_align_length (str, 8))
|
||||
return FALSE;
|
||||
|
||||
if (byte_order != DBUS_COMPILER_BYTE_ORDER)
|
||||
pack_8_octets (value, byte_order, (unsigned char*) &value); /* pack into self, swapping as we go */
|
||||
|
||||
return _dbus_string_append_len (str, (const char *)&value, 8);
|
||||
return _dbus_string_append_8_aligned (str,
|
||||
(const unsigned char *)&value);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1646,6 +1642,99 @@ _dbus_marshal_validate_type (const DBusString *str,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/* Faster validator for array data that doesn't call
|
||||
* validate_arg for each value
|
||||
*/
|
||||
static dbus_bool_t
|
||||
validate_array_data (const DBusString *str,
|
||||
int byte_order,
|
||||
int depth,
|
||||
int type,
|
||||
int array_type_pos,
|
||||
int pos,
|
||||
int *new_pos,
|
||||
int end)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DBUS_TYPE_INVALID:
|
||||
return FALSE;
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_NIL:
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_STRING:
|
||||
case DBUS_TYPE_NAMED:
|
||||
case DBUS_TYPE_ARRAY:
|
||||
case DBUS_TYPE_DICT:
|
||||
/* This clean recursion to validate_arg is what we
|
||||
* are doing logically for all types, but we don't
|
||||
* really want to call validate_arg for every byte
|
||||
* in a byte array, so the primitive types are
|
||||
* special-cased.
|
||||
*/
|
||||
while (pos < end)
|
||||
{
|
||||
if (!_dbus_marshal_validate_arg (str, byte_order, depth,
|
||||
type, array_type_pos, pos, &pos))
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_BYTE:
|
||||
pos = end;
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_BOOLEAN:
|
||||
while (pos < end)
|
||||
{
|
||||
unsigned char c;
|
||||
|
||||
c = _dbus_string_get_byte (str, pos);
|
||||
|
||||
if (!(c == 0 || c == 1))
|
||||
{
|
||||
_dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
++pos;
|
||||
}
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_INT32:
|
||||
case DBUS_TYPE_UINT32:
|
||||
/* Call validate arg one time to check alignment padding
|
||||
* at start of array
|
||||
*/
|
||||
if (!_dbus_marshal_validate_arg (str, byte_order, depth,
|
||||
type, array_type_pos, pos, &pos))
|
||||
return FALSE;
|
||||
pos = _DBUS_ALIGN_VALUE (end, 4);
|
||||
break;
|
||||
|
||||
case DBUS_TYPE_INT64:
|
||||
case DBUS_TYPE_UINT64:
|
||||
case DBUS_TYPE_DOUBLE:
|
||||
/* Call validate arg one time to check alignment padding
|
||||
* at start of array
|
||||
*/
|
||||
if (!_dbus_marshal_validate_arg (str, byte_order, depth,
|
||||
type, array_type_pos, pos, &pos))
|
||||
return FALSE;
|
||||
pos = _DBUS_ALIGN_VALUE (end, 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
_dbus_verbose ("Unknown message arg type %d\n", type);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*new_pos = pos;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates an argument of a specific type, checking that it
|
||||
|
|
@ -1726,7 +1815,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
|
|||
|
||||
c = _dbus_string_get_byte (str, pos);
|
||||
|
||||
if (c != 0 && c != 1)
|
||||
if (!(c == 0 || c == 1))
|
||||
{
|
||||
_dbus_verbose ("boolean value must be either 0 or 1, not %d\n", c);
|
||||
return FALSE;
|
||||
|
|
@ -1874,13 +1963,11 @@ _dbus_marshal_validate_arg (const DBusString *str,
|
|||
}
|
||||
|
||||
end = pos + len;
|
||||
|
||||
while (pos < end)
|
||||
{
|
||||
if (!_dbus_marshal_validate_arg (str, byte_order, depth + 1,
|
||||
array_type, array_type_pos, pos, &pos))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!validate_array_data (str, byte_order, depth + 1,
|
||||
array_type, array_type_pos,
|
||||
pos, &pos, end))
|
||||
return FALSE;
|
||||
|
||||
if (pos < end)
|
||||
{
|
||||
|
|
@ -1888,7 +1975,7 @@ _dbus_marshal_validate_arg (const DBusString *str,
|
|||
* but the check is here just to be paranoid.
|
||||
*/
|
||||
_dbus_verbose ("array length %d specified was longer than actual array contents by %d\n",
|
||||
len, end - pos);
|
||||
len, end - pos);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* -*- mode: C; c-file-style: "gnu" -*- */
|
||||
/* dbus-message-handler.c Sender/receiver of messages.
|
||||
*
|
||||
* Copyright (C) 2002 Red Hat Inc.
|
||||
* Copyright (C) 2002, 2003 Red Hat Inc.
|
||||
*
|
||||
* Licensed under the Academic Free License version 1.2
|
||||
*
|
||||
|
|
@ -47,7 +47,7 @@ _DBUS_DEFINE_GLOBAL_LOCK (message_handler);
|
|||
*/
|
||||
struct DBusMessageHandler
|
||||
{
|
||||
int refcount; /**< reference count */
|
||||
DBusAtomic refcount; /**< reference count */
|
||||
|
||||
DBusHandleMessageFunction function; /**< handler function */
|
||||
void *user_data; /**< user data for function */
|
||||
|
|
@ -176,7 +176,7 @@ dbus_message_handler_new (DBusHandleMessageFunction function,
|
|||
if (handler == NULL)
|
||||
return NULL;
|
||||
|
||||
handler->refcount = 1;
|
||||
handler->refcount.value = 1;
|
||||
handler->function = function;
|
||||
handler->user_data = user_data;
|
||||
handler->free_user_data = free_user_data;
|
||||
|
|
@ -194,12 +194,8 @@ void
|
|||
dbus_message_handler_ref (DBusMessageHandler *handler)
|
||||
{
|
||||
_dbus_return_if_fail (handler != NULL);
|
||||
|
||||
_DBUS_LOCK (message_handler);
|
||||
_dbus_assert (handler != NULL);
|
||||
|
||||
handler->refcount += 1;
|
||||
_DBUS_UNLOCK (message_handler);
|
||||
|
||||
_dbus_atomic_inc (&handler->refcount);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -211,21 +207,13 @@ dbus_message_handler_ref (DBusMessageHandler *handler)
|
|||
void
|
||||
dbus_message_handler_unref (DBusMessageHandler *handler)
|
||||
{
|
||||
int refcount;
|
||||
dbus_bool_t last_unref;
|
||||
|
||||
_dbus_return_if_fail (handler != NULL);
|
||||
|
||||
_DBUS_LOCK (message_handler);
|
||||
|
||||
_dbus_assert (handler != NULL);
|
||||
_dbus_assert (handler->refcount > 0);
|
||||
|
||||
handler->refcount -= 1;
|
||||
refcount = handler->refcount;
|
||||
last_unref = (_dbus_atomic_dec (&handler->refcount) == 1);
|
||||
|
||||
_DBUS_UNLOCK (message_handler);
|
||||
|
||||
if (refcount == 0)
|
||||
if (last_unref)
|
||||
{
|
||||
DBusList *link;
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,8 @@ dbus_bool_t _dbus_message_add_size_counter (DBusMessage *message,
|
|||
void _dbus_message_add_size_counter_link (DBusMessage *message,
|
||||
DBusList *link);
|
||||
void _dbus_message_remove_size_counter (DBusMessage *message,
|
||||
DBusCounter *counter);
|
||||
DBusCounter *counter,
|
||||
DBusList **link_return);
|
||||
|
||||
DBusMessageLoader* _dbus_message_loader_new (void);
|
||||
void _dbus_message_loader_ref (DBusMessageLoader *loader);
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ typedef struct
|
|||
*/
|
||||
struct DBusMessage
|
||||
{
|
||||
volatile dbus_atomic_t refcount; /**< Reference count */
|
||||
DBusAtomic refcount; /**< Reference count */
|
||||
|
||||
DBusString header; /**< Header network data, stored
|
||||
* separately from body so we can
|
||||
|
|
@ -772,15 +772,26 @@ _dbus_message_add_size_counter (DBusMessage *message,
|
|||
* the counter by the size of this message.
|
||||
*
|
||||
* @param message the message
|
||||
* @param link_return return the link used
|
||||
* @param counter the counter
|
||||
*/
|
||||
void
|
||||
_dbus_message_remove_size_counter (DBusMessage *message,
|
||||
DBusCounter *counter)
|
||||
DBusCounter *counter,
|
||||
DBusList **link_return)
|
||||
{
|
||||
if (!_dbus_list_remove_last (&message->size_counters,
|
||||
counter))
|
||||
_dbus_assert_not_reached ("Removed a message size counter that was not added");
|
||||
DBusList *link;
|
||||
|
||||
link = _dbus_list_find_last (&message->size_counters,
|
||||
counter);
|
||||
_dbus_assert (link != NULL);
|
||||
|
||||
_dbus_list_unlink (&message->size_counters,
|
||||
link);
|
||||
if (link_return)
|
||||
*link_return = link;
|
||||
else
|
||||
_dbus_list_free_link (link);
|
||||
|
||||
_dbus_counter_adjust (counter, message->size_counter_delta);
|
||||
|
||||
|
|
@ -898,7 +909,7 @@ dbus_message_new_empty_header (void)
|
|||
if (message == NULL)
|
||||
return NULL;
|
||||
|
||||
message->refcount = 1;
|
||||
message->refcount.value = 1;
|
||||
message->byte_order = DBUS_COMPILER_BYTE_ORDER;
|
||||
message->client_serial = 0;
|
||||
message->reply_serial = 0;
|
||||
|
|
@ -910,13 +921,13 @@ dbus_message_new_empty_header (void)
|
|||
++i;
|
||||
}
|
||||
|
||||
if (!_dbus_string_init (&message->header))
|
||||
if (!_dbus_string_init_preallocated (&message->header, 64))
|
||||
{
|
||||
dbus_free (message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_dbus_string_init (&message->body))
|
||||
if (!_dbus_string_init_preallocated (&message->body, 64))
|
||||
{
|
||||
_dbus_string_free (&message->header);
|
||||
dbus_free (message);
|
||||
|
|
@ -1076,7 +1087,7 @@ dbus_message_copy (const DBusMessage *message)
|
|||
if (retval == NULL)
|
||||
return NULL;
|
||||
|
||||
retval->refcount = 1;
|
||||
retval->refcount.value = 1;
|
||||
retval->byte_order = message->byte_order;
|
||||
retval->client_serial = message->client_serial;
|
||||
retval->reply_serial = message->reply_serial;
|
||||
|
|
@ -1134,12 +1145,12 @@ dbus_message_copy (const DBusMessage *message)
|
|||
void
|
||||
dbus_message_ref (DBusMessage *message)
|
||||
{
|
||||
volatile dbus_atomic_t refcount;
|
||||
dbus_int32_t old_refcount;
|
||||
|
||||
_dbus_return_if_fail (message != NULL);
|
||||
|
||||
refcount = _dbus_atomic_inc (&message->refcount);
|
||||
_dbus_assert (refcount > 1);
|
||||
old_refcount = _dbus_atomic_inc (&message->refcount);
|
||||
_dbus_assert (old_refcount >= 1);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1163,15 +1174,15 @@ free_size_counter (void *element,
|
|||
void
|
||||
dbus_message_unref (DBusMessage *message)
|
||||
{
|
||||
volatile dbus_atomic_t refcount;
|
||||
dbus_int32_t old_refcount;
|
||||
|
||||
_dbus_return_if_fail (message != NULL);
|
||||
|
||||
refcount = _dbus_atomic_dec (&message->refcount);
|
||||
old_refcount = _dbus_atomic_dec (&message->refcount);
|
||||
|
||||
_dbus_assert (refcount >= 0);
|
||||
_dbus_assert (old_refcount >= 0);
|
||||
|
||||
if (refcount == 0)
|
||||
if (old_refcount == 1)
|
||||
{
|
||||
_dbus_list_foreach (&message->size_counters,
|
||||
free_size_counter, message);
|
||||
|
|
|
|||
|
|
@ -169,14 +169,17 @@ undo_alignment (DBusRealString *real)
|
|||
}
|
||||
|
||||
/**
|
||||
* Initializes a string. The string starts life with zero length. The
|
||||
* string must eventually be freed with _dbus_string_free().
|
||||
* Initializes a string that can be up to the given allocation size
|
||||
* before it has to realloc. The string starts life with zero length.
|
||||
* The string must eventually be freed with _dbus_string_free().
|
||||
*
|
||||
* @param str memory to hold the string
|
||||
* @param allocate_size amount to preallocate
|
||||
* @returns #TRUE on success, #FALSE if no memory
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_string_init (DBusString *str)
|
||||
_dbus_string_init_preallocated (DBusString *str,
|
||||
int allocate_size)
|
||||
{
|
||||
DBusRealString *real;
|
||||
|
||||
|
|
@ -192,11 +195,11 @@ _dbus_string_init (DBusString *str)
|
|||
* an existing string, e.g. in _dbus_string_steal_data()
|
||||
*/
|
||||
|
||||
real->str = dbus_malloc (ALLOCATION_PADDING);
|
||||
real->str = dbus_malloc (ALLOCATION_PADDING + allocate_size);
|
||||
if (real->str == NULL)
|
||||
return FALSE;
|
||||
|
||||
real->allocated = ALLOCATION_PADDING;
|
||||
real->allocated = ALLOCATION_PADDING + allocate_size;
|
||||
real->len = 0;
|
||||
real->str[real->len] = '\0';
|
||||
|
||||
|
|
@ -211,6 +214,19 @@ _dbus_string_init (DBusString *str)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a string. The string starts life with zero length. The
|
||||
* string must eventually be freed with _dbus_string_free().
|
||||
*
|
||||
* @param str memory to hold the string
|
||||
* @returns #TRUE on success, #FALSE if no memory
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_string_init (DBusString *str)
|
||||
{
|
||||
return _dbus_string_init_preallocated (str, 0);
|
||||
}
|
||||
|
||||
/* The max length thing is sort of a historical artifact
|
||||
* from a feature that turned out to be dumb; perhaps
|
||||
* we should purge it entirely. The problem with
|
||||
|
|
@ -344,54 +360,63 @@ _dbus_string_lock (DBusString *str)
|
|||
}
|
||||
#endif /* DBUS_BUILD_TESTS */
|
||||
|
||||
static dbus_bool_t
|
||||
reallocate_for_length (DBusRealString *real,
|
||||
int new_length)
|
||||
{
|
||||
int new_allocated;
|
||||
char *new_str;
|
||||
|
||||
/* at least double our old allocation to avoid O(n), avoiding
|
||||
* overflow
|
||||
*/
|
||||
if (real->allocated > (MAX_MAX_LENGTH + ALLOCATION_PADDING) / 2)
|
||||
new_allocated = MAX_MAX_LENGTH + ALLOCATION_PADDING;
|
||||
else
|
||||
new_allocated = real->allocated * 2;
|
||||
|
||||
/* if you change the code just above here, run the tests without
|
||||
* the following before you commit
|
||||
*/
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
new_allocated = 0; /* ensure a realloc every time so that we go
|
||||
* through all malloc failure codepaths
|
||||
*/
|
||||
#endif
|
||||
|
||||
/* But be sure we always alloc at least space for the new length */
|
||||
new_allocated = MAX (new_allocated, new_length + ALLOCATION_PADDING);
|
||||
|
||||
_dbus_assert (new_allocated >= real->allocated); /* code relies on this */
|
||||
new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
|
||||
if (new_str == NULL)
|
||||
return FALSE;
|
||||
|
||||
real->str = new_str + real->align_offset;
|
||||
real->allocated = new_allocated;
|
||||
fixup_alignment (real);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
set_length (DBusRealString *real,
|
||||
int new_length)
|
||||
{
|
||||
/* Note, we are setting the length without nul termination */
|
||||
/* Note, we are setting the length not including nul termination */
|
||||
|
||||
/* exceeding max length is the same as failure to allocate memory */
|
||||
if (new_length > real->max_length)
|
||||
return FALSE;
|
||||
|
||||
if (new_length > (real->allocated - ALLOCATION_PADDING))
|
||||
else if (new_length > (real->allocated - ALLOCATION_PADDING) &&
|
||||
!reallocate_for_length (real, new_length))
|
||||
return FALSE;
|
||||
else
|
||||
{
|
||||
int new_allocated;
|
||||
char *new_str;
|
||||
|
||||
/* at least double our old allocation to avoid O(n), avoiding
|
||||
* overflow
|
||||
*/
|
||||
if (real->allocated > (MAX_MAX_LENGTH + ALLOCATION_PADDING) / 2)
|
||||
new_allocated = MAX_MAX_LENGTH + ALLOCATION_PADDING;
|
||||
else
|
||||
new_allocated = real->allocated * 2;
|
||||
|
||||
/* if you change the code just above here, run the tests without
|
||||
* the following before you commit
|
||||
*/
|
||||
#ifdef DBUS_BUILD_TESTS
|
||||
new_allocated = 0; /* ensure a realloc every time so that we go
|
||||
* through all malloc failure codepaths
|
||||
*/
|
||||
#endif
|
||||
|
||||
/* But be sure we always alloc at least space for the new length */
|
||||
new_allocated = MAX (new_allocated, new_length + ALLOCATION_PADDING);
|
||||
|
||||
new_str = dbus_realloc (real->str - real->align_offset, new_allocated);
|
||||
if (new_str == NULL)
|
||||
return FALSE;
|
||||
|
||||
real->str = new_str + real->align_offset;
|
||||
real->allocated = new_allocated;
|
||||
fixup_alignment (real);
|
||||
real->len = new_length;
|
||||
real->str[real->len] = '\0';
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
real->len = new_length;
|
||||
real->str[real->len] = '\0';
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
|
|
@ -795,6 +820,48 @@ _dbus_string_set_length (DBusString *str,
|
|||
return set_length (real, length);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
align_length_then_lengthen (DBusString *str,
|
||||
int alignment,
|
||||
int then_lengthen_by)
|
||||
{
|
||||
unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
|
||||
int delta;
|
||||
DBUS_STRING_PREAMBLE (str);
|
||||
_dbus_assert (alignment >= 1);
|
||||
_dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
|
||||
|
||||
new_len = _DBUS_ALIGN_VALUE (real->len, alignment);
|
||||
if (new_len > (unsigned long) real->max_length - then_lengthen_by)
|
||||
return FALSE;
|
||||
new_len += then_lengthen_by;
|
||||
|
||||
delta = new_len - real->len;
|
||||
_dbus_assert (delta >= 0);
|
||||
|
||||
if (delta == 0)
|
||||
return TRUE;
|
||||
|
||||
if (!set_length (real, new_len))
|
||||
return FALSE;
|
||||
|
||||
/* delta == padding + then_lengthen_by
|
||||
* new_len == old_len + padding + then_lengthen_by
|
||||
*/
|
||||
if (then_lengthen_by < delta)
|
||||
{
|
||||
unsigned int i;
|
||||
i = new_len - delta;
|
||||
while (i < (new_len - then_lengthen_by))
|
||||
{
|
||||
real->str[i] = '\0';
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Align the length of a string to a specific alignment (typically 4 or 8)
|
||||
* by appending nul bytes to the string.
|
||||
|
|
@ -807,29 +874,7 @@ dbus_bool_t
|
|||
_dbus_string_align_length (DBusString *str,
|
||||
int alignment)
|
||||
{
|
||||
unsigned long new_len; /* ulong to avoid _DBUS_ALIGN_VALUE overflow */
|
||||
int delta;
|
||||
DBUS_STRING_PREAMBLE (str);
|
||||
_dbus_assert (alignment >= 1);
|
||||
_dbus_assert (alignment <= 8); /* it has to be a bug if > 8 */
|
||||
|
||||
new_len = _DBUS_ALIGN_VALUE (real->len, alignment);
|
||||
if (new_len > (unsigned long) real->max_length)
|
||||
return FALSE;
|
||||
|
||||
delta = new_len - real->len;
|
||||
_dbus_assert (delta >= 0);
|
||||
|
||||
if (delta == 0)
|
||||
return TRUE;
|
||||
|
||||
if (!set_length (real, new_len))
|
||||
return FALSE;
|
||||
|
||||
memset (real->str + (new_len - delta),
|
||||
'\0', delta);
|
||||
|
||||
return TRUE;
|
||||
return align_length_then_lengthen (str, alignment, 0);
|
||||
}
|
||||
|
||||
static dbus_bool_t
|
||||
|
|
@ -873,6 +918,74 @@ _dbus_string_append (DBusString *str,
|
|||
return append (real, buffer, buffer_len);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends 4 bytes aligned on a 4 byte boundary
|
||||
* with any alignment padding initialized to 0.
|
||||
*
|
||||
* @param str the DBusString
|
||||
* @param octets 4 bytes to append
|
||||
* @returns #FALSE if not enough memory.
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_string_append_4_aligned (DBusString *str,
|
||||
const unsigned char octets[4])
|
||||
{
|
||||
dbus_uint32_t *p;
|
||||
DBUS_STRING_PREAMBLE (str);
|
||||
|
||||
if (!align_length_then_lengthen (str, 4, 4))
|
||||
return FALSE;
|
||||
|
||||
p = (dbus_uint32_t*) (real->str + (real->len - 4));
|
||||
*p = *((dbus_uint32_t*)octets);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends 8 bytes aligned on an 8 byte boundary
|
||||
* with any alignment padding initialized to 0.
|
||||
*
|
||||
* @param str the DBusString
|
||||
* @param octets 4 bytes to append
|
||||
* @returns #FALSE if not enough memory.
|
||||
*/
|
||||
dbus_bool_t
|
||||
_dbus_string_append_8_aligned (DBusString *str,
|
||||
const unsigned char octets[8])
|
||||
{
|
||||
#ifdef DBUS_HAVE_INT64
|
||||
dbus_uint64_t *p;
|
||||
DBUS_STRING_PREAMBLE (str);
|
||||
|
||||
if (!align_length_then_lengthen (str, 8, 8))
|
||||
return FALSE;
|
||||
|
||||
p = (dbus_uint64_t*) (real->str + (real->len - 8));
|
||||
*p = *((dbus_uint64_t*)octets);
|
||||
#else
|
||||
char *p;
|
||||
DBUS_STRING_PREAMBLE (str);
|
||||
|
||||
if (!align_length_then_lengthen (str, 8, 8))
|
||||
return FALSE;
|
||||
|
||||
p = real->str + (real->len - 8);
|
||||
|
||||
*p++ = octets[0];
|
||||
*p++ = octets[1];
|
||||
*p++ = octets[2];
|
||||
*p++ = octets[3];
|
||||
*p++ = octets[4];
|
||||
*p++ = octets[5];
|
||||
*p++ = octets[6];
|
||||
*p++ = octets[7];
|
||||
_dbus_assert (p == (real->str + real->len));
|
||||
#endif
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends block of bytes with the given length to a DBusString.
|
||||
*
|
||||
|
|
@ -1080,18 +1193,12 @@ _dbus_string_move (DBusString *source,
|
|||
DBusString *dest,
|
||||
int insert_at)
|
||||
{
|
||||
DBUS_STRING_COPY_PREAMBLE (source, start, dest, insert_at);
|
||||
DBusRealString *real_source = (DBusRealString*) source;
|
||||
_dbus_assert (start <= real_source->len);
|
||||
|
||||
if (!copy (real_source, start,
|
||||
real_source->len - start,
|
||||
real_dest,
|
||||
insert_at))
|
||||
return FALSE;
|
||||
|
||||
delete (real_source, start,
|
||||
real_source->len - start);
|
||||
|
||||
return TRUE;
|
||||
return _dbus_string_move_len (source, start,
|
||||
real_source->len - start,
|
||||
dest, insert_at);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1121,6 +1228,9 @@ _dbus_string_copy (const DBusString *source,
|
|||
/**
|
||||
* Like _dbus_string_move(), but can move a segment from
|
||||
* the middle of the source string.
|
||||
*
|
||||
* @todo this doesn't do anything with max_length field.
|
||||
* we should probably just kill the max_length field though.
|
||||
*
|
||||
* @param source the source string
|
||||
* @param start first byte of source string to move
|
||||
|
|
@ -1141,15 +1251,48 @@ _dbus_string_move_len (DBusString *source,
|
|||
_dbus_assert (len >= 0);
|
||||
_dbus_assert ((start + len) <= real_source->len);
|
||||
|
||||
if (!copy (real_source, start, len,
|
||||
real_dest,
|
||||
insert_at))
|
||||
return FALSE;
|
||||
|
||||
delete (real_source, start,
|
||||
len);
|
||||
if (len == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else if (start == 0 &&
|
||||
len == real_source->len &&
|
||||
real_dest->len == 0)
|
||||
{
|
||||
/* Short-circuit moving an entire existing string to an empty string
|
||||
* by just swapping the buffers.
|
||||
*/
|
||||
/* we assume ->constant doesn't matter as you can't have
|
||||
* a constant string involved in a move.
|
||||
*/
|
||||
#define ASSIGN_DATA(a, b) do { \
|
||||
(a)->str = (b)->str; \
|
||||
(a)->len = (b)->len; \
|
||||
(a)->allocated = (b)->allocated; \
|
||||
(a)->align_offset = (b)->align_offset; \
|
||||
} while (0)
|
||||
|
||||
DBusRealString tmp;
|
||||
|
||||
return TRUE;
|
||||
ASSIGN_DATA (&tmp, real_source);
|
||||
ASSIGN_DATA (real_source, real_dest);
|
||||
ASSIGN_DATA (real_dest, &tmp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!copy (real_source, start, len,
|
||||
real_dest,
|
||||
insert_at))
|
||||
return FALSE;
|
||||
|
||||
delete (real_source, start,
|
||||
len);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ void _dbus_string_init_const (DBusString *str,
|
|||
void _dbus_string_init_const_len (DBusString *str,
|
||||
const char *value,
|
||||
int len);
|
||||
dbus_bool_t _dbus_string_init_preallocated (DBusString *str,
|
||||
int allocate_size);
|
||||
void _dbus_string_free (DBusString *str);
|
||||
void _dbus_string_lock (DBusString *str);
|
||||
char* _dbus_string_get_data (DBusString *str);
|
||||
|
|
@ -105,6 +107,10 @@ dbus_bool_t _dbus_string_append_byte (DBusString *str,
|
|||
unsigned char byte);
|
||||
dbus_bool_t _dbus_string_append_unichar (DBusString *str,
|
||||
dbus_unichar_t ch);
|
||||
dbus_bool_t _dbus_string_append_4_aligned (DBusString *str,
|
||||
const unsigned char octets[4]);
|
||||
dbus_bool_t _dbus_string_append_8_aligned (DBusString *str,
|
||||
const unsigned char octets[8]);
|
||||
void _dbus_string_delete (DBusString *str,
|
||||
int start,
|
||||
int len);
|
||||
|
|
|
|||
|
|
@ -1792,19 +1792,18 @@ _dbus_getgid (void)
|
|||
|
||||
_DBUS_DEFINE_GLOBAL_LOCK (atomic);
|
||||
|
||||
|
||||
#ifdef DBUS_USE_ATOMIC_INT_486
|
||||
/* Taken from CVS version 1.7 of glibc's sysdeps/i386/i486/atomicity.h */
|
||||
/* Since the asm stuff here is gcc-specific we go ahead and use "inline" also */
|
||||
static inline dbus_atomic_t
|
||||
atomic_exchange_and_add (volatile dbus_atomic_t *atomic,
|
||||
volatile dbus_atomic_t val)
|
||||
static inline dbus_int32_t
|
||||
atomic_exchange_and_add (DBusAtomic *atomic,
|
||||
volatile dbus_int32_t val)
|
||||
{
|
||||
register dbus_atomic_t result;
|
||||
register dbus_int32_t result;
|
||||
|
||||
__asm__ __volatile__ ("lock; xaddl %0,%1"
|
||||
: "=r" (result), "=m" (*atomic)
|
||||
: "0" (val), "m" (*atomic));
|
||||
: "=r" (result), "=m" (atomic->value)
|
||||
: "0" (val), "m" (atomic->value));
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1813,12 +1812,12 @@ atomic_exchange_and_add (volatile dbus_atomic_t *atomic,
|
|||
* Atomically increments an integer
|
||||
*
|
||||
* @param atomic pointer to the integer to increment
|
||||
* @returns the value after incrementing
|
||||
* @returns the value before incrementing
|
||||
*
|
||||
* @todo implement arch-specific faster atomic ops
|
||||
*/
|
||||
dbus_atomic_t
|
||||
_dbus_atomic_inc (volatile dbus_atomic_t *atomic)
|
||||
dbus_int32_t
|
||||
_dbus_atomic_inc (DBusAtomic *atomic)
|
||||
{
|
||||
#ifdef DBUS_USE_ATOMIC_INT_486
|
||||
return atomic_exchange_and_add (atomic, 1);
|
||||
|
|
@ -1837,12 +1836,12 @@ _dbus_atomic_inc (volatile dbus_atomic_t *atomic)
|
|||
* Atomically decrement an integer
|
||||
*
|
||||
* @param atomic pointer to the integer to decrement
|
||||
* @returns the value after decrementing
|
||||
* @returns the value before decrementing
|
||||
*
|
||||
* @todo implement arch-specific faster atomic ops
|
||||
*/
|
||||
dbus_atomic_t
|
||||
_dbus_atomic_dec (volatile dbus_atomic_t *atomic)
|
||||
dbus_int32_t
|
||||
_dbus_atomic_dec (DBusAtomic *atomic)
|
||||
{
|
||||
#ifdef DBUS_USE_ATOMIC_INT_486
|
||||
return atomic_exchange_and_add (atomic, -1);
|
||||
|
|
|
|||
|
|
@ -169,10 +169,14 @@ unsigned long _dbus_getpid (void);
|
|||
dbus_uid_t _dbus_getuid (void);
|
||||
dbus_gid_t _dbus_getgid (void);
|
||||
|
||||
typedef dbus_int32_t dbus_atomic_t;
|
||||
typedef struct DBusAtomic DBusAtomic;
|
||||
struct DBusAtomic
|
||||
{
|
||||
volatile dbus_int32_t value;
|
||||
};
|
||||
|
||||
dbus_atomic_t _dbus_atomic_inc (volatile dbus_atomic_t *atomic);
|
||||
dbus_atomic_t _dbus_atomic_dec (volatile dbus_atomic_t *atomic);
|
||||
dbus_int32_t _dbus_atomic_inc (DBusAtomic *atomic);
|
||||
dbus_int32_t _dbus_atomic_dec (DBusAtomic *atomic);
|
||||
|
||||
#define _DBUS_POLLIN 0x0001 /* There is data to read */
|
||||
#define _DBUS_POLLPRI 0x0002 /* There is urgent data to read */
|
||||
|
|
|
|||
|
|
@ -64,6 +64,9 @@ _dbus_timeout_new (int interval,
|
|||
DBusTimeout *timeout;
|
||||
|
||||
timeout = dbus_new0 (DBusTimeout, 1);
|
||||
if (timeout == NULL)
|
||||
return NULL;
|
||||
|
||||
timeout->refcount = 1;
|
||||
timeout->interval = interval;
|
||||
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#define N_CLIENT_THREADS 1
|
||||
#define N_ITERATIONS 2000
|
||||
#define N_ITERATIONS 100
|
||||
#define PAYLOAD_SIZE 1000
|
||||
#define ECHO_MESSAGE "org.freedesktop.DBus.Test.EchoProfile"
|
||||
static const char *address;
|
||||
static unsigned char *payload;
|
||||
|
||||
static void
|
||||
send_echo_message (DBusConnection *connection)
|
||||
|
|
@ -40,7 +42,12 @@ send_echo_message (DBusConnection *connection)
|
|||
dbus_message_append_args (message,
|
||||
DBUS_TYPE_STRING, "Hello World!",
|
||||
DBUS_TYPE_INT32, 123456,
|
||||
#if 1
|
||||
DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
|
||||
payload, PAYLOAD_SIZE,
|
||||
#endif
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
dbus_connection_send (connection, message, NULL);
|
||||
dbus_message_unref (message);
|
||||
dbus_connection_flush (connection);
|
||||
|
|
@ -63,12 +70,12 @@ client_filter (DBusMessageHandler *handler,
|
|||
ECHO_MESSAGE))
|
||||
{
|
||||
*iterations += 1;
|
||||
send_echo_message (connection);
|
||||
if (*iterations > N_ITERATIONS)
|
||||
if (*iterations >= N_ITERATIONS)
|
||||
{
|
||||
g_print ("Completed %d iterations\n", N_ITERATIONS);
|
||||
exit (0);
|
||||
}
|
||||
send_echo_message (connection);
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
|
||||
|
|
@ -95,7 +102,7 @@ thread_func (void *data)
|
|||
exit (1);
|
||||
}
|
||||
|
||||
iterations = 0;
|
||||
iterations = 1;
|
||||
|
||||
handler = dbus_message_handler_new (client_filter,
|
||||
&iterations, NULL);
|
||||
|
|
@ -188,6 +195,7 @@ main (int argc, char *argv[])
|
|||
}
|
||||
|
||||
address = dbus_server_get_address (server);
|
||||
payload = g_malloc (PAYLOAD_SIZE);
|
||||
|
||||
dbus_server_set_new_connection_function (server,
|
||||
new_connection_callback,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue