[libvirt] PATCH: 2/25: Internal threads APIs + impl

Daniel P. Berrange berrange at redhat.com
Tue Jan 13 17:38:55 UTC 2009


The forthcoming set of patches will do alot of work relating to
threads, which requires mutual exclusion primitives. This will
include mutexes, condition variables and thread locals. We spefically
do not need the ability to actually create thread though, at least
not in the libvirt.so, only in the daemon.

We currently stub out all the mutex calls to no-ops when pthread.h
is missing. This is undesirable because it means we cannot clearly
state the thread safety rules for use of libvirt. Saying it is thread
safe on Linux, but not on Windows is IMHO not acceptable if we want
to have portability of apps using libvirt.

So this patch

 - Adds an internal API for mutexes, condition variables and
   thread locals
 - Implements this API for pthreads (covers Liunux, Solaris,
   and all BSD variants).
 - Implements this API for Win32 threads (covers Win32 :-)
 - Updates all code to use these internal APIs instead of
   pthread-XXX directly.
 - Adds missing mutex destroy calls from earlier patches.


The pthreads implementation is utterly trivial, since I purposely
designed the internal API to map 1-to-1 onto pthreads, albeit with
many unneccessary bits not exposed.

The Win32 implementatioin is more fun. Mutexes are trivial, I
just followed the libxml2/glib impls for that. Thread locals are
harder since Windows doesn't provide for any destructor to be
called when a thread exits, meaning there's a potential memory
leak. To address this I maintain some state for Win32 thread
locals, in particular the destructor callback. I then added a
DllMain() impl, which triggers upon thread-exit and explicitly
calls the destructors. This is what DBus/win32-pthread does
for thread locals. Finally condition variables are also hard
because there's no native condition variable impl on Windows.
I followed the GLib condition variable impl for this which uses
a queue of waiters, a mutex and a Win32 event for wakeup. Not
all that hard in the end.


I did consider whether we could use win32-pthreads, but there's
a few things I wasn't happy with. There are several different
binary DLLs you have to choose between depending on what behaviour
you want to C++ apps + exceptions. libvirt really shouldn't have
to make that choice. More annoyingly, its pthread.h #include's
its own config.h, so it seriously pollutes the global namespace
with configure settings that clash with our own. This is a show
stopper really. We also don't need the full ability to create
threads, so wrapping Win32 thread natively wasn't very hard
and that's what nearly every other app already does, so by using
Win32 threads directly we should get better interoperabiltiy
with other libraries doing the same.

 mingw32-libvirt.spec.in  |    1 
 po/POTFILES.in           |    1 
 proxy/Makefile.am        |    1 
 qemud/qemud.c            |   80 ++++++++++------
 qemud/qemud.h            |    7 -
 qemud/remote.c           |   72 +++++++--------
 src/Makefile.am          |    7 +
 src/datatypes.c          |   77 ++++++++--------
 src/datatypes.h          |    4 
 src/domain_conf.c        |   26 ++---
 src/domain_conf.h        |    3 
 src/internal.h           |   13 --
 src/libvirt.c            |   41 ++++++++
 src/libvirt_private.syms |   12 ++
 src/logging.c            |   14 +-
 src/lxc_conf.h           |    3 
 src/lxc_driver.c         |   10 +-
 src/network_conf.c       |   25 ++---
 src/network_conf.h       |    3 
 src/network_driver.c     |   12 +-
 src/node_device.c        |    4 
 src/node_device_conf.c   |   27 ++---
 src/node_device_conf.h   |    5 -
 src/node_device_devkit.c |    8 +
 src/node_device_hal.c    |    6 +
 src/openvz_conf.c        |   13 ++
 src/openvz_conf.h        |    3 
 src/openvz_driver.c      |    4 
 src/qemu_conf.h          |    3 
 src/qemu_driver.c        |   11 +-
 src/storage_conf.c       |   26 ++---
 src/storage_conf.h       |    5 -
 src/storage_driver.c     |   10 +-
 src/test.c               |   35 ++++---
 src/threads-pthread.c    |  117 ++++++++++++++++++++++++
 src/threads-pthread.h    |   36 +++++++
 src/threads-win32.c      |  223 +++++++++++++++++++++++++++++++++++++++++++++++
 src/threads-win32.h      |   39 ++++++++
 src/threads.c            |   34 +++++++
 src/threads.h            |   72 +++++++++++++++
 src/uml_conf.h           |    3 
 src/uml_driver.c         |   10 +-
 src/virsh.c              |    1 
 43 files changed, 871 insertions(+), 236 deletions(-)

diff --git a/po/POTFILES.in b/po/POTFILES.in
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -14,6 +14,7 @@ src/lxc_driver.c
 src/network_conf.c
 src/network_driver.c
 src/node_device.c
+src/node_device_conf.c
 src/openvz_conf.c
 src/openvz_driver.c
 src/proxy_internal.c
diff --git a/proxy/Makefile.am b/proxy/Makefile.am
--- a/proxy/Makefile.am
+++ b/proxy/Makefile.am
@@ -12,6 +12,7 @@ libexec_PROGRAMS = libvirt_proxy
 libvirt_proxy_SOURCES = libvirt_proxy.c @top_srcdir@/src/xend_internal.c \
 	    @top_srcdir@/src/xen_internal.c @top_srcdir@/src/virterror.c \
 	    @top_srcdir@/src/sexpr.c  \
+	    @top_srcdir@/src/threads.c  \
             @top_srcdir@/src/xs_internal.c @top_srcdir@/src/buf.c \
             @top_srcdir@/src/capabilities.c \
             @top_srcdir@/src/memory.c \
