Remove windows thread implementation in favour of pthreads

There are a number of pthreads impls available on Win32
these days, in particular the mingw64 project has a good
impl. Delete the native windows thread implementation and
rely on using pthreads everywhere.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrange 2014-01-22 16:17:10 +00:00
parent ab6979430a
commit 0240d94c36
8 changed files with 332 additions and 859 deletions

View File

@ -270,12 +270,21 @@ AC_CHECK_FUNCS_ONCE([cfmakeraw fallocate geteuid getgid getgrnam_r \
posix_memalign prlimit regexec sched_getaffinity setgroups setns \
setrlimit symlink sysctlbyname])
dnl Availability of pthread functions (if missing, win32 threading is
dnl assumed). Because of $LIB_PTHREAD, we cannot use AC_CHECK_FUNCS_ONCE.
dnl LIB_PTHREAD and LIBMULTITHREAD were set during gl_INIT by gnulib.
dnl Availability of pthread functions. Because of $LIB_PTHREAD, we
dnl cannot use AC_CHECK_FUNCS_ONCE. LIB_PTHREAD and LIBMULTITHREAD
dnl were set during gl_INIT by gnulib.
old_LIBS=$LIBS
LIBS="$LIBS $LIB_PTHREAD $LIBMULTITHREAD"
pthread_found=yes
AC_CHECK_FUNCS([pthread_mutexattr_init])
AC_CHECK_HEADER([pthread.h],,[pthread_found=no])
if test "$ac_cv_func_pthread_mutexattr_init:$pthread_found" != "yes:yes"
then
AC_MSG_ERROR([A pthreads impl is required for building libvirt])
fi
dnl At least mingw64-winpthreads #defines pthread_sigmask to 0,
dnl which in turn causes compilation to complain about unused variables.
dnl Expose this broken implementation, so we can work around it.

View File

@ -141,8 +141,6 @@ UTIL_SOURCES = \
util/virsysinfo.c util/virsysinfo.h \
util/virsystemd.c util/virsystemd.h \
util/virthread.c util/virthread.h \
util/virthreadpthread.h \
util/virthreadwin32.h \
util/virthreadpool.c util/virthreadpool.h \
util/virtime.h util/virtime.c \
util/virtpm.h util/virtpm.c \
@ -165,8 +163,6 @@ util/virkeymaps.h: $(srcdir)/util/keymaps.csv \
$(AM_V_GEN)$(PYTHON) $(srcdir)/util/virkeycode-mapgen.py \
<$(srcdir)/util/keymaps.csv >$(srcdir)/util/virkeymaps.h
EXTRA_DIST += util/virthreadpthread.c util/virthreadwin32.c
# Internal generic driver infrastructure
NODE_INFO_SOURCES = nodeinfo.h nodeinfo.c nodeinfopriv.h
DATATYPES_SOURCES = datatypes.h datatypes.c

View File

