dbus/dbus Makefile.am, 1.87, 1.88 dbus-connection.c, 1.149, 1.150 dbus-sysdeps-pthread.c, NONE, 1.1 dbus-sysdeps-win-thread.c, NONE, 1.1 dbus-sysdeps.h, 1.64, 1.65 dbus-threads-internal.h, 1.4, 1.5 dbus-threads.c, 1.34, 1.35 dbus-threads.h, 1.13, 1.14

Havoc Pennington hp at kemper.freedesktop.org
Thu Oct 26 18:09:26 PDT 2006


Update of /cvs/dbus/dbus/dbus
In directory kemper:/tmp/cvs-serv11266/dbus

Modified Files:
	Makefile.am dbus-connection.c dbus-sysdeps.h 
	dbus-threads-internal.h dbus-threads.c dbus-threads.h 
Added Files:
	dbus-sysdeps-pthread.c dbus-sysdeps-win-thread.c 
Log Message:
2006-10-26  Havoc Pennington  <hp at redhat.com>

        * dbus/dbus-threads.[hc]: Documentation improvements. Clarify how 
	condition variables relate to recursive mutexes.
	
        * dbus/dbus-sysdeps-pthread.c, dbus/dbus-sysdeps-win-thread.c, 
	dbus/dbus-threads.c: Split the platforms-specific thread 
	implementations into their own files.
	
	* dbus/dbus-sysdeps-pthread.c
	(_dbus_pthread_condvar_wait_timeout): invert the return value, it
	was backward. Not that anything uses it.



Index: Makefile.am
===================================================================
RCS file: /cvs/dbus/dbus/dbus/Makefile.am,v
retrieving revision 1.87
retrieving revision 1.88
diff -u -d -r1.87 -r1.88
--- Makefile.am	26 Oct 2006 18:06:07 -0000	1.87
+++ Makefile.am	27 Oct 2006 01:09:24 -0000	1.88
@@ -113,6 +113,7 @@
 	dbus-string-private.h			\
 	dbus-sysdeps.c				\
 	dbus-sysdeps.h				\
+	dbus-sysdeps-pthread.c			\
 	dbus-sysdeps-unix.c			\
 	dbus-sysdeps-unix.h			\
 	dbus-userdb.c				\