diff --git a/qemud/qemud.c b/qemud/qemud.c
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -268,11 +268,11 @@ qemudDispatchSignalEvent(int watch ATTRI
     siginfo_t siginfo;
     int ret;
 
-    pthread_mutex_lock(&server->lock);
+    virMutexLock(&server->lock);
 
     if (saferead(server->sigread, &siginfo, sizeof(siginfo)) != sizeof(siginfo)) {
         VIR_ERROR(_("Failed to read from signal pipe: %s"), strerror(errno));
-        pthread_mutex_unlock(&server->lock);
+        virMutexUnlock(&server->lock);
         return;
     }
 
@@ -300,7 +300,7 @@ qemudDispatchSignalEvent(int watch ATTRI
     if (ret != 0)
         server->shutdown = 1;
 
-    pthread_mutex_unlock(&server->lock);
+    virMutexUnlock(&server->lock);
 }
 
 int qemudSetCloseExec(int fd) {
@@ -688,9 +688,14 @@ static struct qemud_server *qemudInitial
         return NULL;
     }
 
-    if (pthread_mutex_init(&server->lock, NULL) != 0) {
+    if (virMutexInit(&server->lock) < 0) {
+        VIR_ERROR("%s", _("cannot initialize mutex"));
         VIR_FREE(server);
-        return NULL;
+    }
+    if (virCondInit(&server->job) < 0) {
+        VIR_ERROR("%s", _("cannot initialize condition variable"));
+        virMutexDestroy(&server->lock);
+        VIR_FREE(server);
     }
 
     server->sigread = sigread;
@@ -1117,8 +1122,11 @@ static int qemudDispatchServer(struct qe
 
     if (VIR_ALLOC(client) < 0)
         goto cleanup;
-    if (pthread_mutex_init(&client->lock, NULL) != 0)
+    if (virMutexInit(&client->lock) < 0) {
+        VIR_ERROR("%s", _("cannot initialize mutex"));
+        VIR_FREE(client);
         goto cleanup;
+    }
 
     client->magic = QEMUD_CLIENT_MAGIC;
     client->fd = fd;
@@ -1233,12 +1241,12 @@ static struct qemud_client *qemudPending
 {
     int i;
     for (i = 0 ; i < server->nclients ; i++) {
-        pthread_mutex_lock(&server->clients[i]->lock);
+        virMutexLock(&server->clients[i]->lock);
         if (server->clients[i]->mode == QEMUD_MODE_WAIT_DISPATCH) {
             /* Delibrately don't unlock client - caller wants the lock */
             return server->clients[i];
         }
-        pthread_mutex_unlock(&server->clients[i]->lock);
+        virMutexUnlock(&server->clients[i]->lock);
     }
     return NULL;
 }
@@ -1250,10 +1258,14 @@ static void *qemudWorker(void *data)
     while (1) {
         struct qemud_client *client;
         int len;
-        pthread_mutex_lock(&server->lock);
-        while ((client = qemudPendingJob(server)) == NULL)
-            pthread_cond_wait(&server->job, &server->lock);
-        pthread_mutex_unlock(&server->lock);
+        virMutexLock(&server->lock);
+        while ((client = qemudPendingJob(server)) == NULL) {
+            if (virCondWait(&server->job, &server->lock) < 0) {
+                virMutexUnlock(&server->lock);
+                return NULL;
+            }
+        }
+        virMutexUnlock(&server->lock);
 
         /* We own a locked client now... */
         client->mode = QEMUD_MODE_IN_DISPATCH;
@@ -1271,8 +1283,8 @@ static void *qemudWorker(void *data)
             qemudDispatchClientFailure(server, client);
 
         client->refs--;
-        pthread_mutex_unlock(&client->lock);
-        pthread_mutex_unlock(&server->lock);
+        virMutexUnlock(&client->lock);
+        virMutexUnlock(&server->lock);
     }
 }
 
@@ -1444,7 +1456,7 @@ static void qemudDispatchClientRead(stru
         if (qemudRegisterClientEvent(server, client, 1) < 0)
             qemudDispatchClientFailure(server, client);
 
-        pthread_cond_signal(&server->job);
+        virCondSignal(&server->job);
 
         break;
     }
@@ -1627,7 +1639,7 @@ qemudDispatchClientEvent(int watch, int 
     struct qemud_client *client = NULL;
     int i;
 
-    pthread_mutex_lock(&server->lock);
+    virMutexLock(&server->lock);
 
     for (i = 0 ; i < server->nclients ; i++) {
         if (server->clients[i]->watch == watch) {
@@ -1637,12 +1649,12 @@ qemudDispatchClientEvent(int watch, int 
     }
 
     if (!client) {
-        pthread_mutex_unlock(&server->lock);
+        virMutexUnlock(&server->lock);
         return;
     }
 
-    pthread_mutex_lock(&client->lock);
-    pthread_mutex_unlock(&server->lock);
+    virMutexLock(&client->lock);
+    virMutexUnlock(&server->lock);
 
     if (client->fd != fd)
         return;
@@ -1653,7 +1665,7 @@ qemudDispatchClientEvent(int watch, int 
         qemudDispatchClientRead(server, client);
     else
         qemudDispatchClientFailure(server, client);
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
 }
 
 static int qemudRegisterClientEvent(struct qemud_server *server,
@@ -1703,7 +1715,7 @@ qemudDispatchServerEvent(int watch, int 
     struct qemud_server *server = (struct qemud_server *)opaque;
     struct qemud_socket *sock;
 
-    pthread_mutex_lock(&server->lock);
+    virMutexLock(&server->lock);
 
     sock = server->sockets;
 
@@ -1717,7 +1729,7 @@ qemudDispatchServerEvent(int watch, int 
     if (sock && sock->fd == fd && events)
         qemudDispatchServer(server, sock);
 
-    pthread_mutex_unlock(&server->lock);
+    virMutexUnlock(&server->lock);
 }
 
 
@@ -1752,7 +1764,7 @@ static int qemudRunLoop(struct qemud_ser
     int timerid = -1;
     int ret = -1, i;
 
-    pthread_mutex_lock(&server->lock);
+    virMutexLock(&server->lock);
 
     server->nworkers = min_workers;
     if (VIR_ALLOC_N(server->workers, server->nworkers) < 0) {
@@ -1783,21 +1795,22 @@ static int qemudRunLoop(struct qemud_ser
             DEBUG("Scheduling shutdown timer %d", timerid);
         }
 
-        pthread_mutex_unlock(&server->lock);
+        virMutexUnlock(&server->lock);
         if (qemudOneLoop() < 0)
             break;
-        pthread_mutex_lock(&server->lock);
+        virMutexLock(&server->lock);
 
     reprocess:
         for (i = 0 ; i < server->nclients ; i++) {
             int inactive;
-            pthread_mutex_lock(&server->clients[i]->lock);
+            virMutexLock(&server->clients[i]->lock);
             inactive = server->clients[i]->fd == -1
                 && server->clients[i]->refs == 0;
-            pthread_mutex_unlock(&server->clients[i]->lock);
+            virMutexUnlock(&server->clients[i]->lock);
             if (inactive) {
                 if (server->clients[i]->conn)
                     virConnectClose(server->clients[i]->conn);
+                virMutexDestroy(&server->clients[i]->lock);
                 VIR_FREE(server->clients[i]);
                 server->nclients--;
                 if (i < server->nclients) {
@@ -1826,13 +1839,13 @@ static int qemudRunLoop(struct qemud_ser
 
     for (i = 0 ; i < server->nworkers ; i++) {
         pthread_t thread = server->workers[i];
-        pthread_mutex_unlock(&server->lock);
+        virMutexUnlock(&server->lock);
         pthread_join(thread, NULL);
-        pthread_mutex_lock(&server->lock);
+        virMutexLock(&server->lock);
     }
 
     free(server->workers);
-    pthread_mutex_unlock(&server->lock);
+    virMutexUnlock(&server->lock);
     return ret;
 }
 
@@ -1862,7 +1875,12 @@ static void qemudCleanup(struct qemud_se
 
     virStateCleanup();
 
-    free(server);
+    if (virCondDestroy(&server->job) < 0) {
+        ;
+    }
+    virMutexDestroy(&server->lock);
+
+    VIR_FREE(server);
 }
 
 /* Allocate an array of malloc'd strings from the config file, filename
diff --git a/qemud/qemud.h b/qemud/qemud.h
--- a/qemud/qemud.h
+++ b/qemud/qemud.h
@@ -46,6 +46,7 @@
 #include <rpc/xdr.h>
 #include "remote_protocol.h"
 #include "logging.h"
+#include "threads.h"
 
 #ifdef __GNUC__
 #ifdef HAVE_ANSIDECL_H
@@ -88,7 +89,7 @@ enum qemud_sock_type {
 
 /* Stores the per-client connection state */
 struct qemud_client {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     int magic;
 
@@ -149,8 +150,8 @@ struct qemud_socket {
 
 /* Main server state */
 struct qemud_server {
-    pthread_mutex_t lock;
-    pthread_cond_t job;
+    virMutex lock;
+    virCond job;
 
     int nworkers;
     pthread_t *workers;
diff --git a/qemud/remote.c b/qemud/remote.c
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -301,7 +301,7 @@ remoteDispatchClientRequest (struct qemu
 
     /* Call function. */
     conn = client->conn;
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
 
     /*
      * When the RPC handler is called:
@@ -315,9 +315,9 @@ remoteDispatchClientRequest (struct qemu
      */
     rv = (data->fn)(server, client, conn, &rerr, &args, &ret);
 
-    pthread_mutex_lock(&server->lock);
-    pthread_mutex_lock(&client->lock);
-    pthread_mutex_unlock(&server->lock);
+    virMutexLock(&server->lock);
+    virMutexLock(&client->lock);
+    virMutexUnlock(&server->lock);
 
     xdr_free (data->args_filter, (char*)&args);
 
@@ -412,9 +412,9 @@ remoteDispatchOpen (struct qemud_server 
         return -1;
     }
 
-    pthread_mutex_lock(&server->lock);
-    pthread_mutex_lock(&client->lock);
-    pthread_mutex_unlock(&server->lock);
+    virMutexLock(&server->lock);
+    virMutexLock(&client->lock);
+    virMutexUnlock(&server->lock);
 
     name = args->name ? *args->name : NULL;
 
@@ -433,7 +433,7 @@ remoteDispatchOpen (struct qemud_server 
         remoteDispatchConnError(rerr, NULL);
 
     rc = client->conn ? 0 : -1;
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
     return rc;
 }
 
@@ -450,13 +450,13 @@ remoteDispatchClose (struct qemud_server
                      remote_error *rerr ATTRIBUTE_UNUSED,
                      void *args ATTRIBUTE_UNUSED, void *ret ATTRIBUTE_UNUSED)
 {
-    pthread_mutex_lock(&server->lock);
-    pthread_mutex_lock(&client->lock);
-    pthread_mutex_unlock(&server->lock);
+    virMutexLock(&server->lock);
+    virMutexLock(&client->lock);
+    virMutexUnlock(&server->lock);
 
     client->closing = 1;
 
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
     return 0;
 }
 
@@ -2472,11 +2472,11 @@ remoteDispatchAuthList (struct qemud_ser
         remoteDispatchOOMError(rerr);
         return -1;
     }
-    pthread_mutex_lock(&server->lock);
-    pthread_mutex_lock(&client->lock);
-    pthread_mutex_unlock(&server->lock);
+    virMutexLock(&server->lock);
+    virMutexLock(&client->lock);
+    virMutexUnlock(&server->lock);
     ret->types.types_val[0] = client->auth;
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
 
     return 0;
 }
@@ -2535,9 +2535,9 @@ remoteDispatchAuthSaslInit (struct qemud
     socklen_t salen;
     char *localAddr, *remoteAddr;
 
-    pthread_mutex_lock(&server->lock);
-    pthread_mutex_lock(&client->lock);
-    pthread_mutex_unlock(&server->lock);
+    virMutexLock(&server->lock);
+    virMutexLock(&client->lock);
+    virMutexUnlock(&server->lock);
 
     REMOTE_DEBUG("Initialize SASL auth %d", client->fd);
     if (client->auth != REMOTE_AUTH_SASL ||
@@ -2663,13 +2663,13 @@ remoteDispatchAuthSaslInit (struct qemud
         goto authfail;
     }
 
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
     return 0;
 
 authfail:
     remoteDispatchAuthError(rerr);
 error:
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
     return -1;
 }
 
@@ -2787,9 +2787,9 @@ remoteDispatchAuthSaslStart (struct qemu
     unsigned int serveroutlen;
     int err;
 
-    pthread_mutex_lock(&server->lock);
-    pthread_mutex_lock(&client->lock);
-    pthread_mutex_unlock(&server->lock);
+    virMutexLock(&server->lock);
+    virMutexLock(&client->lock);
+    virMutexUnlock(&server->lock);
 
     REMOTE_DEBUG("Start SASL auth %d", client->fd);
     if (client->auth != REMOTE_AUTH_SASL ||
@@ -2851,13 +2851,13 @@ remoteDispatchAuthSaslStart (struct qemu
         client->auth = REMOTE_AUTH_NONE;
     }
 
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
     return 0;
 
 authfail:
     remoteDispatchAuthError(rerr);
 error:
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
     return -1;
 }
 
@@ -2874,9 +2874,9 @@ remoteDispatchAuthSaslStep (struct qemud
     unsigned int serveroutlen;
     int err;
 
-    pthread_mutex_lock(&server->lock);
-    pthread_mutex_lock(&client->lock);
-    pthread_mutex_unlock(&server->lock);
+    virMutexLock(&server->lock);
+    virMutexLock(&client->lock);
+    virMutexUnlock(&server->lock);
 
     REMOTE_DEBUG("Step SASL auth %d", client->fd);
     if (client->auth != REMOTE_AUTH_SASL ||
@@ -2939,13 +2939,13 @@ remoteDispatchAuthSaslStep (struct qemud
         client->auth = REMOTE_AUTH_NONE;
     }
 
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
     return 0;
 
 authfail:
     remoteDispatchAuthError(rerr);
 error:
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
     return -1;
 }
 
@@ -3011,9 +3011,9 @@ remoteDispatchAuthPolkit (struct qemud_s
     DBusError err;
     const char *action;
 
-    pthread_mutex_lock(&server->lock);
-    pthread_mutex_lock(&client->lock);
-    pthread_mutex_unlock(&server->lock);
+    virMutexLock(&server->lock);
+    virMutexLock(&client->lock);
+    virMutexUnlock(&server->lock);
 
     action = client->readonly ?
         "org.libvirt.unix.monitor" :
@@ -3091,12 +3091,12 @@ remoteDispatchAuthPolkit (struct qemud_s
     ret->complete = 1;
     client->auth = REMOTE_AUTH_NONE;
 
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
     return 0;
 
 authfail:
     remoteDispatchAuthError(rerr);
-    pthread_mutex_unlock(&client->lock);
+    virMutexUnlock(&client->lock);
     return -1;
 }
 
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -46,14 +46,19 @@ UTIL_SOURCES =							\
 		event.c event.h					\
 		hash.c hash.h					\
 		iptables.c iptables.h				\
+		logging.c logging.h				\
 		memory.c memory.h				\
 		qparams.c qparams.h				\
+		threads.c threads.h				\
+		threads-pthread.h				\
+		threads-win32.h					\
 		uuid.c uuid.h					\
 		util.c util.h					\
 		virterror.c virterror_internal.h		\
-		logging.c logging.h				\
 		xml.c xml.h
 
+EXTRA_DIST += threads-pthread.c threads-win32.c
+
 # Internal generic driver infrastructure
 DRIVER_SOURCES =						\
 		driver.c driver.h				\
diff --git a/src/datatypes.c b/src/datatypes.c
--- a/src/datatypes.c
+++ b/src/datatypes.c
@@ -123,6 +123,11 @@ virGetConnect(void) {
         virLibConnError(NULL, VIR_ERR_NO_MEMORY, _("allocating connection"));
         goto failed;
     }
+    if (virMutexInit(&ret->lock) < 0) {
+        VIR_FREE(ret);
+        goto failed;
+    }
+
     ret->magic = VIR_CONNECT_MAGIC;
     ret->driver = NULL;
     ret->networkDriver = NULL;
@@ -144,8 +149,6 @@ virGetConnect(void) {
     if (ret->nodeDevices == NULL)
         goto failed;
 
-    pthread_mutex_init(&ret->lock, NULL);
-
     ret->refs = 1;
     return(ret);
 
@@ -162,7 +165,7 @@ failed:
         if (ret->nodeDevices != NULL)
             virHashFree(ret->nodeDevices, (virHashDeallocator) virNodeDeviceFree);
 
-        pthread_mutex_destroy(&ret->lock);
+        virMutexDestroy(&ret->lock);
         VIR_FREE(ret);
     }
     return(NULL);
@@ -197,8 +200,8 @@ virReleaseConnect(virConnectPtr conn) {
 
     xmlFreeURI(conn->uri);
 
-    pthread_mutex_unlock(&conn->lock);
-    pthread_mutex_destroy(&conn->lock);
+    virMutexUnlock(&conn->lock);
+    virMutexDestroy(&conn->lock);
     VIR_FREE(conn);
 }
 
@@ -219,7 +222,7 @@ virUnrefConnect(virConnectPtr conn) {
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
-    pthread_mutex_lock(&conn->lock);
+    virMutexLock(&conn->lock);
     DEBUG("unref connection %p %d", conn, conn->refs);
     conn->refs--;
     refs = conn->refs;
@@ -228,7 +231,7 @@ virUnrefConnect(virConnectPtr conn) {
         /* Already unlocked mutex */
         return (0);
     }
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     return (refs);
 }
 
@@ -253,7 +256,7 @@ virGetDomain(virConnectPtr conn, const c
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(NULL);
     }
-    pthread_mutex_lock(&conn->lock);
+    virMutexLock(&conn->lock);
 
     /* TODO search by UUID first as they are better differenciators */
 
@@ -286,11 +289,11 @@ virGetDomain(virConnectPtr conn, const c
         DEBUG("Existing hash entry %p: refs now %d", ret, ret->refs+1);
     }
     ret->refs++;
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     return(ret);
 
  error:
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     if (ret != NULL) {
         VIR_FREE(ret->name);
         VIR_FREE(ret);
@@ -337,7 +340,7 @@ virReleaseDomain(virDomainPtr domain) {
         return;
     }
 
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
 }
 
 
@@ -358,7 +361,7 @@ virUnrefDomain(virDomainPtr domain) {
         virLibConnError(domain->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
-    pthread_mutex_lock(&domain->conn->lock);
+    virMutexLock(&domain->conn->lock);
     DEBUG("unref domain %p %s %d", domain, domain->name, domain->refs);
     domain->refs--;
     refs = domain->refs;
@@ -368,7 +371,7 @@ virUnrefDomain(virDomainPtr domain) {
         return (0);
     }
 
-    pthread_mutex_unlock(&domain->conn->lock);
+    virMutexUnlock(&domain->conn->lock);
     return (refs);
 }
 
@@ -393,7 +396,7 @@ virGetNetwork(virConnectPtr conn, const 
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(NULL);
     }
-    pthread_mutex_lock(&conn->lock);
+    virMutexLock(&conn->lock);
 
     /* TODO search by UUID first as they are better differenciators */
 
@@ -422,11 +425,11 @@ virGetNetwork(virConnectPtr conn, const 
         conn->refs++;
     }
     ret->refs++;
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     return(ret);
 
  error:
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     if (ret != NULL) {
         VIR_FREE(ret->name);
         VIR_FREE(ret);
@@ -473,7 +476,7 @@ virReleaseNetwork(virNetworkPtr network)
         return;
     }
 
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
 }
 
 
@@ -494,7 +497,7 @@ virUnrefNetwork(virNetworkPtr network) {
         virLibConnError(network->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
-    pthread_mutex_lock(&network->conn->lock);
+    virMutexLock(&network->conn->lock);
     DEBUG("unref network %p %s %d", network, network->name, network->refs);
     network->refs--;
     refs = network->refs;
@@ -504,7 +507,7 @@ virUnrefNetwork(virNetworkPtr network) {
         return (0);
     }
 
-    pthread_mutex_unlock(&network->conn->lock);
+    virMutexUnlock(&network->conn->lock);
     return (refs);
 }
 
@@ -530,7 +533,7 @@ virGetStoragePool(virConnectPtr conn, co
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(NULL);
     }
-    pthread_mutex_lock(&conn->lock);
+    virMutexLock(&conn->lock);
 
     /* TODO search by UUID first as they are better differenciators */
 
@@ -559,11 +562,11 @@ virGetStoragePool(virConnectPtr conn, co
         conn->refs++;
     }
     ret->refs++;
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     return(ret);
 
 error:
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     if (ret != NULL) {
         VIR_FREE(ret->name);
         VIR_FREE(ret);
@@ -606,7 +609,7 @@ virReleaseStoragePool(virStoragePoolPtr 
         return;
     }
 
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
 }
 
 
@@ -627,7 +630,7 @@ virUnrefStoragePool(virStoragePoolPtr po
         virLibConnError(pool->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
-    pthread_mutex_lock(&pool->conn->lock);
+    virMutexLock(&pool->conn->lock);
     DEBUG("unref pool %p %s %d", pool, pool->name, pool->refs);
     pool->refs--;
     refs = pool->refs;
@@ -637,7 +640,7 @@ virUnrefStoragePool(virStoragePoolPtr po
         return (0);
     }
 
-    pthread_mutex_unlock(&pool->conn->lock);
+    virMutexUnlock(&pool->conn->lock);
     return (refs);
 }
 
@@ -664,7 +667,7 @@ virGetStorageVol(virConnectPtr conn, con
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(NULL);
     }
-    pthread_mutex_lock(&conn->lock);
+    virMutexLock(&conn->lock);
 
     ret = (virStorageVolPtr) virHashLookup(conn->storageVols, key);
     if (ret == NULL) {
@@ -695,11 +698,11 @@ virGetStorageVol(virConnectPtr conn, con
         conn->refs++;
     }
     ret->refs++;
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     return(ret);
 
 error:
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     if (ret != NULL) {
         VIR_FREE(ret->name);
         VIR_FREE(ret->pool);
@@ -744,7 +747,7 @@ virReleaseStorageVol(virStorageVolPtr vo
         return;
     }
 
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
 }
 
 
@@ -765,7 +768,7 @@ virUnrefStorageVol(virStorageVolPtr vol)
         virLibConnError(vol->conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(-1);
     }
-    pthread_mutex_lock(&vol->conn->lock);
+    virMutexLock(&vol->conn->lock);
     DEBUG("unref vol %p %s %d", vol, vol->name, vol->refs);
     vol->refs--;
     refs = vol->refs;
@@ -775,7 +778,7 @@ virUnrefStorageVol(virStorageVolPtr vol)
         return (0);
     }
 
-    pthread_mutex_unlock(&vol->conn->lock);
+    virMutexUnlock(&vol->conn->lock);
     return (refs);
 }
 
@@ -801,7 +804,7 @@ virGetNodeDevice(virConnectPtr conn, con
         virLibConnError(conn, VIR_ERR_INVALID_ARG, __FUNCTION__);
         return(NULL);
     }
-    pthread_mutex_lock(&conn->lock);
+    virMutexLock(&conn->lock);
 
     ret = (virNodeDevicePtr) virHashLookup(conn->nodeDevices, name);
     if (ret == NULL) {
@@ -825,11 +828,11 @@ virGetNodeDevice(virConnectPtr conn, con
         conn->refs++;
     }
     ret->refs++;
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     return(ret);
 
 error:
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
     if (ret != NULL) {
         VIR_FREE(ret->name);
         VIR_FREE(ret);
@@ -872,7 +875,7 @@ virReleaseNodeDevice(virNodeDevicePtr de
         return;
     }
 
-    pthread_mutex_unlock(&conn->lock);
+    virMutexUnlock(&conn->lock);
 }
 
 
@@ -889,7 +892,7 @@ int
 virUnrefNodeDevice(virNodeDevicePtr dev) {
     int refs;
 
-    pthread_mutex_lock(&dev->conn->lock);
+    virMutexLock(&dev->conn->lock);
     DEBUG("unref dev %p %s %d", dev, dev->name, dev->refs);
     dev->refs--;
     refs = dev->refs;
@@ -899,6 +902,6 @@ virUnrefNodeDevice(virNodeDevicePtr dev)
         return (0);
     }
 
-    pthread_mutex_unlock(&dev->conn->lock);
+    virMutexUnlock(&dev->conn->lock);
     return (refs);
 }
diff --git a/src/datatypes.h b/src/datatypes.h
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -26,7 +26,7 @@
 
 #include "hash.h"
 #include "driver.h"
-
+#include "threads.h"
 
 /**
  * VIR_CONNECT_MAGIC:
@@ -125,7 +125,7 @@ struct _virConnect {
      * count of any virDomain/virNetwork object associated with
      * this connection
      */
-    PTHREAD_MUTEX_T (lock);
+    virMutex lock;
     virHashTablePtr domains;  /* hash table for known domains */
     virHashTablePtr networks; /* hash table for known domains */
     virHashTablePtr storagePools;/* hash table for known storage pools */
diff --git a/src/domain_conf.c b/src/domain_conf.c
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -433,6 +433,8 @@ void virDomainObjFree(virDomainObjPtr do
     VIR_FREE(dom->monitorpath);
     VIR_FREE(dom->vcpupids);
 
+    virMutexDestroy(&dom->lock);
+
     VIR_FREE(dom);
 }
 
@@ -471,7 +473,13 @@ virDomainObjPtr virDomainAssignDef(virCo
         return NULL;
     }
 
-    pthread_mutex_init(&domain->lock, NULL);
+    if (virMutexInit(&domain->lock) < 0) {
+        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                             "%s", _("cannot initialize mutex"));
+        VIR_FREE(domain);
+        return NULL;
+    }
+
     virDomainObjLock(domain);
     domain->state = VIR_DOMAIN_SHUTOFF;
     domain->def = def;
@@ -3660,26 +3668,14 @@ const char *virDomainDefDefaultEmulator(
 }
 
 
-#ifdef HAVE_PTHREAD_H
-
 void virDomainObjLock(virDomainObjPtr obj)
 {
-    pthread_mutex_lock(&obj->lock);
+    virMutexLock(&obj->lock);
 }
 
 void virDomainObjUnlock(virDomainObjPtr obj)
 {
-    pthread_mutex_unlock(&obj->lock);
+    virMutexUnlock(&obj->lock);
 }
 
-#else
-void virDomainObjLock(virDomainObjPtr obj ATTRIBUTE_UNUSED)
-{
-}
-
-void virDomainObjUnlock(virDomainObjPtr obj ATTRIBUTE_UNUSED)
-{
-}
-#endif
-
 #endif /* ! PROXY */
diff --git a/src/domain_conf.h b/src/domain_conf.h
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -31,6 +31,7 @@
 #include "internal.h"
 #include "capabilities.h"
 #include "util.h"
+#include "threads.h"
 
 /* Different types of hypervisor */
 /* NB: Keep in sync with virDomainVirtTypeToString impl */
@@ -456,7 +457,7 @@ struct _virDomainDef {
 typedef struct _virDomainObj virDomainObj;
 typedef virDomainObj *virDomainObjPtr;
 struct _virDomainObj {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     int stdin_fd;
     int stdout_fd;
diff --git a/src/internal.h b/src/internal.h
--- a/src/internal.h
+++ b/src/internal.h
@@ -12,19 +12,6 @@
 #include <sys/syslimits.h>
 #endif
 
-#ifdef HAVE_PTHREAD_H
-#include <pthread.h>
-#define PTHREAD_MUTEX_T(v) pthread_mutex_t v
-#else
-/* Mutex functions disappear if we don't have pthread. */
-#define PTHREAD_MUTEX_T(v) /*empty*/
-#define pthread_mutex_init(lk,p) /*empty*/
-#define pthread_mutex_destroy(lk) /*empty*/
-#define pthread_mutex_lock(lk) /*empty*/
-#define pthread_mutex_unlock(lk) /*empty*/
-#define pthread_sigmask(h, s, o) sigprocmask((h), (s), (o))
-#endif
-
 /* The library itself is allowed to use deprecated functions /
  * variables, so effectively undefine the deprecated attribute
  * which would otherwise be defined in libvirt.h.
diff --git a/src/libvirt.c b/src/libvirt.c
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -253,8 +253,12 @@ virInitialize(void)
 #endif
     if (initialized)
         return(0);
+
     initialized = 1;
 
+    if (virThreadInitialize() < 0)
+        return -1;
+
 #ifdef ENABLE_DEBUG
     debugEnv = getenv("LIBVIRT_DEBUG");
     if (debugEnv && *debugEnv && *debugEnv != '0') {
@@ -316,6 +320,43 @@ virInitialize(void)
     return(0);
 }
 
+#ifdef WIN32
+BOOL WINAPI
+DllMain (HINSTANCE instance, DWORD reason, LPVOID ignore);
+
+BOOL WINAPI
+DllMain (HINSTANCE instance ATTRIBUTE_UNUSED,
+         DWORD reason,
+         LPVOID ignore ATTRIBUTE_UNUSED)
+{
+    switch (reason) {
+    case DLL_PROCESS_ATTACH:
+        fprintf(stderr, "Initializing DLL\n");
+        virInitialize();
+        break;
+
+    case DLL_THREAD_ATTACH:
+        fprintf(stderr, "Thread start\n");
+        /* Nothing todo in libvirt yet */
+        break;
+
+    case DLL_THREAD_DETACH:
+        fprintf(stderr, "Thread exit\n");
+        /* Release per-thread local data */
+        virThreadOnExit();
+        break;
+
+    case DLL_PROCESS_DETACH:
+        fprintf(stderr, "Process exit\n");
+        /* Don't bother releasing per-thread data
+           since (hopefully) windows cleans up
+           everything on process exit */
+        break;
+    }
+
+    return TRUE;
+}
+#endif
 
 
 /**
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -261,6 +261,18 @@ virStoragePoolObjLock;
 virStoragePoolObjUnlock;
 
 
+# threads.h
+virMutexInit;
+virMutexDestroy;
+virMutexLock;
+virMutexUnlock;
+
+virCondInit;
+virCondDestroy;
+virCondWait;
+virCondSignal;
+virCondBroadcast;
+
 # util.h
 virFileReadAll;
 virStrToLong_i;
diff --git a/src/logging.c b/src/logging.c
--- a/src/logging.c
+++ b/src/logging.c
@@ -37,6 +37,7 @@
 #include "logging.h"
 #include "memory.h"
 #include "util.h"
+#include "threads.h"
 
 #ifdef ENABLE_DEBUG
 int debugFlag = 0;
@@ -129,15 +130,15 @@ static int virLogResetOutputs(void);
 /*
  * Logs accesses must be serialized though a mutex
  */
-PTHREAD_MUTEX_T(virLogMutex);
+virMutex virLogMutex;
 
 static void virLogLock(void)
 {
-    pthread_mutex_lock(&virLogMutex);
+    virMutexLock(&virLogMutex);
 }
 static void virLogUnlock(void)
 {
-    pthread_mutex_unlock(&virLogMutex);
+    virMutexUnlock(&virLogMutex);
 }
 
 
@@ -167,8 +168,11 @@ static int virLogInitialized = 0;
 int virLogStartup(void) {
     if (virLogInitialized)
         return(-1);
+
+    if (virMutexInit(&virLogMutex) < 0)
+        return -1;
+
     virLogInitialized = 1;
-    pthread_mutex_init(&virLogMutex, NULL);
     virLogLock();
     virLogLen = 0;
     virLogStart = 0;
@@ -214,7 +218,7 @@ void virLogShutdown(void) {
     virLogStart = 0;
     virLogEnd = 0;
     virLogUnlock();
-    pthread_mutex_destroy(&virLogMutex);
+    virMutexDestroy(&virLogMutex);
     virLogInitialized = 0;
 }
 
diff --git a/src/lxc_conf.h b/src/lxc_conf.h
--- a/src/lxc_conf.h
+++ b/src/lxc_conf.h
@@ -29,6 +29,7 @@
 #include "internal.h"
 #include "domain_conf.h"
 #include "capabilities.h"
+#include "threads.h"
 
 #define LXC_CONFIG_DIR SYSCONF_DIR "/libvirt/lxc"
 #define LXC_STATE_DIR LOCAL_STATE_DIR "/run/libvirt/lxc"
@@ -36,7 +37,7 @@
 
 typedef struct __lxc_driver lxc_driver_t;
 struct __lxc_driver {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     virCapsPtr caps;
 
diff --git a/src/lxc_driver.c b/src/lxc_driver.c
--- a/src/lxc_driver.c
+++ b/src/lxc_driver.c
@@ -57,11 +57,11 @@ static lxc_driver_t *lxc_driver = NULL;
 
 static void lxcDriverLock(lxc_driver_t *driver)
 {
-    pthread_mutex_lock(&driver->lock);
+    virMutexLock(&driver->lock);
 }
 static void lxcDriverUnlock(lxc_driver_t *driver)
 {
-    pthread_mutex_unlock(&driver->lock);
+    virMutexUnlock(&driver->lock);
 }
 
 
@@ -1135,7 +1135,10 @@ static int lxcStartup(void)
     if (VIR_ALLOC(lxc_driver) < 0) {
         return -1;
     }
-    pthread_mutex_init(&lxc_driver->lock, NULL);
+    if (virMutexInit(&lxc_driver->lock) < 0) {
+        VIR_FREE(lxc_driver);
+        return -1;
+    }
     lxcDriverLock(lxc_driver);
 
     /* Check that this is a container enabled kernel */
@@ -1228,6 +1231,7 @@ static int lxcShutdown(void)
     VIR_FREE(lxc_driver->stateDir);
     VIR_FREE(lxc_driver->logDir);
     lxcDriverUnlock(lxc_driver);
+    virMutexDestroy(&lxc_driver->lock);
     VIR_FREE(lxc_driver);
     lxc_driver = NULL;
 
diff --git a/src/network_conf.c b/src/network_conf.c
--- a/src/network_conf.c
+++ b/src/network_conf.c
@@ -126,6 +126,8 @@ void virNetworkObjFree(virNetworkObjPtr 
     VIR_FREE(net->configFile);
     VIR_FREE(net->autostartLink);
 
+    virMutexDestroy(&net->lock);
+
     VIR_FREE(net);
 }
 
@@ -163,7 +165,12 @@ virNetworkObjPtr virNetworkAssignDef(vir
         virNetworkReportError(conn, VIR_ERR_NO_MEMORY, NULL);
         return NULL;
     }
-    pthread_mutex_init(&network->lock, NULL);
+    if (virMutexInit(&network->lock) < 0) {
+        virNetworkReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "%s", _("cannot initialize mutex"));
+        VIR_FREE(network);
+        return NULL;
+    }
     virNetworkObjLock(network);
     network->def = def;
 
@@ -823,25 +830,13 @@ int virNetworkDeleteConfig(virConnectPtr
     return 0;
 }
 
-#ifdef HAVE_PTHREAD_H
-
 void virNetworkObjLock(virNetworkObjPtr obj)
 {
-    pthread_mutex_lock(&obj->lock);
+    virMutexLock(&obj->lock);
 }
 
 void virNetworkObjUnlock(virNetworkObjPtr obj)
 {
-    pthread_mutex_unlock(&obj->lock);
+    virMutexUnlock(&obj->lock);
 }
 
-#else
-void virNetworkObjLock(virNetworkObjPtr obj ATTRIBUTE_UNUSED)
-{
-}
-
-void virNetworkObjUnlock(virNetworkObjPtr obj ATTRIBUTE_UNUSED)
-{
-}
-
-#endif
diff --git a/src/network_conf.h b/src/network_conf.h
--- a/src/network_conf.h
+++ b/src/network_conf.h
@@ -29,6 +29,7 @@
 #include <libxml/xpath.h>
 
 #include "internal.h"
+#include "threads.h"
 
 /* 2 possible types of forwarding */
 enum virNetworkForwardType {
@@ -82,7 +83,7 @@ struct _virNetworkDef {
 typedef struct _virNetworkObj virNetworkObj;
 typedef virNetworkObj *virNetworkObjPtr;
 struct _virNetworkObj {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     pid_t dnsmasqPid;
     unsigned int active : 1;
diff --git a/src/network_driver.c b/src/network_driver.c
--- a/src/network_driver.c
+++ b/src/network_driver.c
@@ -59,7 +59,7 @@
 
 /* Main driver state */
 struct network_driver {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     virNetworkObjList networks;
 
@@ -73,11 +73,11 @@ struct network_driver {
 
 static void networkDriverLock(struct network_driver *driver)
 {
-    pthread_mutex_lock(&driver->lock);
+    virMutexLock(&driver->lock);
 }
 static void networkDriverUnlock(struct network_driver *driver)
 {
-    pthread_mutex_unlock(&driver->lock);
+    virMutexUnlock(&driver->lock);
 }
 
 static int networkShutdown(void);
@@ -134,7 +134,10 @@ networkStartup(void) {
     if (VIR_ALLOC(driverState) < 0)
         goto error;
 
-    pthread_mutex_init(&driverState->lock, NULL);
+    if (virMutexInit(&driverState->lock) < 0) {
+        VIR_FREE(driverState);
+        goto error;
+    }
     networkDriverLock(driverState);
 
     if (!uid) {
@@ -290,6 +293,7 @@ networkShutdown(void) {
         iptablesContextFree(driverState->iptables);
 
     networkDriverUnlock(driverState);
+    virMutexDestroy(&driverState->lock);
 
     VIR_FREE(driverState);
 
diff --git a/src/node_device.c b/src/node_device.c
--- a/src/node_device.c
+++ b/src/node_device.c
@@ -48,12 +48,12 @@ static int dev_has_cap(const virNodeDevi
 void nodeDeviceLock(virDeviceMonitorStatePtr driver)
 {
     DEBUG("LOCK node %p", driver);
-    pthread_mutex_lock(&driver->lock);
+    virMutexLock(&driver->lock);
 }
 void nodeDeviceUnlock(virDeviceMonitorStatePtr driver)
 {
     DEBUG("UNLOCK node %p", driver);
-    pthread_mutex_unlock(&driver->lock);
+    virMutexUnlock(&driver->lock);
 }
 
 static int nodeNumOfDevices(virConnectPtr conn,
diff --git a/src/node_device_conf.c b/src/node_device_conf.c
--- a/src/node_device_conf.c
+++ b/src/node_device_conf.c
@@ -99,6 +99,8 @@ void virNodeDeviceObjFree(virNodeDeviceO
     if (dev->privateFree)
         (*dev->privateFree)(dev->privateData);
 
+    virMutexDestroy(&dev->lock);
+
     VIR_FREE(dev);
 }
 
@@ -128,12 +130,18 @@ virNodeDeviceObjPtr virNodeDeviceAssignD
         return NULL;
     }
 
-    pthread_mutex_init(&device->lock, NULL);
+    if (virMutexInit(&device->lock) < 0) {
+        virNodeDeviceReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("cannot initialize mutex"));
+        VIR_FREE(device);
+        return NULL;
+    }
     virNodeDeviceObjLock(device);
     device->def = def;
 
     if (VIR_REALLOC_N(devs->objs, devs->count+1) < 0) {
         device->def = NULL;
+        virNodeDeviceObjUnlock(device);
         virNodeDeviceObjFree(device);
         virNodeDeviceReportError(conn, VIR_ERR_NO_MEMORY, NULL);
         return NULL;
@@ -408,26 +416,13 @@ void virNodeDevCapsDefFree(virNodeDevCap
 }
 
 
-#ifdef HAVE_PTHREAD_H
-
 void virNodeDeviceObjLock(virNodeDeviceObjPtr obj)
 {
-    pthread_mutex_lock(&obj->lock);
+    virMutexLock(&obj->lock);
 }
 
 void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj)
 {
-    pthread_mutex_unlock(&obj->lock);
+    virMutexUnlock(&obj->lock);
 }
 
-#else
-
-void virNodeDeviceObjLock(virNodeDeviceObjPtr obj ATTRIBUTE_UNUSED)
-{
-}
-
-void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj ATTRIBUTE_UNUSED)
-{
-}
-
-#endif
diff --git a/src/node_device_conf.h b/src/node_device_conf.h
--- a/src/node_device_conf.h
+++ b/src/node_device_conf.h
@@ -26,6 +26,7 @@
 
 #include "internal.h"
 #include "util.h"
+#include "threads.h"
 
 enum virNodeDevCapType {
     /* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */
@@ -142,7 +143,7 @@ struct _virNodeDeviceDef {
 typedef struct _virNodeDeviceObj virNodeDeviceObj;
 typedef virNodeDeviceObj *virNodeDeviceObjPtr;
 struct _virNodeDeviceObj {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     virNodeDeviceDefPtr def;		/* device definition */
     void *privateData;			/* driver-specific private data */
@@ -160,7 +161,7 @@ struct _virNodeDeviceObjList {
 typedef struct _virDeviceMonitorState virDeviceMonitorState;
 typedef virDeviceMonitorState *virDeviceMonitorStatePtr;
 struct _virDeviceMonitorState {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     virNodeDeviceObjList devs;		/* currently-known devices */
     void *privateData;			/* driver-specific private data */
diff --git a/src/node_device_devkit.c b/src/node_device_devkit.c
--- a/src/node_device_devkit.c
+++ b/src/node_device_devkit.c
@@ -298,7 +298,10 @@ static int devkitDeviceMonitorStartup(vo
     if (VIR_ALLOC(driverState) < 0)
         return -1;
 
-    pthread_mutex_init(&driverState->lock, NULL);
+    if (virMutexInit(&driverState->lock) < 0) {
+        VIR_FREE(driverState);
+        return -1;
+    }
 
     g_type_init();
 
@@ -375,7 +378,8 @@ static int devkitDeviceMonitorShutdown(v
         virNodeDeviceObjListFree(&driverState->devs);
         if (devkit_client)
             g_object_unref(devkit_client);
-        nodeDeviceLock(driverState);
+        nodeDeviceUnlock(driverState);
+        virMutexDestroy(&driveState->lock);
         VIR_FREE(driverState);
         return 0;
     }
diff --git a/src/node_device_hal.c b/src/node_device_hal.c
--- a/src/node_device_hal.c
+++ b/src/node_device_hal.c
@@ -678,7 +678,10 @@ static int halDeviceMonitorStartup(void)
     if (VIR_ALLOC(driverState) < 0)
         return -1;
 
-    pthread_mutex_init(&driverState->lock, NULL);
+    if (virMutexInit(&driverState->lock) < 0) {
+        VIR_FREE(driverState);
+        return -1;
+    }
     nodeDeviceLock(driverState);
 
     /* Allocate and initialize a new HAL context */
@@ -770,6 +773,7 @@ static int halDeviceMonitorShutdown(void
         (void)libhal_ctx_shutdown(hal_ctx, NULL);
         (void)libhal_ctx_free(hal_ctx);
         nodeDeviceUnlock(driverState);
+        virMutexDestroy(&driverState->lock);
         VIR_FREE(driverState);
         return 0;
     }
diff --git a/src/openvz_conf.c b/src/openvz_conf.c
--- a/src/openvz_conf.c
+++ b/src/openvz_conf.c
@@ -392,11 +392,18 @@ int openvzLoadDomains(struct openvz_driv
             goto cleanup;
         }
 
-        if (VIR_ALLOC(dom) < 0 ||
-            VIR_ALLOC(dom->def) < 0)
+        if (VIR_ALLOC(dom) < 0)
             goto no_memory;
 
-        pthread_mutex_init(&dom->lock, NULL);
+        if (virMutexInit(&dom->lock) < 0) {
+            openvzError(NULL, VIR_ERR_INTERNAL_ERROR,
+                        "%s", _("cannot initialize mutex"));
+            VIR_FREE(dom);
+            goto cleanup;
+        }
+
+        if (VIR_ALLOC(dom->def) < 0)
+            goto no_memory;
 
         if (STREQ(status, "stopped"))
             dom->state = VIR_DOMAIN_SHUTOFF;
diff --git a/src/openvz_conf.h b/src/openvz_conf.h
--- a/src/openvz_conf.h
+++ b/src/openvz_conf.h
@@ -30,6 +30,7 @@
 
 #include "internal.h"
 #include "domain_conf.h"
+#include "threads.h"
 
 enum { OPENVZ_WARN, OPENVZ_ERR };
 
@@ -53,7 +54,7 @@ enum { OPENVZ_WARN, OPENVZ_ERR };
 #define VZCTL_BRIDGE_MIN_VERSION ((3 * 1000 * 1000) + (0 * 1000) + 22 + 1)
 
 struct openvz_driver {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     virCapsPtr caps;
     virDomainObjList domains;
diff --git a/src/openvz_driver.c b/src/openvz_driver.c
--- a/src/openvz_driver.c
+++ b/src/openvz_driver.c
@@ -70,12 +70,12 @@ static int openvzDomainSetVcpusInternal(
 
 static void openvzDriverLock(struct openvz_driver *driver)
 {
-    pthread_mutex_lock(&driver->lock);
+    virMutexLock(&driver->lock);
 }
 
 static void openvzDriverUnlock(struct openvz_driver *driver)
 {
-    pthread_mutex_unlock(&driver->lock);
+    virMutexUnlock(&driver->lock);
 }
 
 struct openvz_driver ovz_driver;
diff --git a/src/qemu_conf.h b/src/qemu_conf.h
--- a/src/qemu_conf.h
+++ b/src/qemu_conf.h
@@ -32,6 +32,7 @@
 #include "network_conf.h"
 #include "domain_conf.h"
 #include "domain_event.h"
+#include "threads.h"
 
 #define qemudDebug(fmt, ...) do {} while(0)
 
@@ -51,7 +52,7 @@ enum qemud_cmd_flags {
 
 /* Main driver state */
 struct qemud_driver {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     unsigned int qemuVersion;
     int nextvmid;
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -78,11 +78,11 @@ static int qemudShutdown(void);
 
 static void qemuDriverLock(struct qemud_driver *driver)
 {
-    pthread_mutex_lock(&driver->lock);
+    virMutexLock(&driver->lock);
 }
 static void qemuDriverUnlock(struct qemud_driver *driver)
 {
-    pthread_mutex_unlock(&driver->lock);
+    virMutexUnlock(&driver->lock);
 }
 
 static int qemudSetCloseExec(int fd) {
@@ -273,7 +273,11 @@ qemudStartup(void) {
     if (VIR_ALLOC(qemu_driver) < 0)
         return -1;
 
-    pthread_mutex_init(&qemu_driver->lock, NULL);
+    if (virMutexInit(&qemu_driver->lock) < 0) {
+        qemudLog(QEMUD_ERROR, "%s", _("cannot initialize mutex"));
+        VIR_FREE(qemu_driver);
+        return -1;
+    }
     qemuDriverLock(qemu_driver);
 
     /* Don't have a dom0 so start from 1 */
@@ -482,6 +486,7 @@ qemudShutdown(void) {
         brShutdown(qemu_driver->brctl);
 
     qemuDriverUnlock(qemu_driver);
+    virMutexDestroy(&qemu_driver->lock);
     VIR_FREE(qemu_driver);
 
     return 0;
diff --git a/src/storage_conf.c b/src/storage_conf.c
--- a/src/storage_conf.c
+++ b/src/storage_conf.c
@@ -297,6 +297,9 @@ virStoragePoolObjFree(virStoragePoolObjP
 
     VIR_FREE(obj->configFile);
     VIR_FREE(obj->autostartLink);
+
+    virMutexDestroy(&obj->lock);
+
     VIR_FREE(obj);
 }
 
@@ -1259,13 +1262,19 @@ virStoragePoolObjAssignDef(virConnectPtr
         return NULL;
     }
 
-    pthread_mutex_init(&pool->lock, NULL);
+    if (virMutexInit(&pool->lock) < 0) {
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              "%s", _("cannot initialize mutex"));
+        VIR_FREE(pool);
+        return NULL;
+    }
     virStoragePoolObjLock(pool);
     pool->active = 0;
     pool->def = def;
 
     if (VIR_REALLOC_N(pools->objs, pools->count+1) < 0) {
         pool->def = NULL;
+        virStoragePoolObjUnlock(pool);
         virStoragePoolObjFree(pool);
         virStorageReportError(conn, VIR_ERR_NO_MEMORY, NULL);
         return NULL;
@@ -1530,23 +1539,12 @@ char *virStoragePoolSourceListFormat(vir
 }
 
 
-#ifdef HAVE_PTHREAD_H
-
 void virStoragePoolObjLock(virStoragePoolObjPtr obj)
 {
-    pthread_mutex_lock(&obj->lock);
+    virMutexLock(&obj->lock);
 }
 
 void virStoragePoolObjUnlock(virStoragePoolObjPtr obj)
 {
-    pthread_mutex_unlock(&obj->lock);
+    virMutexUnlock(&obj->lock);
 }
-#else
-void virStoragePoolObjLock(virStoragePoolObjPtr obj ATTRIBUTE_UNUSED)
-{
-}
-
-void virStoragePoolObjUnlock(virStoragePoolObjPtr obj ATTRIBUTE_UNUSED)
-{
-}
-#endif
diff --git a/src/storage_conf.h b/src/storage_conf.h
--- a/src/storage_conf.h
+++ b/src/storage_conf.h
@@ -26,6 +26,7 @@
 
 #include "internal.h"
 #include "util.h"
+#include "threads.h"
 
 /* Shared structs */
 
@@ -223,7 +224,7 @@ typedef struct _virStoragePoolObj virSto
 typedef virStoragePoolObj *virStoragePoolObjPtr;
 
 struct _virStoragePoolObj {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     char *configFile;
     char *autostartLink;
@@ -250,7 +251,7 @@ typedef struct _virStorageDriverState vi
 typedef virStorageDriverState *virStorageDriverStatePtr;
 
 struct _virStorageDriverState {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     virStoragePoolObjList pools;
 
diff --git a/src/storage_driver.c b/src/storage_driver.c
--- a/src/storage_driver.c
+++ b/src/storage_driver.c
@@ -49,11 +49,11 @@ static int storageDriverShutdown(void);
 
 static void storageDriverLock(virStorageDriverStatePtr driver)
 {
-    pthread_mutex_lock(&driver->lock);
+    virMutexLock(&driver->lock);
 }
 static void storageDriverUnlock(virStorageDriverStatePtr driver)
 {
-    pthread_mutex_unlock(&driver->lock);
+    virMutexUnlock(&driver->lock);
 }
 
 static void
@@ -113,7 +113,10 @@ storageDriverStartup(void) {
     if (VIR_ALLOC(driverState) < 0)
         return -1;
 
-    pthread_mutex_init(&driverState->lock, NULL);
+    if (virMutexInit(&driverState->lock) < 0) {
+        VIR_FREE(driverState);
+        return -1;
+    }
     storageDriverLock(driverState);
 
     if (!uid) {
@@ -266,6 +269,7 @@ storageDriverShutdown(void) {
     VIR_FREE(driverState->configDir);
     VIR_FREE(driverState->autostartDir);
     storageDriverUnlock(driverState);
+    virMutexDestroy(&driverState->lock);
     VIR_FREE(driverState);
 
     return 0;
diff --git a/src/test.c b/src/test.c
--- a/src/test.c
+++ b/src/test.c
@@ -44,6 +44,7 @@
 #include "domain_conf.h"
 #include "storage_conf.h"
 #include "xml.h"
+#include "threads.h"
 
 #define MAX_CPUS 128
 
@@ -58,7 +59,7 @@ typedef struct _testCell *testCellPtr;
 #define MAX_CELLS 128
 
 struct _testConn {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     char path[PATH_MAX];
     int nextDomID;
@@ -93,20 +94,15 @@ static const virNodeInfo defaultNodeInfo
         virReportErrorHelper(conn, VIR_FROM_TEST, code, __FILE__, \
                                __FUNCTION__, __LINE__, fmt)
 
-#ifdef HAVE_THREAD_H
 static void testDriverLock(testConnPtr driver)
 {
-    pthread_mutex_lock(&driver->lock);
+    virMutexLock(&driver->lock);
 }
 
 static void testDriverUnlock(testConnPtr driver)
 {
-    pthread_mutex_unlock(&driver->lock);
+    virMutexUnlock(&driver->lock);
 }
-#else
-static void testDriverLock(testConnPtr driver ATTRIBUTE_UNUSED) {}
-static void testDriverUnlock(testConnPtr driver ATTRIBUTE_UNUSED) {}
-#endif
 
 static virCapsPtr
 testBuildCapabilities(virConnectPtr conn) {
@@ -216,9 +212,15 @@ static int testOpenDefault(virConnectPtr
         testError(conn, VIR_ERR_NO_MEMORY, "testConn");
         return VIR_DRV_OPEN_ERROR;
     }
+    if (virMutexInit(&privconn->lock) < 0) {
+        testError(conn, VIR_ERR_INTERNAL_ERROR,
+                  "%s", _("cannot initialize mutex"));
+        VIR_FREE(privconn);
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    testDriverLock(privconn);
     conn->privateData = privconn;
-    pthread_mutex_init(&privconn->lock, NULL);
-    testDriverLock(privconn);
 
     if (gettimeofday(&tv, NULL) < 0) {
         testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of day"));
@@ -282,6 +284,7 @@ static int testOpenDefault(virConnectPtr
     virStoragePoolObjUnlock(poolobj);
 
     testDriverUnlock(privconn);
+
     return VIR_DRV_OPEN_SUCCESS;
 
 error:
@@ -290,6 +293,7 @@ error:
     virStoragePoolObjListFree(&privconn->pools);
     virCapabilitiesFree(privconn->caps);
     testDriverUnlock(privconn);
+    conn->privateData = NULL;
     VIR_FREE(privconn);
     return VIR_DRV_OPEN_ERROR;
 }
@@ -335,9 +339,15 @@ static int testOpenFromFile(virConnectPt
         testError(NULL, VIR_ERR_NO_MEMORY, "testConn");
         return VIR_DRV_OPEN_ERROR;
     }
+    if (virMutexInit(&privconn->lock) < 0) {
+        testError(conn, VIR_ERR_INTERNAL_ERROR,
+                  "%s", _("cannot initialize mutex"));
+        VIR_FREE(privconn);
+        return VIR_DRV_OPEN_ERROR;
+    }
+
+    testDriverLock(privconn);
     conn->privateData = privconn;
-    pthread_mutex_init(&privconn->lock, NULL);
-    testDriverLock(privconn);
 
     if (!(privconn->caps = testBuildCapabilities(conn)))
         goto error;
@@ -643,6 +653,7 @@ static int testClose(virConnectPtr conn)
     virNetworkObjListFree(&privconn->networks);
     virStoragePoolObjListFree(&privconn->pools);
     testDriverUnlock(privconn);
+    virMutexDestroy(&privconn->lock);
 
     VIR_FREE (privconn);
     conn->privateData = NULL;
diff --git a/src/threads-pthread.c b/src/threads-pthread.c
new file mode 100644
--- /dev/null
+++ b/src/threads-pthread.c
@@ -0,0 +1,117 @@
+/*
+ * threads-pthread.c: basic thread synchronization primitives
+ *
+ * Copyright (C) 2008 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#include <config.h>
+
+
+/* Nothing special required for pthreads */
+int virThreadInitialize(void)
+{
+    return 0;
+}
+
+void virThreadOnExit(void)
+{
+}
+
+
+int virMutexInit(virMutexPtr m)
+{
+    if (pthread_mutex_init(&m->lock, NULL) != 0) {
+        errno = EINVAL;
+        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 virCondInit(virCondPtr c)
+{
+    if (pthread_cond_init(&c->cond, NULL) != 0) {
+        errno = EINVAL;
+        return -1;
+    }
+    return 0;
+}
+
+int virCondDestroy(virCondPtr c)
+{
+    if (pthread_cond_destroy(&c->cond) != 0) {
+        errno = EINVAL;
+        return -1;
+    }
+    return 0;
+}
+
+int virCondWait(virCondPtr c, virMutexPtr m)
+{
+    if (pthread_cond_wait(&c->cond, &m->lock) != 0) {
+        errno = EINVAL;
+        return -1;
+    }
+    return 0;
+}
+
+void virCondSignal(virCondPtr c)
+{
+    pthread_cond_signal(&c->cond);
+}
+
+void virCondBroadcast(virCondPtr c)
+{
+    pthread_cond_broadcast(&c->cond);
+}
+
+
+int virThreadLocalInit(virThreadLocalPtr l,
+                       virThreadLocalCleanup c)
+{
+    if (pthread_key_create(&l->key, c) != 0) {
+        errno = EINVAL;
+        return -1;
+    }
+    return 0;
+}
+
+void *virThreadLocalGet(virThreadLocalPtr l)
+{
+    return pthread_getspecific(l->key);
+}
+
+void virThreadLocalSet(virThreadLocalPtr l, void *val)
+{
+    pthread_setspecific(l->key, val);
+}
diff --git a/src/threads-pthread.h b/src/threads-pthread.h
new file mode 100644
--- /dev/null
+++ b/src/threads-pthread.h
@@ -0,0 +1,36 @@
+/*
+ * threads.c: basic thread synchronization primitives
+ *
+ * Copyright (C) 2008 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#include "internal.h"
+
+#include <pthread.h>
+
+struct virMutex {
+    pthread_mutex_t lock;
+};
+
+struct virCond {
+    pthread_cond_t cond;
+};
+
+struct virThreadLocal {
+    pthread_key_t key;
+};
diff --git a/src/threads-win32.c b/src/threads-win32.c
new file mode 100644
--- /dev/null
+++ b/src/threads-win32.c
@@ -0,0 +1,223 @@
+/*
+ * threads-win32.c: basic thread synchronization primitives
+ *
+ * Copyright (C) 2008 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#include <config.h>
+
+#include "memory.h"
+
+struct virThreadLocalData {
+    DWORD key;
+    virThreadLocalCleanup cleanup;
+};
+typedef struct virThreadLocalData virThreadLocalData;
+typedef virThreadLocalData *virThreadLocalDataPtr;
+
+virMutex virThreadLocalLock;
+unsigned int virThreadLocalCount = 0;
+virThreadLocalDataPtr virThreadLocalList = NULL;
+
+
+virThreadLocal virCondEvent;
+
+void virCondEventCleanup(void *data);
+
+int virThreadInitialize(void)
+{
+    virMutexInit(&virThreadLocalLock);
+    virThreadLocalInit(&virCondEvent, virCondEventCleanup);
+
+    return 0;
+}
+
+void virThreadOnExit(void)
+{
+    unsigned int 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 virMutexInit(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 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;
+        }
+        virThreadLocalSet(&virCondEvent, event);
+    }
+
+    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;
+}
+
+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) {
+        unsigned int 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);
+}
+
+
+
+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);
+}
+
+void virThreadLocalSet(virThreadLocalPtr l, void *val)
+{
+    TlsSetValue(l->key, val);
+}
diff --git a/src/threads-win32.h b/src/threads-win32.h
new file mode 100644
--- /dev/null
+++ b/src/threads-win32.h
@@ -0,0 +1,39 @@
+/*
+ * threads-win32.h basic thread synchronization primitives
+ *
+ * Copyright (C) 2008 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#include "internal.h"
+
+#include <windows.h>
+
+struct virMutex {
+    HANDLE lock;
+};
+
+struct virCond {
+    virMutex lock;
+    unsigned int nwaiters;
+    HANDLE *waiters;
+};
+
+
+struct virThreadLocal {
+    DWORD key;
+};
diff --git a/src/threads.c b/src/threads.c
new file mode 100644
--- /dev/null
+++ b/src/threads.c
@@ -0,0 +1,34 @@
+/*
+ * threads.c: basic thread synchronization primitives
+ *
+ * Copyright (C) 2008 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#include <config.h>
+
+#include "threads.h"
+
+#ifdef HAVE_PTHREAD_H
+#include "threads-pthread.c"
+#else
+#ifdef WIN32
+#include "threads-win32.c"
+#else
+#error "Either pthreads or Win32 threads are required"
+#endif
+#endif
diff --git a/src/threads.h b/src/threads.h
new file mode 100644
--- /dev/null
+++ b/src/threads.h
@@ -0,0 +1,72 @@
+/*
+ * threads.h: basic thread synchronization primitives
+ *
+ * Copyright (C) 2008 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
+ *
+ */
+
+#ifndef __THREADS_H_
+#define __THREADS_H_
+
+#include "internal.h"
+
+typedef struct virMutex virMutex;
+typedef virMutex *virMutexPtr;
+
+typedef struct virCond virCond;
+typedef virCond *virCondPtr;
+
+typedef struct virThreadLocal virThreadLocal;
+typedef virThreadLocal *virThreadLocalPtr;
+
+
+int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK;
+void virThreadOnExit(void);
+
+int virMutexInit(virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
+void virMutexDestroy(virMutexPtr m);
+
+void virMutexLock(virMutexPtr m);
+void virMutexUnlock(virMutexPtr m);
+
+
+
+int virCondInit(virCondPtr c) ATTRIBUTE_RETURN_CHECK;
+int virCondDestroy(virCondPtr c) ATTRIBUTE_RETURN_CHECK;
+
+int virCondWait(virCondPtr c, virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
+void virCondSignal(virCondPtr c);
+void virCondBroadcast(virCondPtr c);
+
+
+typedef void (*virThreadLocalCleanup)(void *);
+int virThreadLocalInit(virThreadLocalPtr l,
+                       virThreadLocalCleanup c) ATTRIBUTE_RETURN_CHECK;
+void *virThreadLocalGet(virThreadLocalPtr l);
+void virThreadLocalSet(virThreadLocalPtr l, void*);
+
+#ifdef HAVE_PTHREAD_H
+#include "threads-pthread.h"
+#else
+#ifdef WIN32
+#include "threads-win32.h"
+#else
+#error "Either pthreads or Win32 threads are required"
+#endif
+#endif
+
+#endif
diff --git a/src/uml_conf.h b/src/uml_conf.h
--- a/src/uml_conf.h
+++ b/src/uml_conf.h
@@ -30,6 +30,7 @@
 #include "network_conf.h"
 #include "domain_conf.h"
 #include "virterror_internal.h"
+#include "threads.h"
 
 #define umlDebug(fmt, ...) do {} while(0)
 
@@ -39,7 +40,7 @@
 
 /* Main driver state */
 struct uml_driver {
-    PTHREAD_MUTEX_T(lock);
+    virMutex lock;
 
     unsigned int umlVersion;
     int nextvmid;
diff --git a/src/uml_driver.c b/src/uml_driver.c
--- a/src/uml_driver.c
+++ b/src/uml_driver.c
@@ -74,11 +74,11 @@ static int umlShutdown(void);
 
 static void umlDriverLock(struct uml_driver *driver)
 {
-    pthread_mutex_lock(&driver->lock);
+    virMutexLock(&driver->lock);
 }
 static void umlDriverUnlock(struct uml_driver *driver)
 {
-    pthread_mutex_unlock(&driver->lock);
+    virMutexUnlock(&driver->lock);
 }
 
 
@@ -314,7 +314,10 @@ umlStartup(void) {
     if (VIR_ALLOC(uml_driver) < 0)
         return -1;
 
-    pthread_mutex_init(&uml_driver->lock, NULL);
+    if (virMutexInit(&uml_driver->lock) < 0) {
+        VIR_FREE(uml_driver);
+        return -1;
+    }
     umlDriverLock(uml_driver);
 
     /* Don't have a dom0 so start from 1 */
@@ -501,6 +504,7 @@ umlShutdown(void) {
         brShutdown(uml_driver->brctl);
 
     umlDriverUnlock(uml_driver);
+    virMutexDestroy(&uml_driver->lock);
     VIR_FREE(uml_driver);
 
     return 0;
diff --git a/src/virsh.c b/src/virsh.c
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -6500,6 +6500,7 @@ _vshStrdup(vshControl *ctl, const char *
 /*
  * Initialize connection.
  */
+
 static int
 vshInit(vshControl *ctl)
 {

-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list