@ -23,12 +23,291 @@
#include "virthread.h"
/* On mingw, we prefer native threading over the sometimes-broken
* pthreads-win32 library wrapper. */
#ifdef WIN32
# include "virthreadwin32.c"
#elif defined HAVE_PTHREAD_MUTEXATTR_INIT
# include "virthreadpthread.c"
#else
# error "Either pthreads or Win32 threads are required"
#include <unistd.h>
#include <inttypes.h>
#if HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif
#include "viralloc.h"
/* Nothing special required for pthreads */
int virThreadInitialize(void)
{
return 0;
}
void virThreadOnExit(void)
{
}
int virOnce(virOnceControlPtr once, virOnceFunc init)
{
return pthread_once(&once->once, init);
}
int virMutexInit(virMutexPtr m)
{
int ret;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
ret = pthread_mutex_init(&m->lock, &attr);
pthread_mutexattr_destroy(&attr);
if (ret != 0) {
errno = ret;
return -1;
}
return 0;
}
int virMutexInitRecursive(virMutexPtr m)
{
int ret;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
ret = pthread_mutex_init(&m->lock, &attr);
pthread_mutexattr_destroy(&attr);
if (ret != 0) {
errno = ret;
return -1;
}
return 0;
}
void virMutexDestroy(virMutexPtr m)
{
pthread_mutex_destroy(&m->lock);
}
void virMutexLock(virMutexPtr m){
pthread_mutex_lock(&m->lock);
}
void virMutexUnlock(virMutexPtr m)
{
pthread_mutex_unlock(&m->lock);
}
int virRWLockInit(virRWLockPtr m)
{
int ret;
ret = pthread_rwlock_init(&m->lock, NULL);
if (ret != 0) {
errno = ret;
return -1;
}
return 0;
}
void virRWLockDestroy(virRWLockPtr m)
{
pthread_rwlock_destroy(&m->lock);
}
void virRWLockRead(virRWLockPtr m)
{
pthread_rwlock_rdlock(&m->lock);
}
void virRWLockWrite(virRWLockPtr m)
{
pthread_rwlock_wrlock(&m->lock);
}
void virRWLockUnlock(virRWLockPtr m)
{
pthread_rwlock_unlock(&m->lock);
}
int virCondInit(virCondPtr c)
{
int ret;
if ((ret = pthread_cond_init(&c->cond, NULL)) != 0) {
errno = ret;
return -1;
}
return 0;
}
int virCondDestroy(virCondPtr c)
{
int ret;
if ((ret = pthread_cond_destroy(&c->cond)) != 0) {
errno = ret;
return -1;
}
return 0;
}
int virCondWait(virCondPtr c, virMutexPtr m)
{
int ret;
if ((ret = pthread_cond_wait(&c->cond, &m->lock)) != 0) {
errno = ret;
return -1;
}
return 0;
}
int virCondWaitUntil(virCondPtr c, virMutexPtr m, unsigned long long whenms)
{
int ret;
struct timespec ts;
ts.tv_sec = whenms / 1000;
ts.tv_nsec = (whenms % 1000) * 1000;
if ((ret = pthread_cond_timedwait(&c->cond, &m->lock, &ts)) != 0) {
errno = ret;
return -1;
}
return 0;
}
void virCondSignal(virCondPtr c)
{
pthread_cond_signal(&c->cond);
}
void virCondBroadcast(virCondPtr c)
{
pthread_cond_broadcast(&c->cond);
}
struct virThreadArgs {
virThreadFunc func;
void *opaque;
};
static void *virThreadHelper(void *data)
{
struct virThreadArgs *args = data;
struct virThreadArgs local = *args;
/* Free args early, rather than tying it up during the entire thread. */
VIR_FREE(args);
local.func(local.opaque);
return NULL;
}
int virThreadCreate(virThreadPtr thread,
bool joinable,
virThreadFunc func,
void *opaque)
{
struct virThreadArgs *args;
pthread_attr_t attr;
int ret = -1;
int err;
if ((err = pthread_attr_init(&attr)) != 0)
goto cleanup;
if (VIR_ALLOC_QUIET(args) < 0) {
err = ENOMEM;
goto cleanup;
}
args->func = func;
args->opaque = opaque;
if (!joinable)
pthread_attr_setdetachstate(&attr, 1);
err = pthread_create(&thread->thread, &attr, virThreadHelper, args);
if (err != 0) {
VIR_FREE(args);
goto cleanup;
}
/* New thread owns 'args' in success case, so don't free */
ret = 0;
cleanup:
pthread_attr_destroy(&attr);
if (ret < 0)
errno = err;
return ret;
}
void virThreadSelf(virThreadPtr thread)
{
thread->thread = pthread_self();
}
bool virThreadIsSelf(virThreadPtr thread)
{
return pthread_equal(pthread_self(), thread->thread) ? true : false;
}
/* For debugging use only; this result is not guaranteed unique if
* pthread_t is larger than a 64-bit pointer, nor does it always match
* the pthread_self() id on Linux. */
unsigned long long virThreadSelfID(void)
{
#if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid)
pid_t tid = syscall(SYS_gettid);
return tid;
#else
union {
unsigned long long l;
pthread_t t;
} u;
u.t = pthread_self();
return u.l;
#endif
}
/* For debugging use only; this result is not guaranteed unique if
* pthread_t is larger than a 64-bit pointer, nor does it always match
* the thread id of virThreadSelfID on Linux. */
unsigned long long virThreadID(virThreadPtr thread)
{
union {
unsigned long long l;
pthread_t t;
} u;
u.t = thread->thread;
return u.l;
}
void virThreadJoin(virThreadPtr thread)
{
pthread_join(thread->thread, NULL);
}
void virThreadCancel(virThreadPtr thread)
{
pthread_cancel(thread->thread);
}
int virThreadLocalInit(virThreadLocalPtr l,
virThreadLocalCleanup c)
{
int ret;
if ((ret = pthread_key_create(&l->key, c)) != 0) {
errno = ret;
return -1;
}
return 0;
}
void *virThreadLocalGet(virThreadLocalPtr l)
{
return pthread_getspecific(l->key);
}
int virThreadLocalSet(virThreadLocalPtr l, void *val)
{
int err = pthread_setspecific(l->key, val);
if (err) {
errno = err;
return -1;
}
return 0;
}