Index: dbus-connection.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-connection.c,v
retrieving revision 1.149
retrieving revision 1.150
diff -u -d -r1.149 -r1.150
--- dbus-connection.c	26 Oct 2006 18:03:24 -0000	1.149
+++ dbus-connection.c	27 Oct 2006 01:09:24 -0000	1.150
@@ -991,7 +991,7 @@
  */
 static dbus_bool_t
 _dbus_connection_acquire_io_path (DBusConnection *connection,
-				  int timeout_milliseconds)
+				  int             timeout_milliseconds)
 {
   dbus_bool_t we_acquired;
   
@@ -1017,9 +1017,20 @@
         {
           _dbus_verbose ("%s waiting %d for IO path to be acquirable\n",
                          _DBUS_FUNCTION_NAME, timeout_milliseconds);
-          _dbus_condvar_wait_timeout (connection->io_path_cond,
-                                      connection->io_path_mutex,
-                                      timeout_milliseconds);
+
+          if (!_dbus_condvar_wait_timeout (connection->io_path_cond,
+                                           connection->io_path_mutex,
+                                           timeout_milliseconds))
+            {
+              /* We timed out before anyone signaled. */
+              /* (writing the loop to handle the !timedout case by
+               * waiting longer if needed is a pain since dbus
+               * wraps pthread_cond_timedwait to take a relative
+               * time instead of absolute, something kind of stupid
+               * on our part. for now it doesn't matter, we will just
+               * end up back here eventually.)
+               */
+            }
         }
       else
         {

--- NEW FILE: dbus-sysdeps-pthread.c ---
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-sysdeps-pthread.c Implements threads using pthreads (internal to libdbus)
 * 
 * Copyright (C) 2002, 2003, 2006  Red Hat, Inc.
 *
 * Licensed under the Academic Free License version 2.1
 * 
 * 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 "dbus-internals.h"
#include "dbus-sysdeps.h"
#include "dbus-threads.h"

#include <sys/time.h>
#include <pthread.h>

static DBusMutex*
_dbus_pthread_mutex_new (void)
{
  pthread_mutex_t *retval;
  
  retval = dbus_new (pthread_mutex_t, 1);
  if (retval == NULL)
    return NULL;
  
  if (pthread_mutex_init (retval, NULL))
    {
      dbus_free (retval);
      return NULL;
    }

  return (DBusMutex *) retval;
}

static void
_dbus_pthread_mutex_free (DBusMutex *mutex)
{
  pthread_mutex_destroy ((pthread_mutex_t *) mutex);
  dbus_free (mutex);
}

static dbus_bool_t
_dbus_pthread_mutex_lock (DBusMutex *mutex)
{
  return pthread_mutex_lock ((pthread_mutex_t *) mutex) == 0;
}

static dbus_bool_t
_dbus_pthread_mutex_unlock (DBusMutex *mutex)
{
  return pthread_mutex_unlock ((pthread_mutex_t *) mutex) == 0;
}

static DBusCondVar *
_dbus_pthread_condvar_new (void)
{
  pthread_cond_t *retval;
  
  retval = dbus_new (pthread_cond_t, 1);
  if (retval == NULL)
    return NULL;
  
  if (pthread_cond_init (retval, NULL))
    {
      dbus_free (retval);
      return NULL;
    }
  return (DBusCondVar *) retval;
}

static void
_dbus_pthread_condvar_free (DBusCondVar *cond)
{
  pthread_cond_destroy ((pthread_cond_t *) cond);
  dbus_free (cond);
}

static void
_dbus_pthread_condvar_wait (DBusCondVar *cond,
                    DBusMutex   *mutex)
{
  pthread_cond_wait ((pthread_cond_t *)cond,
		     (pthread_mutex_t *) mutex);
}

static dbus_bool_t
_dbus_pthread_condvar_wait_timeout (DBusCondVar               *cond,
				     DBusMutex                 *mutex,
				     int                        timeout_milliseconds)
{
  struct timeval time_now;
  struct timespec end_time;
  int result;
  
  gettimeofday (&time_now, NULL);
  
  end_time.tv_sec = time_now.tv_sec + timeout_milliseconds / 1000;
  end_time.tv_nsec = (time_now.tv_usec + (timeout_milliseconds % 1000) * 1000) * 1000;
  if (end_time.tv_nsec > 1000*1000*1000)
    {
      end_time.tv_sec += 1;
      end_time.tv_nsec -= 1000*1000*1000;
    }
  
  result = pthread_cond_timedwait ((pthread_cond_t *) cond,
				   (pthread_mutex_t *) mutex,
				   &end_time);
  
  /* return true if we did not time out */
  return result != ETIMEDOUT;
}

static void
_dbus_pthread_condvar_wake_one (DBusCondVar *cond)
{
  pthread_cond_signal ((pthread_cond_t *)cond);
}

static void
_dbus_pthread_condvar_wake_all (DBusCondVar *cond)
{
  pthread_cond_broadcast ((pthread_cond_t *)cond);
}

static const DBusThreadFunctions pthread_functions =
{
  DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
  DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
  DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
  DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
  DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
  DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
  _dbus_pthread_mutex_new,
  _dbus_pthread_mutex_free,
  _dbus_pthread_mutex_lock,
  _dbus_pthread_mutex_unlock,
  _dbus_pthread_condvar_new,
  _dbus_pthread_condvar_free,
  _dbus_pthread_condvar_wait,
  _dbus_pthread_condvar_wait_timeout,
  _dbus_pthread_condvar_wake_one,
  _dbus_pthread_condvar_wake_all
};

dbus_bool_t
_dbus_threads_init_platform_specific (void)
{
  return dbus_threads_init (&pthread_functions);
}

--- NEW FILE: dbus-sysdeps-win-thread.c ---
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-sysdeps-pthread.c Implements threads using Windows threads (internal to libdbus)
 * 
 * Copyright (C) 2006  Red Hat, Inc.
 *
 * Licensed under the Academic Free License version 2.1
 * 
 * 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 "dbus-internals.h"
#include "dbus-sysdeps.h"
#include "dbus-threads.h"

#include <windows.h>

struct DBusCondVar {
  DBusList *list;        /**< list thread-local-stored events waiting on the cond variable */
  CRITICAL_SECTION lock; /**< lock protecting the list */
};

static DWORD dbus_cond_event_tls = TLS_OUT_OF_INDEXES;


BOOL WINAPI DllMain (HINSTANCE hinstDLL,
		     DWORD     fdwReason,
		     LPVOID    lpvReserved);

/* We need this to free the TLS events on thread exit */
BOOL WINAPI
DllMain (HINSTANCE hinstDLL,
	 DWORD     fdwReason,
	 LPVOID    lpvReserved)
{
  HANDLE event;
  switch (fdwReason) 
    { 
    case DLL_THREAD_DETACH:
      if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
	{
	  event = TlsGetValue(dbus_cond_event_tls);
	  CloseHandle (event);
	  TlsSetValue(dbus_cond_event_tls, NULL);
	}
      break;
    case DLL_PROCESS_DETACH: 
      if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
	{
	  event = TlsGetValue(dbus_cond_event_tls);
	  CloseHandle (event);
	  TlsSetValue(dbus_cond_event_tls, NULL);

	  TlsFree(dbus_cond_event_tls); 
	}
      break;
    default: 
      break; 
    }
  return TRUE;
}

static DBusMutex*
_dbus_windows_mutex_new (void)
{
  HANDLE handle;
  handle = CreateMutex (NULL, FALSE, NULL);
  return (DBusMutex *) handle;
}

static void
_dbus_windows_mutex_free (DBusMutex *mutex)
{
  CloseHandle ((HANDLE *) mutex);
}

static dbus_bool_t
_dbus_windows_mutex_lock (DBusMutex *mutex)
{
  return WaitForSingleObject ((HANDLE *) mutex, INFINITE) != WAIT_FAILED;
}

static dbus_bool_t
_dbus_windows_mutex_unlock (DBusMutex *mutex)
{
  return ReleaseMutex ((HANDLE *) mutex) != 0;
}

static DBusCondVar *
_dbus_windows_condvar_new (void)
{
  DBusCondVar *cond;
    
  cond = dbus_new (DBusCondVar, 1);
  if (cond == NULL)
    return NULL;
  
  cond->list = NULL;
  
  InitializeCriticalSection (&cond->lock);
  return (DBusCondVar *) cond;
}

static void
_dbus_windows_condvar_free (DBusCondVar *cond)
{
  DeleteCriticalSection (&cond->lock);
  _dbus_list_clear (&cond->list);
  dbus_free (cond);
}

static dbus_bool_t
_dbus_condvar_wait_win32 (DBusCondVar *cond,
			  DBusMutex *mutex,
			  int milliseconds)
{
  DWORD retval;
  dbus_bool_t ret;
  HANDLE event = TlsGetValue (dbus_cond_event_tls);

  if (!event)
    {
      event = CreateEvent (0, FALSE, FALSE, NULL);
      if (event == 0)
	return FALSE;
      TlsSetValue (dbus_cond_event_tls, event);
    }

  EnterCriticalSection (&cond->lock);

  /* The event must not be signaled. Check this */
  _dbus_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT);

  ret = _dbus_list_append (&cond->list, event);
  
  LeaveCriticalSection (&cond->lock);
  
  if (!ret)
    return FALSE; /* Prepend failed */

  _dbus_mutex_unlock (mutex);
  retval = WaitForSingleObject (event, milliseconds);
  _dbus_mutex_lock (mutex);
  
  if (retval == WAIT_TIMEOUT)
    {
      EnterCriticalSection (&cond->lock);
      _dbus_list_remove (&cond->list, event);

      /* In the meantime we could have been signaled, so we must again
       * wait for the signal, this time with no timeout, to reset
       * it. retval is set again to honour the late arrival of the
       * signal */
      retval = WaitForSingleObject (event, 0);

      LeaveCriticalSection (&cond->lock);
    }

#ifndef DBUS_DISABLE_ASSERT
  EnterCriticalSection (&cond->lock);

  /* Now event must not be inside the array, check this */
  _dbus_assert (_dbus_list_remove (cond->list, event) == FALSE);

  LeaveCriticalSection (&cond->lock);
#endif /* !G_DISABLE_ASSERT */

  return retval != WAIT_TIMEOUT;
}

static void
_dbus_windows_condvar_wait (DBusCondVar *cond,
                            DBusMutex   *mutex)
{
  _dbus_condvar_wait_win32 (cond, mutex, INFINITE);
}

static dbus_bool_t
_dbus_windows_condvar_wait_timeout (DBusCondVar               *cond,
				     DBusMutex                 *mutex,
				     int                        timeout_milliseconds)
{
  return _dbus_condvar_wait_win32 (cond, mutex, timeout_milliseconds);
}

static void
_dbus_windows_condvar_wake_one (DBusCondVar *cond)
{
  EnterCriticalSection (&cond->lock);
  
  if (cond->list != NULL)
    SetEvent (_dbus_list_pop_first (&cond->list));
    
  LeaveCriticalSection (&cond->lock);
}

static void
_dbus_windows_condvar_wake_all (DBusCondVar *cond)
{
  EnterCriticalSection (&cond->lock);

  while (cond->list != NULL)
    SetEvent (_dbus_list_pop_first (&cond->list));
  
  LeaveCriticalSection (&cond->lock);
}

static const DBusThreadFunctions windows_functions =
{
  DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
  DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
  DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
  DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
  DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
  DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
  _dbus_windows_mutex_new,
  _dbus_windows_mutex_free,
  _dbus_windows_mutex_lock,
  _dbus_windows_mutex_unlock,
  _dbus_windows_condvar_new,
  _dbus_windows_condvar_free,
  _dbus_windows_condvar_wait,
  _dbus_windows_condvar_wait_timeout,
  _dbus_windows_condvar_wake_one,
  _dbus_windows_condvar_wake_all
};

void
_dbus_threads_init_platform_specific (void)
{
  /* We reuse this over several generations, because we can't
   * free the events once they are in use
   */
  if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
    {
      dbus_cond_event_tls = TlsAlloc ();
      if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
	return FALSE;
    }

  return dbus_threads_init (&windows_functions);
}


Index: dbus-sysdeps.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps.h,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- dbus-sysdeps.h	24 Oct 2006 20:25:01 -0000	1.64
+++ dbus-sysdeps.h	27 Oct 2006 01:09:24 -0000	1.65
@@ -425,6 +425,12 @@
                                              dbus_bool_t       create_if_not_found,
                                              DBusError        *error);
 
