2003-05-11 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Sun, 11 May 2003 07:59:08 +0000 (07:59 +0000)
committerHavoc Pennington <hp@redhat.com>
Sun, 11 May 2003 07:59:08 +0000 (07:59 +0000)
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()

13 files changed:
ChangeLog
bus/connection.c
configure.in
dbus/dbus-auth.c
dbus/dbus-connection.c
dbus/dbus-internals.c
dbus/dbus-message.c
dbus/dbus-spawn.c
dbus/dbus-sysdeps.c
dbus/dbus-sysdeps.h
dbus/dbus-threads.c
glib/Makefile.am
glib/test-profile.c [new file with mode: 0644]

index 43321cc..cb74a1e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
index 6bb5314..05532db 100644 (file)
@@ -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");
index 18cb519..f95da56 100644 (file)
@@ -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"
index 4da3966..b496dba 100644 (file)
@@ -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.
index 688841d..6309ea4 100644 (file)
@@ -21,6 +21,7 @@
  *
  */
 
+#include <config.h>
 #include "dbus-connection.h"
 #include "dbus-list.h"
 #include "dbus-timeout.h"
 #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;
 }
 
index 25bd52b..6a091e6 100644 (file)
@@ -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);
index 668736d..2920910 100644 (file)
@@ -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);
   
index 179b9f9..d401556 100644 (file)
@@ -31,6 +31,7 @@
 #include <signal.h>
 #include <sys/wait.h>
 #include <errno.h>
+#include <stdlib.h>
 
 /**
  * @addtogroup DBusInternalsUtils
index 91f6e95..c813a83 100644 (file)
@@ -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
 }
 
 /**
index 593496c..2ae455b 100644 (file)
@@ -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 */
index 07c9897..76b2f19 100644 (file)
@@ -458,7 +458,7 @@ dbus_fake_condvar_free (DBusCondVar *cond)
 
 static void
 dbus_fake_condvar_wait (DBusCondVar *cond,
-                   DBusMutex   *mutex)
+                        DBusMutex   *mutex)
 {
   
 }
index d9edf6f..ebdb932 100644 (file)
@@ -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 (file)
index 0000000..6173f3a
--- /dev/null
@@ -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;
+}
+