View File

@ -25,24 +25,57 @@
# include "internal.h"
# include "virerror.h"
# include <pthread.h>
typedef struct virMutex virMutex;
typedef virMutex *virMutexPtr;
struct virMutex {
pthread_mutex_t lock;
};
typedef struct virRWLock virRWLock;
typedef virRWLock *virRWLockPtr;
struct virRWLock {
pthread_rwlock_t lock;
};
typedef struct virCond virCond;
typedef virCond *virCondPtr;
struct virCond {
pthread_cond_t cond;
};
typedef struct virThreadLocal virThreadLocal;
typedef virThreadLocal *virThreadLocalPtr;
struct virThreadLocal {
pthread_key_t key;
};
typedef struct virThread virThread;
typedef virThread *virThreadPtr;
struct virThread {
pthread_t thread;
};
typedef struct virOnceControl virOnceControl;
typedef virOnceControl *virOnceControlPtr;
struct virOnceControl {
pthread_once_t once;
};
# define VIR_ONCE_CONTROL_INITIALIZER \
{ \
.once = PTHREAD_ONCE_INIT \
}
typedef void (*virOnceFunc)(void);
int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK;
@ -121,14 +154,6 @@ int virThreadLocalInit(virThreadLocalPtr l,
void *virThreadLocalGet(virThreadLocalPtr l);
int virThreadLocalSet(virThreadLocalPtr l, void*) ATTRIBUTE_RETURN_CHECK;
# ifdef WIN32
# include "virthreadwin32.h"
# elif defined HAVE_PTHREAD_MUTEXATTR_INIT
# include "virthreadpthread.h"
# else
# error "Either pthreads or Win32 threads are required"
# endif
/**
* VIR_ONCE_GLOBAL_INIT:

View File

@ -1,311 +0,0 @@
/*
* virthreadpthread.c: basic thread synchronization primitives
*
* Copyright (C) 2009-2011, 2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#include <config.h>
#include <unistd.h>
#include <inttypes.h>
#if HAVE_SYS_SYSCALL_H
# include <sys/syscall.h>
#endif
#include "viralloc.h"
/* Nothing special required for pthreads */
int virThreadInitialize(void)
{
return 0;
}
void virThreadOnExit(void)
{
}
int virOnce(virOnceControlPtr once, virOnceFunc init)
{
return pthread_once(&once->once, init);
}
int virMutexInit(virMutexPtr m)
{
int ret;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL);
ret = pthread_mutex_init(&m->lock, &attr);
pthread_mutexattr_destroy(&attr);
if (ret != 0) {
errno = ret;
return -1;
}
return 0;
}
int virMutexInitRecursive(virMutexPtr m)
{
int ret;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
ret = pthread_mutex_init(&m->lock, &attr);
pthread_mutexattr_destroy(&attr);
if (ret != 0) {
errno = ret;
return -1;
}
return 0;
}
void virMutexDestroy(virMutexPtr m)
{
pthread_mutex_destroy(&m->lock);
}
void virMutexLock(virMutexPtr m){
pthread_mutex_lock(&m->lock);
}
void virMutexUnlock(virMutexPtr m)
{
pthread_mutex_unlock(&m->lock);
}
int virRWLockInit(virRWLockPtr m)
{
int ret;
ret = pthread_rwlock_init(&m->lock, NULL);
if (ret != 0) {
errno = ret;
return -1;
}
return 0;
}
void virRWLockDestroy(virRWLockPtr m)
{
pthread_rwlock_destroy(&m->lock);
}
void virRWLockRead(virRWLockPtr m)
{
pthread_rwlock_rdlock(&m->lock);
}
void virRWLockWrite(virRWLockPtr m)
{
pthread_rwlock_wrlock(&m->lock);
}
void virRWLockUnlock(virRWLockPtr m)
{
pthread_rwlock_unlock(&m->lock);
}
int virCondInit(virCondPtr c)
{
int ret;
if ((ret = pthread_cond_init(&c->cond, NULL)) != 0) {
errno = ret;
return -1;
}
return 0;
}
int virCondDestroy(virCondPtr c)
{
int ret;
if ((ret = pthread_cond_destroy(&c->cond)) != 0) {
errno = ret;
return -1;
}
return 0;
}
int virCondWait(virCondPtr c, virMutexPtr m)
{
int ret;
if ((ret = pthread_cond_wait(&c->cond, &m->lock)) != 0) {
errno = ret;
return -1;
}
return 0;
}
int virCondWaitUntil(virCondPtr c, virMutexPtr m, unsigned long long whenms)
{
int ret;
struct timespec ts;
ts.tv_sec = whenms / 1000;
ts.tv_nsec = (whenms % 1000) * 1000;
if ((ret = pthread_cond_timedwait(&c->cond, &m->lock, &ts)) != 0) {
errno = ret;
return -1;
}
return 0;
}
void virCondSignal(virCondPtr c)
{
pthread_cond_signal(&c->cond);
}
void virCondBroadcast(virCondPtr c)
{
pthread_cond_broadcast(&c->cond);
}
struct virThreadArgs {
virThreadFunc func;
void *opaque;
};
static void *virThreadHelper(void *data)
{
struct virThreadArgs *args = data;
struct virThreadArgs local = *args;
/* Free args early, rather than tying it up during the entire thread. */
VIR_FREE(args);
local.func(local.opaque);
return NULL;
}
int virThreadCreate(virThreadPtr thread,
bool joinable,
virThreadFunc func,
void *opaque)
{
struct virThreadArgs *args;
pthread_attr_t attr;
int ret = -1;
int err;
if ((err = pthread_attr_init(&attr)) != 0)
goto cleanup;
if (VIR_ALLOC_QUIET(args) < 0) {
err = ENOMEM;
goto cleanup;
}
args->func = func;
args->opaque = opaque;
if (!joinable)
pthread_attr_setdetachstate(&attr, 1);
err = pthread_create(&thread->thread, &attr, virThreadHelper, args);
if (err != 0) {
VIR_FREE(args);
goto cleanup;
}
/* New thread owns 'args' in success case, so don't free */
ret = 0;
cleanup:
pthread_attr_destroy(&attr);
if (ret < 0)
errno = err;
return ret;
}
void virThreadSelf(virThreadPtr thread)
{
thread->thread = pthread_self();
}
bool virThreadIsSelf(virThreadPtr thread)
{
return pthread_equal(pthread_self(), thread->thread) ? true : false;
}
/* For debugging use only; this result is not guaranteed unique if
* pthread_t is larger than a 64-bit pointer, nor does it always match
* the pthread_self() id on Linux. */
unsigned long long virThreadSelfID(void)
{
#if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid)
pid_t tid = syscall(SYS_gettid);
return tid;
#else
union {
unsigned long long l;
pthread_t t;
} u;
u.t = pthread_self();
return u.l;
#endif
}
/* For debugging use only; this result is not guaranteed unique if
* pthread_t is larger than a 64-bit pointer, nor does it always match
* the thread id of virThreadSelfID on Linux. */
unsigned long long virThreadID(virThreadPtr thread)
{
union {
unsigned long long l;
pthread_t t;
} u;
u.t = thread->thread;
return u.l;
}
void virThreadJoin(virThreadPtr thread)
{
pthread_join(thread->thread, NULL);
}
void virThreadCancel(virThreadPtr thread)
{
pthread_cancel(thread->thread);
}
int virThreadLocalInit(virThreadLocalPtr l,
virThreadLocalCleanup c)
{
int ret;
if ((ret = pthread_key_create(&l->key, c)) != 0) {
errno = ret;
return -1;
}
return 0;
}
void *virThreadLocalGet(virThreadLocalPtr l)
{
return pthread_getspecific(l->key);
}
int virThreadLocalSet(virThreadLocalPtr l, void *val)
{
int err = pthread_setspecific(l->key, val);
if (err) {
errno = err;
return -1;
}
return 0;
}