+/**
+ * Initialize threads as in dbus_threads_init_default(), appropriately
+ * for the platform.
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t _dbus_threads_init_platform_specific (void);
 
 /** @} */
 

Index: dbus-threads-internal.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-threads-internal.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- dbus-threads-internal.h	14 Sep 2006 04:26:00 -0000	1.4
+++ dbus-threads-internal.h	27 Oct 2006 01:09:24 -0000	1.5
@@ -43,10 +43,10 @@
 dbus_bool_t  _dbus_condvar_wait_timeout      (DBusCondVar       *cond,
                                               DBusMutex         *mutex,
                                               int                timeout_milliseconds);
-void          _dbus_condvar_wake_one         (DBusCondVar       *cond);
-void          _dbus_condvar_wake_all         (DBusCondVar       *cond);
-void          _dbus_condvar_new_at_location  (DBusCondVar      **location_p);
-void          _dbus_condvar_free_at_location (DBusCondVar      **location_p);
+void         _dbus_condvar_wake_one          (DBusCondVar       *cond);
+void         _dbus_condvar_wake_all          (DBusCondVar       *cond);
+void         _dbus_condvar_new_at_location   (DBusCondVar      **location_p);
+void         _dbus_condvar_free_at_location  (DBusCondVar      **location_p);
 
 DBUS_END_DECLS
 

