diff options
| -rw-r--r-- | ChangeLog | 51 | ||||
| -rw-r--r-- | bus/connection.c | 15 | ||||
| -rw-r--r-- | dbus/dbus-connection.c | 287 | ||||
| -rw-r--r-- | dbus/dbus-list.c | 33 | ||||
| -rw-r--r-- | dbus/dbus-list.h | 2 | ||||
| -rw-r--r-- | dbus/dbus-marshal.c | 121 | ||||
| -rw-r--r-- | dbus/dbus-message-handler.c | 28 | ||||
| -rw-r--r-- | dbus/dbus-message-internal.h | 3 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 43 | ||||
| -rw-r--r-- | dbus/dbus-string.c | 293 | ||||
| -rw-r--r-- | dbus/dbus-string.h | 6 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps.c | 25 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps.h | 10 | ||||
| -rw-r--r-- | dbus/dbus-timeout.c | 3 | ||||
| -rw-r--r-- | glib/test-profile.c | 16 | 
15 files changed, 666 insertions, 270 deletions
| @@ -1,5 +1,56 @@  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;  	profile reveals lock contention, memcpy/realloc of buffers, and  	UTF-8 validation as hot spots. 20% of lock contention eliminated diff --git a/bus/connection.c b/bus/connection.c index 05532dba..70a0eb15 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -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; diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 6309ea44..9da5fb52 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -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)  { +  DBusList *link; +      _dbus_assert (_dbus_transport_get_is_authenticated (connection->transport)); -  _dbus_assert (message == _dbus_list_get_last (&connection->outgoing_messages)); -  _dbus_list_pop_last (&connection->outgoing_messages); +  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,18 +1226,8 @@ struct DBusPreallocatedSend    DBusList *counter_link;  }; - -/** - * Preallocates resources needed to send a message, allowing the message  - * to be sent without the possibility of memory allocation failure. - * Allows apps to create a future guarantee that they can send - * a message regardless of memory shortages. - * - * @param connection the connection we're preallocating for. - * @returns the preallocated resources, or #NULL - */ -DBusPreallocatedSend* -dbus_connection_preallocate_send (DBusConnection *connection) +static DBusPreallocatedSend* +_dbus_connection_preallocate_send_unlocked (DBusConnection *connection)  {    DBusPreallocatedSend *preallocated; @@ -1224,21 +1237,35 @@ dbus_connection_preallocate_send (DBusConnection *connection)    if (preallocated == NULL)      return NULL; -  CONNECTION_LOCK (connection); -   -  preallocated->queue_link = _dbus_list_alloc_link (NULL); -  if (preallocated->queue_link == NULL) -    goto failed_0; +  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; +    } -  preallocated->counter_link = _dbus_list_alloc_link (connection->outgoing_counter); -  if (preallocated->counter_link == NULL) -    goto failed_1; +  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; - -  CONNECTION_UNLOCK (connection);    return preallocated; @@ -1246,13 +1273,37 @@ dbus_connection_preallocate_send (DBusConnection *connection)    _dbus_list_free_link (preallocated->queue_link);   failed_0:    dbus_free (preallocated); - -  CONNECTION_UNLOCK (connection);    return NULL;  }  /** + * Preallocates resources needed to send a message, allowing the message  + * to be sent without the possibility of memory allocation failure. + * Allows apps to create a future guarantee that they can send + * a message regardless of memory shortages. + * + * @param connection the connection we're preallocating for. + * @returns the preallocated resources, or #NULL + */ +DBusPreallocatedSend* +dbus_connection_preallocate_send (DBusConnection *connection) +{ +  DBusPreallocatedSend *preallocated; + +  _dbus_return_val_if_fail (connection != NULL, NULL); + +  CONNECTION_LOCK (connection); +   +  preallocated = +    _dbus_connection_preallocate_send_unlocked (connection); + +  CONNECTION_UNLOCK (connection); + +  return preallocated; +} + +/**   * Frees preallocated message-sending resources from   * dbus_connection_preallocate_send(). Should only   * be called if the preallocated resources are not used @@ -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); + +  CONNECTION_LOCK (connection); +  status = _dbus_connection_get_dispatch_status_unlocked (connection);    if (status != DBUS_DISPATCH_DATA_REMAINS)      { -      _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 status;      } - -  CONNECTION_LOCK (connection);    /* 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); diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c index 235ed275..5d2bcd42 100644 --- a/dbus/dbus-list.c +++ b/dbus/dbus-list.c @@ -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;  }  /** diff --git a/dbus/dbus-list.h b/dbus/dbus-list.h index f3b37ef8..7aa6c96c 100644 --- a/dbus/dbus-list.h +++ b/dbus/dbus-list.h @@ -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); diff --git a/dbus/dbus-marshal.c b/dbus/dbus-marshal.c index 82de8ffc..ad15ae21 100644 --- a/dbus/dbus-marshal.c +++ b/dbus/dbus-marshal.c @@ -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;            } diff --git a/dbus/dbus-message-handler.c b/dbus/dbus-message-handler.c index a978ba05..f38e5100 100644 --- a/dbus/dbus-message-handler.c +++ b/dbus/dbus-message-handler.c @@ -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; -   -  _DBUS_UNLOCK (message_handler); +  last_unref = (_dbus_atomic_dec (&handler->refcount) == 1); -  if (refcount == 0) +  if (last_unref)      {        DBusList *link; diff --git a/dbus/dbus-message-internal.h b/dbus/dbus-message-internal.h index eb4123c3..53711f3d 100644 --- a/dbus/dbus-message-internal.h +++ b/dbus/dbus-message-internal.h @@ -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); diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 29209106..7c89d734 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -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); diff --git a/dbus/dbus-string.c b/dbus/dbus-string.c index 65d2fb1b..c6f929a8 100644 --- a/dbus/dbus-string.c +++ b/dbus/dbus-string.c @@ -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 @@ -345,56 +361,65 @@ _dbus_string_lock (DBusString *str)  #endif /* DBUS_BUILD_TESTS */  static dbus_bool_t -set_length (DBusRealString *real, -            int             new_length) +reallocate_for_length (DBusRealString *real, +                       int             new_length)  { -  /* Note, we are setting the length without 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)) -    { -      int new_allocated; -      char *new_str; +  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; +  /* 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 -       */ +  /* 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 -                          */ +  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; +  /* But be sure we always alloc at least space for the new length */ +  new_allocated = MAX (new_allocated, new_length + ALLOCATION_PADDING); -      real->str = new_str + real->align_offset; -      real->allocated = new_allocated; -      fixup_alignment (real); -    } +  _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->len = new_length; -  real->str[real->len] = '\0'; +  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 not including nul termination */ + +  /* exceeding max length is the same as failure to allocate memory */ +  if (new_length > real->max_length) +    return FALSE; +  else if (new_length > (real->allocated - ALLOCATION_PADDING) && +           !reallocate_for_length (real, new_length)) +    return FALSE; +  else +    { +      real->len = new_length; +      real->str[real->len] = '\0'; +      return TRUE; +    } +} + +static dbus_bool_t  open_gap (int             len,            DBusRealString *dest,            int             insert_at) @@ -795,17 +820,10 @@ _dbus_string_set_length (DBusString *str,    return set_length (real, length);  } -/** - * Align the length of a string to a specific alignment (typically 4 or 8) - * by appending nul bytes to the string. - * - * @param str a string - * @param alignment the alignment - * @returns #FALSE if no memory - */ -dbus_bool_t -_dbus_string_align_length (DBusString *str, -                           int         alignment) +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; @@ -814,8 +832,9 @@ _dbus_string_align_length (DBusString *str,    _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) +  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); @@ -826,12 +845,38 @@ _dbus_string_align_length (DBusString *str,    if (!set_length (real, new_len))      return FALSE; -  memset (real->str + (new_len - delta), -          '\0', delta); - +  /* 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. + * + * @param str a string + * @param alignment the alignment + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_string_align_length (DBusString *str, +                           int         alignment) +{ +  return align_length_then_lengthen (str, alignment, 0); +} +  static dbus_bool_t  append (DBusRealString *real,          const char     *buffer, @@ -874,6 +919,74 @@ _dbus_string_append (DBusString *str,  }  /** + * 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.   *   * @param str the 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; +    }  }  /** diff --git a/dbus/dbus-string.h b/dbus/dbus-string.h index b9b298ae..8fa13805 100644 --- a/dbus/dbus-string.h +++ b/dbus/dbus-string.h @@ -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); diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index c813a83c..e2975c30 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -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); diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 2ae455b1..7a4696f3 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -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 */ diff --git a/dbus/dbus-timeout.c b/dbus/dbus-timeout.c index 625fbb74..289d6347 100644 --- a/dbus/dbus-timeout.c +++ b/dbus/dbus-timeout.c @@ -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; diff --git a/glib/test-profile.c b/glib/test-profile.c index 6173f3a5..d53f7626 100644 --- a/glib/test-profile.c +++ b/glib/test-profile.c @@ -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, | 