View File

@ -1,53 +0,0 @@
/*
* virthreadpthread.c: basic thread synchronization primitives
*
* Copyright (C) 2009, 2011 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#include "internal.h"
#include <pthread.h>
struct virMutex {
pthread_mutex_t lock;
};
struct virRWLock {
pthread_rwlock_t lock;
};
struct virCond {
pthread_cond_t cond;
};
struct virThread {
pthread_t thread;
};
struct virThreadLocal {
pthread_key_t key;
};
struct virOnceControl {
pthread_once_t once;
};
#define VIR_ONCE_CONTROL_INITIALIZER \
{ \
.once = PTHREAD_ONCE_INIT \
}

View File

@ -1,415 +0,0 @@
/*
* virthreadwin32.c: basic thread synchronization primitives
*
* Copyright (C) 2009-2011, 2013 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#include <config.h>
#include <process.h>
#include "viralloc.h"
#define VIR_FROM_THIS VIR_FROM_NONE
struct virThreadLocalData {
DWORD key;
virThreadLocalCleanup cleanup;
};
typedef struct virThreadLocalData virThreadLocalData;
typedef virThreadLocalData *virThreadLocalDataPtr;
virMutex virThreadLocalLock;
size_t virThreadLocalCount = 0;
virThreadLocalDataPtr virThreadLocalList = NULL;
DWORD selfkey;
virThreadLocal virCondEvent;
void virCondEventCleanup(void *data);
int virThreadInitialize(void)
{
if (virMutexInit(&virThreadLocalLock) < 0)
return -1;
if (virThreadLocalInit(&virCondEvent, virCondEventCleanup) < 0)
return -1;
if ((selfkey = TlsAlloc()) == TLS_OUT_OF_INDEXES)
return -1;
return 0;
}
void virThreadOnExit(void)
{
size_t i;
virMutexLock(&virThreadLocalLock);
for (i = 0; i < virThreadLocalCount; i++) {
if (virThreadLocalList[i].cleanup) {
void *data = TlsGetValue(virThreadLocalList[i].key);
if (data) {
TlsSetValue(virThreadLocalList[i].key, NULL);
(virThreadLocalList[i].cleanup)(data);
}
}
}
virMutexUnlock(&virThreadLocalLock);
}
int virOnce(virOnceControlPtr once, virOnceFunc func)
{
if (!once->complete) {
if (InterlockedIncrement(&once->init) == 1) {
/* We're the first thread. */
func();
once->complete = 1;
} else {
/* We're a later thread. Decrement the init counter back
* to avoid overflow, then yield until the first thread
* marks that the function is complete. It is rare that
* multiple threads will be waiting here, and since each
* thread is yielding except the first, we should get out
* soon enough. */
InterlockedDecrement(&once->init);
while (!once->complete)
Sleep(0);
}
}
return 0;
}
int virMutexInit(virMutexPtr m)
{
return virMutexInitRecursive(m);
}
int virMutexInitRecursive(virMutexPtr m)
{
if (!(m->lock = CreateMutex(NULL, FALSE, NULL))) {
errno = ESRCH;
return -1;
}
return 0;
}
void virMutexDestroy(virMutexPtr m)
{
CloseHandle(m->lock);
}
void virMutexLock(virMutexPtr m)
{
WaitForSingleObject(m->lock, INFINITE);
}
void virMutexUnlock(virMutexPtr m)
{
ReleaseMutex(m->lock);
}
int virRWLockInit(virRWLockPtr m ATTRIBUTE_UNUSED)
{
errno = ENOSYS;
return -1;
}
void virRWLockDestroy(virRWLockPtr m ATTRIBUTE_UNUSED)
{}
void virRWLockRead(virRWLockPtr m ATTRIBUTE_UNUSED)
{}
void virRWLockWrite(virRWLockPtr m ATTRIBUTE_UNUSED)
{}
void virRWLockUnlock(virRWLockPtr m ATTRIBUTE_UNUSED)
{}
int virCondInit(virCondPtr c)
{
c->waiters = NULL;
if (virMutexInit(&c->lock) < 0)
return -1;
return 0;
}
int virCondDestroy(virCondPtr c)
{
if (c->waiters) {
errno = EINVAL;
return -1;
}
virMutexDestroy(&c->lock);
return 0;
}
void virCondEventCleanup(void *data)
{
HANDLE event = data;
CloseHandle(event);
}
int virCondWait(virCondPtr c, virMutexPtr m)
{
HANDLE event = virThreadLocalGet(&virCondEvent);
if (!event) {
event = CreateEvent(0, FALSE, FALSE, NULL);
if (!event) {
return -1;
}
if (virThreadLocalSet(&virCondEvent, event) < 0) {
CloseHandle(event);
return -1;
}
}
virMutexLock(&c->lock);
if (VIR_REALLOC_N(c->waiters, c->nwaiters + 1) < 0) {
virMutexUnlock(&c->lock);
return -1;
}
c->waiters[c->nwaiters] = event;
c->nwaiters++;
virMutexUnlock(&c->lock);
virMutexUnlock(m);
if (WaitForSingleObject(event, INFINITE) == WAIT_FAILED) {
virMutexLock(m);
errno = EINVAL;
return -1;
}
virMutexLock(m);
return 0;
}
int virCondWaitUntil(virCondPtr c ATTRIBUTE_UNUSED,
virMutexPtr m ATTRIBUTE_UNUSED,
unsigned long long whenms ATTRIBUTE_UNUSED)
{
/* FIXME: this function is currently only used by the QEMU driver that
* is not compiled on Windows, so it's okay for now to just
* miss an implementation */
return -1;
}
void virCondSignal(virCondPtr c)
{
virMutexLock(&c->lock);
if (c->nwaiters) {
HANDLE event = c->waiters[0];
if (c->nwaiters > 1)
memmove(c->waiters,
c->waiters + 1,
sizeof(c->waiters[0]) * (c->nwaiters-1));
if (VIR_REALLOC_N(c->waiters, c->nwaiters - 1) < 0) {
;
}
c->nwaiters--;
SetEvent(event);
}
virMutexUnlock(&c->lock);
}
void virCondBroadcast(virCondPtr c)
{
virMutexLock(&c->lock);
if (c->nwaiters) {
size_t i;
for (i = 0; i < c->nwaiters; i++) {
HANDLE event = c->waiters[i];
SetEvent(event);
}
VIR_FREE(c->waiters);
c->nwaiters = 0;
}
virMutexUnlock(&c->lock);
}
struct virThreadArgs {
virThreadFunc func;
void *opaque;
};
static void virThreadHelperDaemon(void *data)
{
struct virThreadArgs *args = data;
virThread self;
HANDLE handle = GetCurrentThread();
HANDLE process = GetCurrentProcess();
self.joinable = false;
DuplicateHandle(process, handle, process,
&self.thread, 0, FALSE,
DUPLICATE_SAME_ACCESS);
TlsSetValue(selfkey, &self);
args->func(args->opaque);
TlsSetValue(selfkey, NULL);
CloseHandle(self.thread);
VIR_FREE(args);
}
static unsigned int __stdcall virThreadHelperJoinable(void *data)
{
struct virThreadArgs *args = data;
virThread self;
HANDLE handle = GetCurrentThread();
HANDLE process = GetCurrentProcess();
self.joinable = true;
DuplicateHandle(process, handle, process,
&self.thread, 0, FALSE,
DUPLICATE_SAME_ACCESS);
TlsSetValue(selfkey, &self);
args->func(args->opaque);
TlsSetValue(selfkey, NULL);
CloseHandle(self.thread);
VIR_FREE(args);
return 0;
}
int virThreadCreate(virThreadPtr thread,
bool joinable,
virThreadFunc func,
void *opaque)
{
struct virThreadArgs *args;
uintptr_t ret;
if (VIR_ALLOC(args) < 0)
return -1;
args->func = func;
args->opaque = opaque;
thread->joinable = joinable;
if (joinable) {
ret = _beginthreadex(NULL, 0,
virThreadHelperJoinable,
args, 0, NULL);
if (ret == 0)
return -1;
} else {
ret = _beginthread(virThreadHelperDaemon,
0, args);
if (ret == -1L)
return -1;
}
thread->thread = (HANDLE)ret;
return 0;
}
void virThreadSelf(virThreadPtr thread)
{
virThreadPtr self = TlsGetValue(selfkey);
if (self == NULL) {
/* called on a thread not created by virThreadCreate, e.g. the main thread */
thread->thread = 0;
thread->joinable = false;
} else {
thread->thread = self->thread;
thread->joinable = self->joinable;
}
}
bool virThreadIsSelf(virThreadPtr thread)
{
virThread self;
virThreadSelf(&self);
return self.thread == thread->thread ? true : false;
}
/* For debugging use only; see comments in virthreadpthread.c. */
unsigned long long virThreadSelfID(void)
{
return GetCurrentThreadId();
}
/* For debugging use only; see comments in virthreadpthread.c. */
unsigned long long virThreadID(virThreadPtr thread)
{
return (intptr_t)thread->thread;
}
void virThreadJoin(virThreadPtr thread)
{
if (thread->joinable) {
WaitForSingleObject(thread->thread, INFINITE);
CloseHandle(thread->thread);
thread->thread = 0;
thread->joinable = false;
}
}
void virThreadCancel(virThreadPtr thread ATTRIBUTE_UNUSED)
{}
int virThreadLocalInit(virThreadLocalPtr l,
virThreadLocalCleanup c)
{
if ((l->key = TlsAlloc()) == TLS_OUT_OF_INDEXES) {
errno = ESRCH;
return -1;
}
TlsSetValue(l->key, NULL);
if (c) {
virMutexLock(&virThreadLocalLock);
if (VIR_REALLOC_N(virThreadLocalList,
virThreadLocalCount + 1) < 0)
return -1;
virThreadLocalList[virThreadLocalCount].key = l->key;
virThreadLocalList[virThreadLocalCount].cleanup = c;
virThreadLocalCount++;
virMutexUnlock(&virThreadLocalLock);
}
return 0;
}
void *virThreadLocalGet(virThreadLocalPtr l)
{
return TlsGetValue(l->key);
}
int virThreadLocalSet(virThreadLocalPtr l, void *val)
{
return TlsSetValue(l->key, val) == 0 ? -1 : 0;
}

View File

@ -1,57 +0,0 @@
/*
* virthreadwin32.h basic thread synchronization primitives
*
* Copyright (C) 2009, 2011-2012 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
#include "internal.h"
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
#include <windows.h>
struct virMutex {
HANDLE lock;
};
struct virRWLock {
bool ignored;
};
struct virCond {
virMutex lock;
size_t nwaiters;
HANDLE *waiters;
};
struct virThread {
HANDLE thread;
bool joinable;
};
struct virThreadLocal {
DWORD key;
};
struct virOnceControl {
volatile long init; /* 0 at startup, > 0 if init has started */
volatile long complete; /* 0 until first thread completes callback */
};
#define VIR_ONCE_CONTROL_INITIALIZER { 0, 0 }