Index: dbus-threads.c
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-threads.c,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -d -r1.34 -r1.35
--- dbus-threads.c	24 Oct 2006 21:28:57 -0000	1.34
+++ dbus-threads.c	27 Oct 2006 01:09:24 -0000	1.35
@@ -1,7 +1,7 @@
 /* -*- mode: C; c-file-style: "gnu" -*- */
 /* dbus-threads.h  D-Bus threads handling
  *
- * Copyright (C) 2002, 2003 Red Hat Inc.
+ * Copyright (C) 2002, 2003, 2006 Red Hat Inc.
  *
  * Licensed under the Academic Free License version 2.1
  * 
@@ -25,17 +25,6 @@
 #include "dbus-threads-internal.h"
 #include "dbus-list.h"
 
-#if defined(__WIN32) || defined(__CYGWIN__)
-#define USE_WIN32_THREADS
-#endif
-
-#ifdef USE_WIN32_THREADS
-#include <windows.h>
-#else
-#include <sys/time.h>
-#include <pthread.h>
-#endif
-
 static DBusThreadFunctions thread_functions =
 {
   0,
@@ -46,15 +35,6 @@
   NULL, NULL, NULL, NULL
 };
 
-#ifdef USE_WIN32_THREADS
-struct DBusCondVar {
-  DBusList *list;
-  CRITICAL_SECTION lock;
-};
-
-static DWORD dbus_cond_event_tls = TLS_OUT_OF_INDEXES;
-#endif
-
 static int thread_init_generation = 0;
  
 static DBusList *uninitialized_mutex_list = NULL;
@@ -275,16 +255,15 @@
 }
 
 /**
- * Atomically unlocks the mutex and waits for the conditions
- * variable to be signalled, or for a timeout. Locks the
- * mutex again before returning.
- * Does nothing if passed a #NULL pointer.
+ * Atomically unlocks the mutex and waits for the conditions variable
+ * to be signalled, or for a timeout. Locks the mutex again before
+ * returning.  Does nothing if passed a #NULL pointer.  Return value
+ * is #FALSE if we timed out, #TRUE otherwise.
  *
  * @param cond the condition variable
  * @param mutex the mutex
  * @param timeout_milliseconds the maximum time to wait
- * @returns TRUE if the condition was reached, or FALSE if the
- * timeout was reached.
+ * @returns #FALSE if the timeout occurred, #TRUE if not
  */
 dbus_bool_t
 _dbus_condvar_wait_timeout (DBusCondVar               *cond,
@@ -672,338 +651,6 @@
 
 /* Default thread implemenation */
 
-static DBusMutex*   _dbus_internal_mutex_new            (void);
-static void         _dbus_internal_mutex_free           (DBusMutex   *mutex);
-static dbus_bool_t  _dbus_internal_mutex_lock           (DBusMutex   *mutex);
-static dbus_bool_t  _dbus_internal_mutex_unlock         (DBusMutex   *mutex);
-static DBusCondVar *_dbus_internal_condvar_new          (void);
-static void         _dbus_internal_condvar_free         (DBusCondVar *cond);
-static void         _dbus_internal_condvar_wait         (DBusCondVar *cond,
-							 DBusMutex   *mutex);
-static dbus_bool_t  _dbus_internal_condvar_wait_timeout (DBusCondVar *cond,
-							 DBusMutex   *mutex,
-							 int          timeout_milliseconds);
-static void         _dbus_internal_condvar_wake_one     (DBusCondVar *cond);
-static void         _dbus_internal_condvar_wake_all     (DBusCondVar *cond);
-
-#ifdef USE_WIN32_THREADS
-
-BOOL WINAPI DllMain (HINSTANCE hinstDLL,
-		     DWORD     fdwReason,
-		     LPVOID    lpvReserved);
-
-/* We need this to free the TLS events on thread exit */
-BOOL WINAPI
-DllMain (HINSTANCE hinstDLL,
-	 DWORD     fdwReason,
-	 LPVOID    lpvReserved)
-{
-  HANDLE event;
-  switch (fdwReason) 
-    { 
-    case DLL_THREAD_DETACH:
-      if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
-	{
-	  event = TlsGetValue(dbus_cond_event_tls);
-	  CloseHandle (event);
-	  TlsSetValue(dbus_cond_event_tls, NULL);
-	}
-      break;
-    case DLL_PROCESS_DETACH: 
-      if (dbus_cond_event_tls != TLS_OUT_OF_INDEXES)
-	{
-	  event = TlsGetValue(dbus_cond_event_tls);
-	  CloseHandle (event);
-	  TlsSetValue(dbus_cond_event_tls, NULL);
-
-	  TlsFree(dbus_cond_event_tls); 
-	}
-      break;
-    default: 
-      break; 
-    }
-  return TRUE;
-}
-
-static DBusMutex*
-_dbus_internal_mutex_new (void)
-{
-  HANDLE handle;
-  handle = CreateMutex (NULL, FALSE, NULL);
-  return (DBusMutex *) handle;
-}
-
-static void
-_dbus_internal_mutex_free (DBusMutex *mutex)
-{
-  CloseHandle ((HANDLE *) mutex);
-}
-
-static dbus_bool_t
-_dbus_internal_mutex_lock (DBusMutex *mutex)
-{
-  return WaitForSingleObject ((HANDLE *) mutex, INFINITE) != WAIT_FAILED;
-}
-
-static dbus_bool_t
-_dbus_internal_mutex_unlock (DBusMutex *mutex)
-{
-  return ReleaseMutex ((HANDLE *) mutex) != 0;
-}
-
-static DBusCondVar *
-_dbus_internal_condvar_new (void)
-{
-  DBusCondVar *cond;
-    
-  cond = dbus_new (DBusCondVar, 1);
-  if (cond == NULL)
-    return NULL;
-  
-  cond->list = NULL;
-  
-  InitializeCriticalSection (&cond->lock);
-  return (DBusCondVar *) cond;
-}
-
-static void
-_dbus_internal_condvar_free (DBusCondVar *cond)
-{
-  DeleteCriticalSection (&cond->lock);
-  _dbus_list_clear (&cond->list);
-  dbus_free (cond);
-}
-
-static dbus_bool_t
-_dbus_condvar_wait_win32 (DBusCondVar *cond,
-			  DBusMutex *mutex,
-			  int milliseconds)
-{
-  DWORD retval;
-  dbus_bool_t ret;
-  HANDLE event = TlsGetValue (dbus_cond_event_tls);
-
-  if (!event)
-    {
-      event = CreateEvent (0, FALSE, FALSE, NULL);
-      if (event == 0)
-	return FALSE;
-      TlsSetValue (dbus_cond_event_tls, event);
-    }
-
-  EnterCriticalSection (&cond->lock);
-
-  /* The event must not be signaled. Check this */
-  _dbus_assert (WaitForSingleObject (event, 0) == WAIT_TIMEOUT);
-
-  ret = _dbus_list_append (&cond->list, event);
-  
-  LeaveCriticalSection (&cond->lock);
-  
-  if (!ret)
-    return FALSE; /* Prepend failed */
-
-  _dbus_mutex_unlock (mutex);
-  retval = WaitForSingleObject (event, milliseconds);
-  _dbus_mutex_lock (mutex);
-  
-  if (retval == WAIT_TIMEOUT)
-    {
-      EnterCriticalSection (&cond->lock);
-      _dbus_list_remove (&cond->list, event);
-
-      /* In the meantime we could have been signaled, so we must again
-       * wait for the signal, this time with no timeout, to reset
-       * it. retval is set again to honour the late arrival of the
-       * signal */
-      retval = WaitForSingleObject (event, 0);
-
-      LeaveCriticalSection (&cond->lock);
-    }
-
-#ifndef DBUS_DISABLE_ASSERT
-  EnterCriticalSection (&cond->lock);
-
-  /* Now event must not be inside the array, check this */
-  _dbus_assert (_dbus_list_remove (cond->list, event) == FALSE);
-
-  LeaveCriticalSection (&cond->lock);
-#endif /* !G_DISABLE_ASSERT */
-
-  return retval != WAIT_TIMEOUT;
-}
-
-static void
-_dbus_internal_condvar_wait (DBusCondVar *cond,
-                    DBusMutex   *mutex)
-{
-  _dbus_condvar_wait_win32 (cond, mutex, INFINITE);
-}
-
-static dbus_bool_t
-_dbus_internal_condvar_wait_timeout (DBusCondVar               *cond,
-				     DBusMutex                 *mutex,
-				     int                        timeout_milliseconds)
-{
-  return _dbus_condvar_wait_win32 (cond, mutex, timeout_milliseconds);
-}
-
-static void
-_dbus_internal_condvar_wake_one (DBusCondVar *cond)
-{
-  EnterCriticalSection (&cond->lock);
-  
-  if (cond->list != NULL)
-    SetEvent (_dbus_list_pop_first (&cond->list));
-    
-  LeaveCriticalSection (&cond->lock);
-}
-
-static void
-_dbus_internal_condvar_wake_all (DBusCondVar *cond)
-{
-  EnterCriticalSection (&cond->lock);
-
-  while (cond->list != NULL)
-    SetEvent (_dbus_list_pop_first (&cond->list));
-  
-  LeaveCriticalSection (&cond->lock);
-}
-
-
-#else /* Posix threads */
-
-static DBusMutex*
-_dbus_internal_mutex_new (void)
-{
-  pthread_mutex_t *retval;
-  
-  retval = dbus_new (pthread_mutex_t, 1);
-  if (retval == NULL)
-    return NULL;
-  
-  if (pthread_mutex_init (retval, NULL))
-    {
-      dbus_free (retval);
-      return NULL;
-    }
-  return (DBusMutex *) retval;
-}
-
-static void
-_dbus_internal_mutex_free (DBusMutex *mutex)
-{
-  pthread_mutex_destroy ((pthread_mutex_t *) mutex);
-  dbus_free (mutex);
-}
-
-static dbus_bool_t
-_dbus_internal_mutex_lock (DBusMutex *mutex)
-{
-  return pthread_mutex_lock ((pthread_mutex_t *) mutex) == 0;
-}
-
-static dbus_bool_t
-_dbus_internal_mutex_unlock (DBusMutex *mutex)
-{
-  return pthread_mutex_unlock ((pthread_mutex_t *) mutex) == 0;
-}
-
-static DBusCondVar *
-_dbus_internal_condvar_new (void)
-{
-  pthread_cond_t *retval;
-  
-  retval = dbus_new (pthread_cond_t, 1);
-  if (retval == NULL)
-    return NULL;
-  
-  if (pthread_cond_init (retval, NULL))
-    {
-      dbus_free (retval);
-      return NULL;
-    }
-  return (DBusCondVar *) retval;
-}
-
-static void
-_dbus_internal_condvar_free (DBusCondVar *cond)
-{
-  pthread_cond_destroy ((pthread_cond_t *) cond);
-  dbus_free (cond);
-}
-
-static void
-_dbus_internal_condvar_wait (DBusCondVar *cond,
-                    DBusMutex   *mutex)
-{
-  pthread_cond_wait ((pthread_cond_t *)cond,
-		     (pthread_mutex_t *) mutex);
-}
-
-static dbus_bool_t
-_dbus_internal_condvar_wait_timeout (DBusCondVar               *cond,
-				     DBusMutex                 *mutex,
-				     int                        timeout_milliseconds)
-{
-  struct timeval time_now;
-  struct timespec end_time;
-  int result;
-  
-  gettimeofday (&time_now, NULL);
-  
-  end_time.tv_sec = time_now.tv_sec + timeout_milliseconds / 1000;
-  end_time.tv_nsec = (time_now.tv_usec + (timeout_milliseconds % 1000) * 1000) * 1000;
-  if (end_time.tv_nsec > 1000*1000*1000)
-    {
-      end_time.tv_sec += 1;
-      end_time.tv_nsec -= 1000*1000*1000;
-    }
-  
-  result = pthread_cond_timedwait ((pthread_cond_t *) cond,
-				   (pthread_mutex_t *) mutex,
-				   &end_time);
-  return result == ETIMEDOUT;
-}
-
-static void
-_dbus_internal_condvar_wake_one (DBusCondVar *cond)
-{
-  pthread_cond_signal ((pthread_cond_t *)cond);
-}
-
-static void
-_dbus_internal_condvar_wake_all (DBusCondVar *cond)
-{
-  pthread_cond_broadcast ((pthread_cond_t *)cond);
-}
-
-#endif
-
-static const DBusThreadFunctions internal_functions =
-{
-  DBUS_THREAD_FUNCTIONS_MUTEX_NEW_MASK |
-  DBUS_THREAD_FUNCTIONS_MUTEX_FREE_MASK |
-  DBUS_THREAD_FUNCTIONS_MUTEX_LOCK_MASK |
-  DBUS_THREAD_FUNCTIONS_MUTEX_UNLOCK_MASK |
-  DBUS_THREAD_FUNCTIONS_CONDVAR_NEW_MASK |
-  DBUS_THREAD_FUNCTIONS_CONDVAR_FREE_MASK |
-  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_MASK |
-  DBUS_THREAD_FUNCTIONS_CONDVAR_WAIT_TIMEOUT_MASK |
-  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ONE_MASK|
-  DBUS_THREAD_FUNCTIONS_CONDVAR_WAKE_ALL_MASK,
-  _dbus_internal_mutex_new,
-  _dbus_internal_mutex_free,
-  _dbus_internal_mutex_lock,
-  _dbus_internal_mutex_unlock,
-  _dbus_internal_condvar_new,
-  _dbus_internal_condvar_free,
-  _dbus_internal_condvar_wait,
-  _dbus_internal_condvar_wait_timeout,
-  _dbus_internal_condvar_wake_one,
-  _dbus_internal_condvar_wake_all
-};
-
 /**
  *
  * Calls dbus_threads_init() with a default set of
@@ -1022,19 +669,7 @@
 dbus_bool_t
 dbus_threads_init_default (void)
 {
-#ifdef USE_WIN32_THREADS
-  /* We reuse this over several generations, because we can't
-   * free the events once they are in use
-   */
-  if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
-    {
-      dbus_cond_event_tls = TlsAlloc ();
-      if (dbus_cond_event_tls == TLS_OUT_OF_INDEXES)
-	return FALSE;
-    }
-#endif
-  
-  return dbus_threads_init (&internal_functions);
+  return _dbus_threads_init_platform_specific ();
 }
 
 

