mirror of
https://gitlab.freedesktop.org/dbus/dbus.git
synced 2026-06-16 08:08:22 +02:00
2006-10-26 Havoc Pennington <hp@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.
This commit is contained in:
parent
caae991f97
commit
5886f5326d
9 changed files with 506 additions and 385 deletions
13
ChangeLog
13
ChangeLog
|
|
@ -1,3 +1,16 @@
|
|||
2006-10-26 Havoc Pennington <hp@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.
|
||||
|
||||
2006-10-26 John (J5) Palmieri <johnp@redhat.com>
|
||||
|
||||
* dbus-sysdeps-unix.c (_dbus_set_local_creds): Clean up the
|
||||
|
|
|
|||
|
|
@ -113,6 +113,7 @@ DBUS_SHARED_SOURCES= \
|
|||
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 \
|
||||
|
|
|
|||
|
|
@ -991,7 +991,7 @@ _dbus_connection_remove_pending_call (DBusConnection *connection,
|
|||
*/
|
||||
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_connection_acquire_io_path (DBusConnection *connection,
|
|||
{
|
||||
_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
|
||||
{
|
||||
|
|
|
|||
167
dbus/dbus-sysdeps-pthread.c
Normal file
167
dbus/dbus-sysdeps-pthread.c
Normal file
|
|
@ -0,0 +1,167 @@
|
|||
/* -*- 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);
|
||||
}
|
||||
259
dbus/dbus-sysdeps-win-thread.c
Normal file
259
dbus/dbus-sysdeps-win-thread.c
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/* -*- 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);
|
||||
}
|
||||
|
||||
|
|
@ -425,6 +425,12 @@ dbus_bool_t _dbus_read_local_machine_uuid (DBusGUID *machine_id,
|
|||
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);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
|
|
|||
|
|
@ -43,10 +43,10 @@ void _dbus_condvar_wait (DBusCondVar *cond,
|
|||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 @@ static DBusThreadFunctions thread_functions =
|
|||
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 @@ _dbus_condvar_wait (DBusCondVar *cond,
|
|||
}
|
||||
|
||||
/**
|
||||
* 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 @@ dbus_threads_init (const DBusThreadFunctions *functions)
|
|||
|
||||
/* 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 @@ static const DBusThreadFunctions internal_functions =
|
|||
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 ();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -46,13 +46,16 @@ typedef struct DBusCondVar DBusCondVar;
|
|||
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 @@ typedef DBusCondVar* (* DBusCondVarNewFunction) (void);
|
|||
/** 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 @@ typedef enum
|
|||
* 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
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue