diff options
| -rw-r--r-- | ChangeLog | 30 | ||||
| -rw-r--r-- | bus/connection.c | 6 | ||||
| -rw-r--r-- | configure.in | 23 | ||||
| -rw-r--r-- | dbus/dbus-auth.c | 3 | ||||
| -rw-r--r-- | dbus/dbus-connection.c | 241 | ||||
| -rw-r--r-- | dbus/dbus-internals.c | 4 | ||||
| -rw-r--r-- | dbus/dbus-message.c | 6 | ||||
| -rw-r--r-- | dbus/dbus-spawn.c | 1 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps.c | 30 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps.h | 6 | ||||
| -rw-r--r-- | dbus/dbus-threads.c | 2 | ||||
| -rw-r--r-- | glib/Makefile.am | 33 | ||||
| -rw-r--r-- | glib/test-profile.c | 215 | 
13 files changed, 468 insertions, 132 deletions
| @@ -1,3 +1,33 @@ +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 +	with dbus_atomic_inc/dec implementation on x86.  Much remaining +	contention is global mempool locks for GList and DBusList. +	 +	* dbus/dbus-sysdeps.c (_dbus_atomic_inc, _dbus_atomic_dec): add +	x86 implementation + +	* dbus/dbus-connection.c (struct DBusConnection): use +	dbus_atomic_t for the reference count	 + +	* dbus/dbus-message.c (struct DBusMessage): declare  +	dbus_atomic_t values as volatile + +	* configure.in: code to detect ability to use atomic integer +	operations in assembly, from GLib patch + +	* dbus/dbus-internals.c (_dbus_verbose_real): call getpid every +	time, tired of it being wrong in threads and forked processes + +	* glib/test-profile.c: a little program to bounce messages back  +	and forth between threads and eat CPU + +	* dbus/dbus-connection.c: add debug spew macros for debugging +	thread locks; include config.h at top; fix deadlock in  +	dbus_connection_flush() +  2003-05-08  Havoc Pennington  <hp@pobox.com>  	* dbus/dbus-spawn.c: s/_exit/exit/ because it was keeping gcov diff --git a/bus/connection.c b/bus/connection.c index 6bb53148..05532dba 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -292,9 +292,9 @@ connection_watch_callback (DBusWatch     *watch,                             void          *data)  {   /* FIXME this can be done in dbus-mainloop.c -   * if the code in activation.c for the babysitter -   * watch handler is fixed. -   */ +  * if the code in activation.c for the babysitter +  * watch handler is fixed. +  */  #if 0    _dbus_verbose ("Calling handle_watch\n"); diff --git a/configure.in b/configure.in index 18cb519e..f95da565 100644 --- a/configure.in +++ b/configure.in @@ -205,6 +205,28 @@ AC_SUBST(DBUS_HAVE_INT64)  ## byte order  AC_C_BIGENDIAN +#### Atomic integers (checks by Sebastian Wilhelmi for GLib) +AC_MSG_CHECKING([whether to use inline assembler routines for atomic integers]) +have_atomic_inc=no +if test x"$GCC" = xyes; then +  case $host_cpu in +    i386) +      AC_MSG_RESULT([no]) +      ;; +    i?86) +      AC_MSG_RESULT([i486]) +      AC_DEFINE_UNQUOTED(DBUS_USE_ATOMIC_INT_486, 1, [Use atomic integer implementation for 486]) +      have_atomic_inc=yes +      ;; +    *) +      AC_MSG_RESULT([no]) +      ;; +  esac +fi +if test x$have_atomic_inc = xyes ; then +  AC_DEFINE_UNQUOTED(DBUS_HAVE_ATOMIC_INT, 1, [Some atomic integer implementation present]) +fi +  #### Various functions  AC_CHECK_LIB(socket,socket)  AC_CHECK_LIB(nsl,gethostbyname) @@ -598,6 +620,7 @@ else     TEST_SOCKET_DIR=$DEFAULT_SOCKET_DIR  fi  AC_SUBST(TEST_SOCKET_DIR) +AC_DEFINE_UNQUOTED(DBUS_TEST_SOCKET_DIR, "$TEST_SOCKET_DIR", [Where to put test sockets])  if ! test -z "$with_session_socket_dir" ; then     DBUS_SESSION_SOCKET_DIR="$with_session_socket_dir" diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index 4da39667..b496dba0 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -39,9 +39,6 @@   * is first established, and also manage any encryption used over a   * connection.   * - * The file doc/dbus-sasl-profile.txt documents the network protocol - * used for authentication. - *   * @todo some SASL profiles require sending the empty string as a   * challenge/response, but we don't currently allow that in our   * protocol. diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 688841d7..6309ea44 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -21,6 +21,7 @@   *   */ +#include <config.h>  #include "dbus-connection.h"  #include "dbus-list.h"  #include "dbus-timeout.h" @@ -35,6 +36,20 @@  #include "dbus-protocol.h"  #include "dbus-dataslot.h" +#if 1 +#define CONNECTION_LOCK(connection)   do {                      \ +    _dbus_verbose ("  LOCK: %s\n", _DBUS_FUNCTION_NAME);        \ +    dbus_mutex_lock ((connection)->mutex);                      \ +  } while (0) +#define CONNECTION_UNLOCK(connection) do {                      \ +    _dbus_verbose ("  UNLOCK: %s\n", _DBUS_FUNCTION_NAME);      \ +    dbus_mutex_unlock ((connection)->mutex);                    \ +  } while (0) +#else +#define CONNECTION_LOCK(connection)    dbus_mutex_lock ((connection)->mutex) +#define CONNECTION_UNLOCK(connection)  dbus_mutex_unlock ((connection)->mutex) +#endif +  /**   * @defgroup DBusConnection DBusConnection   * @ingroup  DBus @@ -117,7 +132,7 @@ static dbus_bool_t _dbus_modify_sigpipe = TRUE;   */  struct DBusConnection  { -  int refcount; /**< Reference count. */ +  dbus_atomic_t refcount; /**< Reference count. */    DBusMutex *mutex; /**< Lock on the entire DBusConnection */ @@ -193,7 +208,7 @@ static void               _dbus_connection_update_dispatch_status_locked (DBusCo  void  _dbus_connection_lock (DBusConnection *connection)  { -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);  }  /** @@ -204,7 +219,7 @@ _dbus_connection_lock (DBusConnection *connection)  void  _dbus_connection_unlock (DBusConnection *connection)  { -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);  }  /** @@ -478,9 +493,9 @@ static void  _dbus_connection_remove_timeout_locked (DBusConnection *connection,  					DBusTimeout    *timeout)  { -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_connection_remove_timeout (connection, timeout); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);  }  /** @@ -820,7 +835,7 @@ _dbus_connection_handler_destroyed_locked (DBusConnection     *connection,    DBusHashIter iter;    DBusList *link; -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_hash_iter_init (connection->handler_table, &iter);    while (_dbus_hash_iter_next (&iter)) @@ -843,7 +858,7 @@ _dbus_connection_handler_destroyed_locked (DBusConnection     *connection,        link = next;      } -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);  }  /** @@ -870,7 +885,7 @@ _dbus_connection_handle_watch (DBusWatch                   *watch,    connection = data; -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_connection_acquire_io_path (connection, -1);    retval = _dbus_transport_handle_watch (connection->transport,                                           watch, condition); @@ -878,7 +893,7 @@ _dbus_connection_handle_watch (DBusWatch                   *watch,    status = _dbus_connection_get_dispatch_status_unlocked (connection); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    _dbus_connection_update_dispatch_status_locked (connection, status); @@ -948,12 +963,20 @@ void  dbus_connection_ref (DBusConnection *connection)  {    _dbus_return_if_fail (connection != NULL); + +  /* The connection lock is better than the global +   * lock in the atomic increment fallback +   */ -  dbus_mutex_lock (connection->mutex); +#ifdef DBUS_HAVE_ATOMIC_INT +  _dbus_atomic_inc (&connection->refcount); +#else +  CONNECTION_LOCK (connection);    _dbus_assert (connection->refcount > 0);    connection->refcount += 1; -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection); +#endif  }  static void @@ -1075,8 +1098,15 @@ dbus_connection_unref (DBusConnection *connection)    dbus_bool_t last_unref;    _dbus_return_if_fail (connection != NULL); + +  /* The connection lock is better than the global +   * lock in the atomic increment fallback +   */ -  dbus_mutex_lock (connection->mutex); +#ifdef DBUS_HAVE_ATOMIC_INT +  last_unref = (_dbus_atomic_dec (&connection->refcount) == 0); +#else +  CONNECTION_LOCK (connection);    _dbus_assert (connection->refcount > 0); @@ -1087,8 +1117,9 @@ dbus_connection_unref (DBusConnection *connection)    printf ("unref() connection %p count = %d\n", connection, connection->refcount);  #endif -  dbus_mutex_unlock (connection->mutex); - +  CONNECTION_UNLOCK (connection); +#endif +      if (last_unref)      _dbus_connection_last_unref (connection);  } @@ -1108,9 +1139,15 @@ dbus_connection_disconnect (DBusConnection *connection)  {    _dbus_return_if_fail (connection != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_transport_disconnect (connection->transport); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection); +} + +static dbus_bool_t +_dbus_connection_get_is_connected_unlocked (DBusConnection *connection) +{ +  return _dbus_transport_get_is_connected (connection->transport);  }  /** @@ -1130,9 +1167,9 @@ dbus_connection_get_is_connected (DBusConnection *connection)    _dbus_return_val_if_fail (connection != NULL, FALSE); -  dbus_mutex_lock (connection->mutex); -  res = _dbus_transport_get_is_connected (connection->transport); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_LOCK (connection); +  res = _dbus_connection_get_is_connected_unlocked (connection); +  CONNECTION_UNLOCK (connection);    return res;  } @@ -1152,9 +1189,9 @@ dbus_connection_get_is_authenticated (DBusConnection *connection)    _dbus_return_val_if_fail (connection != NULL, FALSE); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    res = _dbus_transport_get_is_authenticated (connection->transport); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return res;  } @@ -1187,7 +1224,7 @@ dbus_connection_preallocate_send (DBusConnection *connection)    if (preallocated == NULL)      return NULL; -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    preallocated->queue_link = _dbus_list_alloc_link (NULL);    if (preallocated->queue_link == NULL) @@ -1201,7 +1238,7 @@ dbus_connection_preallocate_send (DBusConnection *connection)    preallocated->connection = connection; -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return preallocated; @@ -1210,7 +1247,7 @@ dbus_connection_preallocate_send (DBusConnection *connection)   failed_0:    dbus_free (preallocated); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return NULL;  } @@ -1264,7 +1301,7 @@ dbus_connection_send_preallocated (DBusConnection       *connection,    _dbus_return_if_fail (preallocated->connection == connection);    _dbus_return_if_fail (dbus_message_get_name (message) != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    preallocated->queue_link->data = message;    _dbus_list_prepend_link (&connection->outgoing_messages, @@ -1307,7 +1344,7 @@ dbus_connection_send_preallocated (DBusConnection       *connection,    _dbus_connection_wakeup_mainloop (connection); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);  }  /** @@ -1359,7 +1396,7 @@ reply_handler_timeout (void *data)    connection = reply_handler_data->connection; -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    if (reply_handler_data->timeout_link)      {        _dbus_connection_queue_synthesized_message_link (connection, @@ -1373,7 +1410,7 @@ reply_handler_timeout (void *data)    status = _dbus_connection_get_dispatch_status_unlocked (connection); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    _dbus_connection_update_dispatch_status_locked (connection, status); @@ -1474,14 +1511,14 @@ dbus_connection_send_with_reply (DBusConnection     *connection,        return FALSE;      } -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    /* Add timeout */    if (!_dbus_connection_add_timeout (connection, timeout))      {        reply_handler_data_free (data);        _dbus_timeout_unref (timeout); -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        return FALSE;      } @@ -1494,7 +1531,7 @@ dbus_connection_send_with_reply (DBusConnection     *connection,    if (!_dbus_message_handler_add_connection (reply_handler, connection))      { -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        reply_handler_data_free (data);        return FALSE;      } @@ -1516,7 +1553,7 @@ dbus_connection_send_with_reply (DBusConnection     *connection,  					"No reply within specified time");    if (!reply)      { -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        reply_handler_data_free (data);        return FALSE;      } @@ -1524,7 +1561,7 @@ dbus_connection_send_with_reply (DBusConnection     *connection,    reply_link = _dbus_list_alloc_link (reply);    if (!reply)      { -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        dbus_message_unref (reply);        reply_handler_data_free (data);        return FALSE; @@ -1535,12 +1572,12 @@ dbus_connection_send_with_reply (DBusConnection     *connection,    /* Insert the serial in the pending replies hash. */    if (!_dbus_hash_table_insert_int (connection->pending_replies, serial, data))      { -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        reply_handler_data_free (data);              return FALSE;      } -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    if (!dbus_connection_send (connection, message, NULL))      { @@ -1637,7 +1674,7 @@ dbus_connection_send_with_reply_and_block (DBusConnection     *connection,    /* Flush message queue */    dbus_connection_flush (connection); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_get_current_time (&start_tv_sec, &start_tv_usec);    end_tv_sec = start_tv_sec + timeout_milliseconds / 1000; @@ -1675,7 +1712,7 @@ dbus_connection_send_with_reply_and_block (DBusConnection     *connection,          {                      status = _dbus_connection_get_dispatch_status_unlocked (connection); -          dbus_mutex_unlock (connection->mutex); +          CONNECTION_UNLOCK (connection);            _dbus_verbose ("dbus_connection_send_with_reply_and_block(): got reply %s\n",                           dbus_message_get_name (reply)); @@ -1735,7 +1772,7 @@ dbus_connection_send_with_reply_and_block (DBusConnection     *connection,    else      dbus_set_error (error, DBUS_ERROR_DISCONNECTED, "Disconnected prior to receiving a reply"); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    _dbus_connection_update_dispatch_status_locked (connection, status); @@ -1759,9 +1796,9 @@ dbus_connection_flush (DBusConnection *connection)    _dbus_return_if_fail (connection != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    while (connection->n_outgoing > 0 && -         dbus_connection_get_is_connected (connection)) +         _dbus_connection_get_is_connected_unlocked (connection))      _dbus_connection_do_iteration (connection,                                     DBUS_ITERATION_DO_READING |                                     DBUS_ITERATION_DO_WRITING | @@ -1770,7 +1807,7 @@ dbus_connection_flush (DBusConnection *connection)    status = _dbus_connection_get_dispatch_status_unlocked (connection); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    _dbus_connection_update_dispatch_status_locked (connection, status);  } @@ -1816,7 +1853,7 @@ dbus_connection_borrow_message  (DBusConnection *connection)    if (status != DBUS_DISPATCH_DATA_REMAINS)      return NULL; -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    if (connection->message_borrowed != NULL)      _dbus_connection_wait_for_borrowed (connection); @@ -1826,7 +1863,7 @@ dbus_connection_borrow_message  (DBusConnection *connection)    if (message)       connection->message_borrowed = message; -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return message;  } @@ -1844,14 +1881,14 @@ dbus_connection_return_message (DBusConnection *connection,    _dbus_return_if_fail (connection != NULL);    _dbus_return_if_fail (message != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_assert (message == connection->message_borrowed);    connection->message_borrowed = NULL;    dbus_condvar_wake_all (connection->message_returned_cond); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);  }  /** @@ -1872,7 +1909,7 @@ dbus_connection_steal_borrowed_message (DBusConnection *connection,    _dbus_return_if_fail (connection != NULL);    _dbus_return_if_fail (message != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_assert (message == connection->message_borrowed); @@ -1887,7 +1924,7 @@ dbus_connection_steal_borrowed_message (DBusConnection *connection,    connection->message_borrowed = NULL;    dbus_condvar_wake_all (connection->message_returned_cond); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);  }  /* See dbus_connection_pop_message, but requires the caller to own @@ -1968,13 +2005,13 @@ dbus_connection_pop_message (DBusConnection *connection)    if (status != DBUS_DISPATCH_DATA_REMAINS)      return NULL; -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    message = _dbus_connection_pop_message_unlocked (connection);    _dbus_verbose ("Returning popped message %p\n", message);     -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return message;  } @@ -2052,7 +2089,7 @@ _dbus_connection_update_dispatch_status_locked (DBusConnection    *connection,    DBusDispatchStatusFunction function;    void *data; -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_connection_ref_unlocked (connection);    changed = new_status != connection->last_dispatch_status; @@ -2062,7 +2099,7 @@ _dbus_connection_update_dispatch_status_locked (DBusConnection    *connection,    function = connection->dispatch_status_function;    data = connection->dispatch_status_data; -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    if (changed && function)      { @@ -2093,11 +2130,11 @@ dbus_connection_get_dispatch_status (DBusConnection *connection)    _dbus_return_val_if_fail (connection != NULL, DBUS_DISPATCH_COMPLETE); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    status = _dbus_connection_get_dispatch_status_unlocked (connection); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return status;  } @@ -2137,7 +2174,7 @@ dbus_connection_dispatch (DBusConnection *connection)        return status;      } -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    /* We need to ref the connection since the callback could potentially     * drop the last ref to it @@ -2158,7 +2195,7 @@ dbus_connection_dispatch (DBusConnection *connection)        /* another thread dispatched our stuff */        _dbus_connection_release_dispatch (connection); -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        status = dbus_connection_get_dispatch_status (connection); @@ -2180,7 +2217,7 @@ dbus_connection_dispatch (DBusConnection *connection)    if (!_dbus_list_copy (&connection->filter_list, &filter_list_copy))      {        _dbus_connection_release_dispatch (connection); -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        _dbus_connection_failed_pop (connection, message_link);        _dbus_connection_update_dispatch_status_locked (connection, DBUS_DISPATCH_NEED_MEMORY); @@ -2197,7 +2234,7 @@ dbus_connection_dispatch (DBusConnection *connection)    /* We're still protected from dispatch() reentrancy here     * since we acquired the dispatcher     */ -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    link = _dbus_list_get_first_link (&filter_list_copy);    while (link != NULL) @@ -2220,7 +2257,7 @@ dbus_connection_dispatch (DBusConnection *connection)  		      NULL);    _dbus_list_clear (&filter_list_copy); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    /* Did a reply we were waiting on get filtered? */    if (reply_handler_data && result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE) @@ -2244,14 +2281,14 @@ dbus_connection_dispatch (DBusConnection *connection)    if (reply_handler_data)      { -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        _dbus_verbose ("  running reply handler on message %p\n", message);        result = _dbus_message_handler_handle_message (reply_handler_data->handler,  						     connection, message);        reply_handler_data_free (reply_handler_data); -      dbus_mutex_lock (connection->mutex); +      CONNECTION_LOCK (connection);        goto out;      } @@ -2265,14 +2302,14 @@ dbus_connection_dispatch (DBusConnection *connection)  	  /* We're still protected from dispatch() reentrancy here  	   * since we acquired the dispatcher             */ -	  dbus_mutex_unlock (connection->mutex); +	  CONNECTION_UNLOCK (connection);            _dbus_verbose ("  running app handler on message %p (%s)\n",                           message, dbus_message_get_name (message));            result = _dbus_message_handler_handle_message (handler, connection,                                                           message); -	  dbus_mutex_lock (connection->mutex); +	  CONNECTION_LOCK (connection);            if (result == DBUS_HANDLER_RESULT_REMOVE_MESSAGE)              goto out;          } @@ -2283,7 +2320,7 @@ dbus_connection_dispatch (DBusConnection *connection)   out:    _dbus_connection_release_dispatch (connection); -  dbus_mutex_unlock (connection->mutex); +  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 @@ -2368,7 +2405,7 @@ dbus_connection_set_watch_functions (DBusConnection              *connection,    _dbus_return_val_if_fail (connection != NULL, FALSE); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    /* ref connection for slightly better reentrancy */    _dbus_connection_ref_unlocked (connection); @@ -2380,7 +2417,7 @@ dbus_connection_set_watch_functions (DBusConnection              *connection,                                             toggled_function,                                             data, free_data_function); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    /* drop our paranoid refcount */    dbus_connection_unref (connection); @@ -2432,7 +2469,7 @@ dbus_connection_set_timeout_functions   (DBusConnection            *connection,    _dbus_return_val_if_fail (connection != NULL, FALSE); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    /* ref connection for slightly better reentrancy */    _dbus_connection_ref_unlocked (connection); @@ -2441,7 +2478,7 @@ dbus_connection_set_timeout_functions   (DBusConnection            *connection,                                               toggled_function,                                               data, free_data_function); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    /* drop our paranoid refcount */    dbus_connection_unref (connection); @@ -2473,7 +2510,7 @@ dbus_connection_set_wakeup_main_function (DBusConnection            *connection,    _dbus_return_if_fail (connection != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    old_data = connection->wakeup_main_data;    old_free_data = connection->free_wakeup_main_data; @@ -2481,7 +2518,7 @@ dbus_connection_set_wakeup_main_function (DBusConnection            *connection,    connection->wakeup_main_data = data;    connection->free_wakeup_main_data = free_data_function; -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    /* Callback outside the lock */    if (old_free_data) @@ -2515,7 +2552,7 @@ dbus_connection_set_dispatch_status_function (DBusConnection             *connec    _dbus_return_if_fail (connection != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    old_data = connection->dispatch_status_data;    old_free_data = connection->free_dispatch_status_data; @@ -2523,7 +2560,7 @@ dbus_connection_set_dispatch_status_function (DBusConnection             *connec    connection->dispatch_status_data = data;    connection->free_dispatch_status_data = free_data_function; -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    /* Callback outside the lock */    if (old_free_data) @@ -2550,14 +2587,14 @@ dbus_connection_get_unix_user (DBusConnection *connection,    _dbus_return_val_if_fail (connection != NULL, FALSE);    _dbus_return_val_if_fail (uid != NULL, FALSE); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    if (!_dbus_transport_get_is_authenticated (connection->transport))      result = FALSE;    else      result = _dbus_transport_get_unix_user (connection->transport,                                              uid); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return result;  } @@ -2589,11 +2626,11 @@ dbus_connection_set_unix_user_function (DBusConnection             *connection,    _dbus_return_if_fail (connection != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_transport_set_unix_user_function (connection->transport,                                            function, data, free_data_function,                                            &old_data, &old_free_function); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    if (old_free_function != NULL)      (* old_free_function) (old_data);     @@ -2624,11 +2661,11 @@ dbus_connection_add_filter (DBusConnection      *connection,  {    _dbus_return_val_if_fail (connection != NULL, FALSE);    _dbus_return_val_if_fail (handler != NULL, FALSE); -   -  dbus_mutex_lock (connection->mutex); + +  CONNECTION_LOCK (connection);    if (!_dbus_message_handler_add_connection (handler, connection))      { -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        return FALSE;      } @@ -2636,11 +2673,11 @@ dbus_connection_add_filter (DBusConnection      *connection,                            handler))      {        _dbus_message_handler_remove_connection (handler, connection); -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        return FALSE;      } -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return TRUE;  } @@ -2662,17 +2699,17 @@ dbus_connection_remove_filter (DBusConnection      *connection,    _dbus_return_if_fail (connection != NULL);    _dbus_return_if_fail (handler != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    if (!_dbus_list_remove_last (&connection->filter_list, handler))      {        _dbus_warn ("Tried to remove a DBusConnection filter that had not been added\n"); -      dbus_mutex_unlock (connection->mutex); +      CONNECTION_UNLOCK (connection);        return;      }    _dbus_message_handler_remove_connection (handler, connection); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);  }  /** @@ -2714,7 +2751,7 @@ dbus_connection_register_handler (DBusConnection     *connection,    _dbus_return_val_if_fail (n_messages >= 0, FALSE);    _dbus_return_val_if_fail (n_messages == 0 || messages_to_handle != NULL, FALSE); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    i = 0;    while (i < n_messages)      { @@ -2753,7 +2790,7 @@ dbus_connection_register_handler (DBusConnection     *connection,        ++i;      } -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return TRUE;   failed: @@ -2765,7 +2802,7 @@ dbus_connection_register_handler (DBusConnection     *connection,                                        messages_to_handle,                                        i); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return FALSE;  } @@ -2792,7 +2829,7 @@ dbus_connection_unregister_handler (DBusConnection     *connection,    _dbus_return_if_fail (n_messages >= 0);    _dbus_return_if_fail (n_messages == 0 || messages_to_handle != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    i = 0;    while (i < n_messages)      { @@ -2819,7 +2856,7 @@ dbus_connection_unregister_handler (DBusConnection     *connection,        ++i;      } -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);  }  static DBusDataSlotAllocator slot_allocator; @@ -2885,14 +2922,14 @@ dbus_connection_set_data (DBusConnection   *connection,    _dbus_return_val_if_fail (connection != NULL, FALSE);    _dbus_return_val_if_fail (slot >= 0, FALSE); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    retval = _dbus_data_slot_list_set (&slot_allocator,                                       &connection->slot_list,                                       slot, data, free_data_func,                                       &old_free_func, &old_data); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    if (retval)      { @@ -2920,13 +2957,13 @@ dbus_connection_get_data (DBusConnection   *connection,    _dbus_return_val_if_fail (connection != NULL, NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    res = _dbus_data_slot_list_get (&slot_allocator,                                    &connection->slot_list,                                    slot); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return res;  } @@ -2957,10 +2994,10 @@ dbus_connection_set_max_message_size (DBusConnection *connection,  {    _dbus_return_if_fail (connection != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_transport_set_max_message_size (connection->transport,                                          size); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);  }  /** @@ -2976,9 +3013,9 @@ dbus_connection_get_max_message_size (DBusConnection *connection)    _dbus_return_val_if_fail (connection != NULL, 0); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    res = _dbus_transport_get_max_message_size (connection->transport); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return res;  } @@ -3013,10 +3050,10 @@ dbus_connection_set_max_received_size (DBusConnection *connection,  {    _dbus_return_if_fail (connection != NULL); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    _dbus_transport_set_max_received_size (connection->transport,                                           size); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);  }  /** @@ -3032,9 +3069,9 @@ dbus_connection_get_max_received_size (DBusConnection *connection)    _dbus_return_val_if_fail (connection != NULL, 0); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    res = _dbus_transport_get_max_received_size (connection->transport); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return res;  } @@ -3055,9 +3092,9 @@ dbus_connection_get_outgoing_size (DBusConnection *connection)    _dbus_return_val_if_fail (connection != NULL, 0); -  dbus_mutex_lock (connection->mutex); +  CONNECTION_LOCK (connection);    res = _dbus_counter_get_value (connection->outgoing_counter); -  dbus_mutex_unlock (connection->mutex); +  CONNECTION_UNLOCK (connection);    return res;  } diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c index 25bd52ba..6a091e62 100644 --- a/dbus/dbus-internals.c +++ b/dbus/dbus-internals.c @@ -190,7 +190,6 @@ _dbus_verbose_real (const char *format,  {    va_list args;    static dbus_bool_t verbose = TRUE; -  static unsigned long pid;    /* things are written a bit oddly here so that     * in the non-verbose case we just have the one @@ -202,13 +201,12 @@ _dbus_verbose_real (const char *format,    if (!verbose_initted)      {        verbose = _dbus_getenv ("DBUS_VERBOSE") != NULL; -      pid = _dbus_getpid ();        verbose_initted = TRUE;        if (!verbose)          return;      } -  fprintf (stderr, "%lu: ", pid); +  fprintf (stderr, "%lu: ", _dbus_getpid ());    va_start (args, format);    vfprintf (stderr, format, args); diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 668736dc..29209106 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -81,7 +81,7 @@ typedef struct   */  struct DBusMessage  { -  dbus_atomic_t refcount; /**< Reference count */ +  volatile dbus_atomic_t refcount; /**< Reference count */    DBusString header; /**< Header network data, stored                        * separately from body so we can @@ -1134,7 +1134,7 @@ dbus_message_copy (const DBusMessage *message)  void  dbus_message_ref (DBusMessage *message)  { -  dbus_atomic_t refcount; +  volatile dbus_atomic_t refcount;    _dbus_return_if_fail (message != NULL); @@ -1163,7 +1163,7 @@ free_size_counter (void *element,  void  dbus_message_unref (DBusMessage *message)  { -  dbus_atomic_t refcount; +  volatile dbus_atomic_t refcount;    _dbus_return_if_fail (message != NULL); diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c index 179b9f9a..d4015561 100644 --- a/dbus/dbus-spawn.c +++ b/dbus/dbus-spawn.c @@ -31,6 +31,7 @@  #include <signal.h>  #include <sys/wait.h>  #include <errno.h> +#include <stdlib.h>  /**   * @addtogroup DBusInternalsUtils diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index 91f6e95a..c813a83c 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -1790,9 +1790,25 @@ _dbus_getgid (void)    return getgid ();  } -  _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) +{ +  register dbus_atomic_t result; + +  __asm__ __volatile__ ("lock; xaddl %0,%1" +                        : "=r" (result), "=m" (*atomic)  +			: "0" (val), "m" (*atomic)); +  return result; +} +#endif +  /**   * Atomically increments an integer   * @@ -1802,8 +1818,11 @@ _DBUS_DEFINE_GLOBAL_LOCK (atomic);   * @todo implement arch-specific faster atomic ops   */  dbus_atomic_t -_dbus_atomic_inc (dbus_atomic_t *atomic) +_dbus_atomic_inc (volatile dbus_atomic_t *atomic)  { +#ifdef DBUS_USE_ATOMIC_INT_486 +  return atomic_exchange_and_add (atomic, 1); +#else    dbus_atomic_t res;    _DBUS_LOCK (atomic); @@ -1811,6 +1830,7 @@ _dbus_atomic_inc (dbus_atomic_t *atomic)    res = *atomic;    _DBUS_UNLOCK (atomic);    return res; +#endif  }  /** @@ -1822,8 +1842,11 @@ _dbus_atomic_inc (dbus_atomic_t *atomic)   * @todo implement arch-specific faster atomic ops   */  dbus_atomic_t -_dbus_atomic_dec (dbus_atomic_t *atomic) +_dbus_atomic_dec (volatile dbus_atomic_t *atomic)  { +#ifdef DBUS_USE_ATOMIC_INT_486 +  return atomic_exchange_and_add (atomic, -1); +#else    dbus_atomic_t res;    _DBUS_LOCK (atomic); @@ -1831,6 +1854,7 @@ _dbus_atomic_dec (dbus_atomic_t *atomic)    res = *atomic;    _DBUS_UNLOCK (atomic);    return res; +#endif  }  /** diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 593496c0..2ae455b1 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -169,10 +169,10 @@ unsigned long _dbus_getpid (void);  dbus_uid_t    _dbus_getuid (void);  dbus_gid_t    _dbus_getgid (void); -typedef int dbus_atomic_t; +typedef dbus_int32_t dbus_atomic_t; -dbus_atomic_t _dbus_atomic_inc (dbus_atomic_t *atomic); -dbus_atomic_t _dbus_atomic_dec (dbus_atomic_t *atomic); +dbus_atomic_t _dbus_atomic_inc (volatile dbus_atomic_t *atomic); +dbus_atomic_t _dbus_atomic_dec (volatile dbus_atomic_t *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-threads.c b/dbus/dbus-threads.c index 07c98973..76b2f194 100644 --- a/dbus/dbus-threads.c +++ b/dbus/dbus-threads.c @@ -458,7 +458,7 @@ dbus_fake_condvar_free (DBusCondVar *cond)  static void  dbus_fake_condvar_wait (DBusCondVar *cond, -		    DBusMutex   *mutex) +                        DBusMutex   *mutex)  {  } diff --git a/glib/Makefile.am b/glib/Makefile.am index d9edf6f5..ebdb932f 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -13,21 +13,11 @@ libdbus_glib_1_la_SOURCES = 			\  libdbus_glib_1_la_LIBADD= $(DBUS_GLIB_LIBS) $(top_builddir)/dbus/libdbus-1.la -  if DBUS_BUILD_TESTS  if HAVE_GLIB_THREADS -    THREAD_APPS=test-thread-server test-thread-client -endif - -noinst_PROGRAMS= test-dbus-glib $(THREAD_APPS) - -test_dbus_glib_SOURCES=				\ -	test-dbus-glib.c - -test_dbus_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la +THREAD_APPS=test-thread-server test-thread-client test-profile -if HAVE_GLIB_THREADS  test_thread_server_SOURCES=				\  	test-thread-server.c				\  	test-thread.h @@ -41,4 +31,25 @@ test_thread_client_SOURCES=				\  test_thread_client_LDADD= $(DBUS_GLIB_THREADS_LIBS) $(top_builddir)/glib/libdbus-glib-1.la   endif +noinst_PROGRAMS= test-dbus-glib $(THREAD_APPS) + +test_dbus_glib_SOURCES=				\ +	test-dbus-glib.c + +test_dbus_glib_LDADD= $(top_builddir)/glib/libdbus-glib-1.la + +else +### not building tests + +if HAVE_GLIB_THREADS +noinst_PROGRAMS=test-profile +endif +  endif + +if HAVE_GLIB_THREADS +test_profile_SOURCES=				\ +	test-profile.c + +test_profile_LDADD= $(DBUS_GLIB_THREADS_LIBS) $(top_builddir)/glib/libdbus-glib-1.la  +endif
\ No newline at end of file diff --git a/glib/test-profile.c b/glib/test-profile.c new file mode 100644 index 00000000..6173f3a5 --- /dev/null +++ b/glib/test-profile.c @@ -0,0 +1,215 @@ +/* -*- mode: C; c-file-style: "gnu" -*- */ +/* test-profile.c Program that does basic message-response for timing + * + * Copyright (C) 2003  Red Hat Inc. + * + * Licensed under the Academic Free License version 1.2 + *  + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + *  + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#include <config.h> +#include <glib.h> +#include "dbus-glib.h" +#include <stdlib.h> + +#define N_CLIENT_THREADS 1 +#define N_ITERATIONS 2000 +#define ECHO_MESSAGE "org.freedesktop.DBus.Test.EchoProfile" +static const char *address; + +static void +send_echo_message (DBusConnection *connection) +{ +  DBusMessage *message; + +  message = dbus_message_new (ECHO_MESSAGE, NULL); +  dbus_message_append_args (message, +                            DBUS_TYPE_STRING, "Hello World!", +                            DBUS_TYPE_INT32, 123456, +                            DBUS_TYPE_INVALID); +  dbus_connection_send (connection, message, NULL); +  dbus_message_unref (message); +  dbus_connection_flush (connection); +} + +static DBusHandlerResult +client_filter (DBusMessageHandler *handler, +	       DBusConnection     *connection, +	       DBusMessage        *message, +	       void               *user_data) +{ +  int *iterations = user_data; +   +  if (dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT)) +    { +      g_printerr ("Client thread disconnected\n"); +      exit (1); +    } +  else if (dbus_message_has_name (message, +                                  ECHO_MESSAGE)) +    { +      *iterations += 1; +      send_echo_message (connection); +      if (*iterations > N_ITERATIONS) +        { +          g_print ("Completed %d iterations\n", N_ITERATIONS); +          exit (0); +        } +    } +   +  return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; +} + +static void* +thread_func (void *data) +{ +  DBusError error; +  GMainContext *context; +  GMainLoop *loop; +  DBusMessageHandler *handler; +  DBusConnection *connection; +  int iterations; +   +  g_printerr ("Starting client thread\n"); +   +  dbus_error_init (&error); +  connection = dbus_connection_open (address, &error); +  if (connection == NULL) +    { +      g_printerr ("could not open connection: %s\n", error.message); +      dbus_error_free (&error); +      exit (1); +    } + +  iterations = 0; +   +  handler = dbus_message_handler_new (client_filter, +                                      &iterations, NULL); +   +  if (!dbus_connection_add_filter (connection, +				   handler)) +    g_error ("no memory"); + +  /* FIXME we leak the handler */ +   +  context = g_main_context_new (); +  loop = g_main_loop_new (context, FALSE); +   +  dbus_connection_setup_with_g_main (connection, context); + +  g_printerr ("Client thread sending message to prime pingpong\n"); +  send_echo_message (connection); +  g_printerr ("Client thread sent message\n"); + +  g_printerr ("Client thread entering main loop\n"); +  g_main_loop_run (loop); +  g_printerr ("Client thread exiting main loop\n"); +   +  g_main_loop_unref (loop); +  g_main_context_unref (context); + +  return NULL; +} + +static DBusHandlerResult +server_filter (DBusMessageHandler *handler, +	       DBusConnection     *connection, +	       DBusMessage        *message, +	       void               *user_data) +{ +  if (dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT)) +    { +      g_printerr ("Server thread disconnected\n"); +      exit (1); +    } +  else if (dbus_message_has_name (message, +                                  ECHO_MESSAGE)) +    { +      send_echo_message (connection); +    } +   +  return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS; +} + +static void +new_connection_callback (DBusServer     *server, +                         DBusConnection *new_connection, +                         void           *user_data) +{ +  DBusMessageHandler *handler; +   +  dbus_connection_ref (new_connection); +  dbus_connection_setup_with_g_main (new_connection, NULL);   + +  handler = dbus_message_handler_new (server_filter, +                                      NULL, NULL); +   +  if (!dbus_connection_add_filter (new_connection, +				   handler)) +    g_error ("no memory"); +   + +  /* FIXME we leak the handler */   +} + +int +main (int argc, char *argv[]) +{ +  GMainLoop *loop; +  DBusError error; +  DBusServer *server; +  int i; +   +  g_thread_init (NULL); +  dbus_gthread_init (); + +  dbus_error_init (&error); +  server = dbus_server_listen ("unix:tmpdir="DBUS_TEST_SOCKET_DIR, +                               &error); +  if (server == NULL) +    { +      g_printerr ("Could not start server: %s\n", +                  error.message); +      return 1; +    } + +  address = dbus_server_get_address (server); +   +  dbus_server_set_new_connection_function (server, +                                           new_connection_callback, +                                           NULL, NULL); +   +  loop = g_main_loop_new (NULL, FALSE); + +  dbus_server_setup_with_g_main (server, NULL); +   +  for (i = 0; i < N_CLIENT_THREADS; i++) +    { +      g_thread_create (thread_func, NULL, FALSE, NULL); +    } + +  g_printerr ("Server thread entering main loop\n"); +  g_main_loop_run (loop); +  g_printerr ("Server thread exiting main loop\n"); + +  dbus_server_unref (server); +   +  g_main_loop_unref (loop); +   +  return 0; +} +   | 