Index: dbus-threads.h
===================================================================
RCS file: /cvs/dbus/dbus/dbus/dbus-threads.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- dbus-threads.h	21 Oct 2006 21:57:31 -0000	1.13
+++ dbus-threads.h	27 Oct 2006 01:09:24 -0000	1.14
@@ -46,13 +46,16 @@
 typedef DBusMutex*  (* DBusMutexNewFunction)    (void);
 /** Deprecated, provide DBusRecursiveMutexFreeFunction instead. */
 typedef void        (* DBusMutexFreeFunction)   (DBusMutex *mutex);
-/** Deprecated, provide DBusRecursiveMutexLockFunction instead. */
+/** Deprecated, provide DBusRecursiveMutexLockFunction instead. Return value is lock success, but gets ignored in practice. */
 typedef dbus_bool_t (* DBusMutexLockFunction)   (DBusMutex *mutex);
-/** Deprecated, provide DBusRecursiveMutexUnlockFunction instead. */
+/** Deprecated, provide DBusRecursiveMutexUnlockFunction instead. Return value is unlock success, but gets ignored in practice. */
 typedef dbus_bool_t (* DBusMutexUnlockFunction) (DBusMutex *mutex);
 
 /** Creates a new recursively-lockable mutex, or returns #NULL if not enough memory.
- * Found in #DBusThreadFunctions
+ * Found in #DBusThreadFunctions. Do not just use PTHREAD_MUTEX_RECURSIVE for this, because
+ * it does not save/restore the recursion count when waiting on a condition. libdbus
+ * requires the Java-style behavior where the mutex is fully unlocked to wait on
+ * a condition.
  */
 typedef DBusMutex*  (* DBusRecursiveMutexNewFunction)    (void);
 /** Frees a recursively-lockable mutex.  Found in #DBusThreadFunctions.
@@ -71,11 +74,21 @@
 /** Frees a condition variable.  Found in #DBusThreadFunctions.
  */
 typedef void          (* DBusCondVarFreeFunction)        (DBusCondVar *cond);
-/** Waits on a condition variable.  Found in #DBusThreadFunctions.
+
+/** Waits on a condition variable.  Found in
+ * #DBusThreadFunctions. Must work with either a recursive or
+ * nonrecursive mutex, whichever the thread implementation
+ * provides. Note that PTHREAD_MUTEX_RECURSIVE does not work with
+ * condition variables (does not save/restore the recursion count) so
+ * don't try using simply pthread_cond_wait() and a
+ * PTHREAD_MUTEX_RECURSIVE to implement this, it won't work right.
  */
 typedef void          (* DBusCondVarWaitFunction)        (DBusCondVar *cond,
 							  DBusMutex   *mutex);
-/** Waits on a condition variable with a timeout.  Found in #DBusThreadFunctions.
+
+/** Waits on a condition variable with a timeout.  Found in
+ *  #DBusThreadFunctions. Returns #TRUE if the wait did not
+ *  time out, and #FALSE if it did.
  */
 typedef dbus_bool_t   (* DBusCondVarWaitTimeoutFunction) (DBusCondVar *cond,
 							  DBusMutex   *mutex,
@@ -115,6 +128,22 @@
  * Functions that must be implemented to make the D-Bus library
  * thread-aware. The recursive mutex functions should be specified
  * rather than the old, deprecated nonrecursive ones.
+ *
+ * The condition variable functions have to work with recursive
+ * mutexes if you provide those, or with nonrecursive mutexes if you
+ * provide those.
+ *
+ * If implementing threads using pthreads, be aware that
+ * PTHREAD_MUTEX_RECURSIVE is broken in combination with condition
+ * variables. libdbus relies on the Java-style behavior that when
+ * waiting on a condition, the recursion count is saved and restored,
+ * and the mutex is completely unlocked, not just decremented one
+ * level of recursion.
+ *
+ * Thus with pthreads you probably have to roll your own emulated
+ * recursive mutexes, you can't use PTHREAD_MUTEX_RECURSIVE. This is
+ * what dbus_threads_init_default() does on platforms that use
+ * pthreads.
  */
 typedef struct
 {



More information about the dbus-commit mailing list