+Thu Jan 15 19:54:19 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
+
+ Provide a generic internal API for threads support
+ * src/Makefile.am, src/threads.c, src/threads.h: Generic internal API for threads
+ * src/threads-pthread.c, src/threads-pthread.h: UNIX pthreads impl
+ * src/threads-win32.c, src/threads-win32.h: Win32 threads impl
+ * src/internal.h: Remove unnneccessary pthreads macros
+ * src/libvirt_private.syms: Add symbols for internal threads API
+ * po/POTFILES.in: Add node_device_conf.c
+ * proxy/Makefile.am: Add threads.c to build
+ * qemud/qemud.c, qemud/qemud.h, qemud/remote.c, src/datatypes.c,
+ src/datatypes.h, src/domain_conf.c, src/domain_conf.h,
+ src/libvirt.c, src/logging.c, src/lxc_conf.h, src/lxc_driver.c,
+ src/network_conf.c, src/network_conf.h, src/network_driver.c,
+ src/node_device.c, src/node_device_conf.c, src/node_device_conf.h,
+ src/node_device_devkit.c, src/node_device_hal.c, src/openvz_conf.c,
+ src/openvz_conf.h, src/openvz_driver.c, src/qemu_conf.h,
+ src/qemu_driver.c, src/storage_conf.c, src/storage_conf.h,
+ src/storage_driver.c, src/test.c, src/uml_conf.h, src/uml_driver.c:
+ Switch over to internal threads API instead of pthreads
+
+
+
+
Thu Jan 15 19:39:19 GMT 2009 Daniel P. Berrange <berrange@redhat.com>
* src/util.c: Implement virKill() for Win32 platform
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
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 \
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;
}
if (ret != 0)
server->shutdown = 1;
- pthread_mutex_unlock(&server->lock);
+ virMutexUnlock(&server->lock);
}
int qemudSetCloseExec(int fd) {
return NULL;
}
- if (pthread_mutex_init(&server->lock, NULL) != 0) {
+ if (virMutexInit(&server->lock) < 0) {
+ VIR_ERROR("%s", _("cannot initialize mutex"));
+ VIR_FREE(server);
+ }
+ if (virCondInit(&server->job) < 0) {
+ VIR_ERROR("%s", _("cannot initialize condition variable"));
+ virMutexDestroy(&server->lock);
VIR_FREE(server);
- return NULL;
}
server->sigread = sigread;
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;
{
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;
}
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;
qemudDispatchClientFailure(server, client);
client->refs--;
- pthread_mutex_unlock(&client->lock);
- pthread_mutex_unlock(&server->lock);
+ virMutexUnlock(&client->lock);
+ virMutexUnlock(&server->lock);
}
}
if (qemudRegisterClientEvent(server, client, 1) < 0)
qemudDispatchClientFailure(server, client);
- pthread_cond_signal(&server->job);
+ virCondSignal(&server->job);
break;
}
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) {
}
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;
qemudDispatchClientRead(server, client);
else
qemudDispatchClientFailure(server, client);
- pthread_mutex_unlock(&client->lock);
+ virMutexUnlock(&client->lock);
}
static int qemudRegisterClientEvent(struct qemud_server *server,
struct qemud_server *server = (struct qemud_server *)opaque;
struct qemud_socket *sock;
- pthread_mutex_lock(&server->lock);
+ virMutexLock(&server->lock);
sock = server->sockets;
if (sock && sock->fd == fd && events)
qemudDispatchServer(server, sock);
- pthread_mutex_unlock(&server->lock);
+ virMutexUnlock(&server->lock);
}
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) {
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) {
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;
}
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
#include <rpc/xdr.h>
#include "remote_protocol.h"
#include "logging.h"
+#include "threads.h"
#ifdef __GNUC__
#ifdef HAVE_ANSIDECL_H
/* Stores the per-client connection state */
struct qemud_client {
- PTHREAD_MUTEX_T(lock);
+ virMutex lock;
int magic;
/* Main server state */
struct qemud_server {
- pthread_mutex_t lock;
- pthread_cond_t job;
+ virMutex lock;
+ virCond job;
int nworkers;
pthread_t *workers;
/* Call function. */
conn = client->conn;
- pthread_mutex_unlock(&client->lock);
+ virMutexUnlock(&client->lock);
/*
* When the RPC handler is called:
*/
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);
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;
remoteDispatchConnError(rerr, NULL);
rc = client->conn ? 0 : -1;
- pthread_mutex_unlock(&client->lock);
+ virMutexUnlock(&client->lock);
return rc;
}
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;
}
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;
}
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 ||
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;
}
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 ||
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;
}
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 ||
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;
}
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" :
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;
}
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 \
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;
if (ret->nodeDevices == NULL)
goto failed;
- pthread_mutex_init(&ret->lock, NULL);
-
ret->refs = 1;
return(ret);
if (ret->nodeDevices != NULL)
virHashFree(ret->nodeDevices, (virHashDeallocator) virNodeDeviceFree);
- pthread_mutex_destroy(&ret->lock);
+ virMutexDestroy(&ret->lock);
VIR_FREE(ret);
}
return(NULL);
xmlFreeURI(conn->uri);
- pthread_mutex_unlock(&conn->lock);
- pthread_mutex_destroy(&conn->lock);
+ virMutexUnlock(&conn->lock);
+ virMutexDestroy(&conn->lock);
VIR_FREE(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;
/* Already unlocked mutex */
return (0);
}
- pthread_mutex_unlock(&conn->lock);
+ virMutexUnlock(&conn->lock);
return (refs);
}
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 */
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);
return;
}
- pthread_mutex_unlock(&conn->lock);
+ virMutexUnlock(&conn->lock);
}
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;
return (0);
}
- pthread_mutex_unlock(&domain->conn->lock);
+ virMutexUnlock(&domain->conn->lock);
return (refs);
}
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 */
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);
return;
}
- pthread_mutex_unlock(&conn->lock);
+ virMutexUnlock(&conn->lock);
}
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;
return (0);
}
- pthread_mutex_unlock(&network->conn->lock);
+ virMutexUnlock(&network->conn->lock);
return (refs);
}
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 */
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);
return;
}
- pthread_mutex_unlock(&conn->lock);
+ virMutexUnlock(&conn->lock);
}
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;
return (0);
}
- pthread_mutex_unlock(&pool->conn->lock);
+ virMutexUnlock(&pool->conn->lock);
return (refs);
}
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) {
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);
return;
}
- pthread_mutex_unlock(&conn->lock);
+ virMutexUnlock(&conn->lock);
}
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;
return (0);
}
- pthread_mutex_unlock(&vol->conn->lock);
+ virMutexUnlock(&vol->conn->lock);
return (refs);
}
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) {
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);
return;
}
- pthread_mutex_unlock(&conn->lock);
+ virMutexUnlock(&conn->lock);
}
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;
return (0);
}
- pthread_mutex_unlock(&dev->conn->lock);
+ virMutexUnlock(&dev->conn->lock);
return (refs);
}
#include "hash.h"
#include "driver.h"
-
+#include "threads.h"
/**
* VIR_CONNECT_MAGIC:
* 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 */
VIR_FREE(dom->monitorpath);
VIR_FREE(dom->vcpupids);
+ virMutexDestroy(&dom->lock);
+
VIR_FREE(dom);
}
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;
}
-#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 */
#include "internal.h"
#include "capabilities.h"
#include "util.h"
+#include "threads.h"
/* Different types of hypervisor */
/* NB: Keep in sync with virDomainVirtTypeToString impl */
typedef struct _virDomainObj virDomainObj;
typedef virDomainObj *virDomainObjPtr;
struct _virDomainObj {
- PTHREAD_MUTEX_T(lock);
+ virMutex lock;
int stdin_fd;
int stdout_fd;
#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.
#endif
if (initialized)
return(0);
+
initialized = 1;
+ if (virThreadInitialize() < 0)
+ return -1;
+
#ifdef ENABLE_DEBUG
debugEnv = getenv("LIBVIRT_DEBUG");
if (debugEnv && *debugEnv && *debugEnv != '0') {
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
/**
virStoragePoolObjUnlock;
+# threads.h
+virMutexInit;
+virMutexDestroy;
+virMutexLock;
+virMutexUnlock;
+
+virCondInit;
+virCondDestroy;
+virCondWait;
+virCondSignal;
+virCondBroadcast;
+
# util.h
virFileReadAll;
virStrToLong_i;
#include "logging.h"
#include "memory.h"
#include "util.h"
+#include "threads.h"
#ifdef ENABLE_DEBUG
int debugFlag = 0;
/*
* 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);
}
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;
virLogStart = 0;
virLogEnd = 0;
virLogUnlock();
- pthread_mutex_destroy(&virLogMutex);
+ virMutexDestroy(&virLogMutex);
virLogInitialized = 0;
}
#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"
typedef struct __lxc_driver lxc_driver_t;
struct __lxc_driver {
- PTHREAD_MUTEX_T(lock);
+ virMutex lock;
virCapsPtr caps;
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);
}
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 */
VIR_FREE(lxc_driver->stateDir);
VIR_FREE(lxc_driver->logDir);
lxcDriverUnlock(lxc_driver);
+ virMutexDestroy(&lxc_driver->lock);
VIR_FREE(lxc_driver);
lxc_driver = NULL;
VIR_FREE(net->configFile);
VIR_FREE(net->autostartLink);
+ virMutexDestroy(&net->lock);
+
VIR_FREE(net);
}
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;
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);
-}
-
-#else
-void virNetworkObjLock(virNetworkObjPtr obj ATTRIBUTE_UNUSED)
-{
-}
-
-void virNetworkObjUnlock(virNetworkObjPtr obj ATTRIBUTE_UNUSED)
-{
+ virMutexUnlock(&obj->lock);
}
-#endif
#include <libxml/xpath.h>
#include "internal.h"
+#include "threads.h"
/* 2 possible types of forwarding */
enum virNetworkForwardType {
typedef struct _virNetworkObj virNetworkObj;
typedef virNetworkObj *virNetworkObjPtr;
struct _virNetworkObj {
- PTHREAD_MUTEX_T(lock);
+ virMutex lock;
pid_t dnsmasqPid;
unsigned int active : 1;
/* Main driver state */
struct network_driver {
- PTHREAD_MUTEX_T(lock);
+ virMutex lock;
virNetworkObjList networks;
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);
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) {
iptablesContextFree(driverState->iptables);
networkDriverUnlock(driverState);
+ virMutexDestroy(&driverState->lock);
VIR_FREE(driverState);
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,
if (dev->privateFree)
(*dev->privateFree)(dev->privateData);
+ virMutexDestroy(&dev->lock);
+
VIR_FREE(dev);
}
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;
}
-#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);
-}
-
-#else
-
-void virNodeDeviceObjLock(virNodeDeviceObjPtr obj ATTRIBUTE_UNUSED)
-{
-}
-
-void virNodeDeviceObjUnlock(virNodeDeviceObjPtr obj ATTRIBUTE_UNUSED)
-{
+ virMutexUnlock(&obj->lock);
}
-#endif
#include "internal.h"
#include "util.h"
+#include "threads.h"
enum virNodeDevCapType {
/* Keep in sync with VIR_ENUM_IMPL in node_device_conf.c */
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 */
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 */
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();
virNodeDeviceObjListFree(&driverState->devs);
if (devkit_client)
g_object_unref(devkit_client);
- nodeDeviceLock(driverState);
+ nodeDeviceUnlock(driverState);
+ virMutexDestroy(&driveState->lock);
VIR_FREE(driverState);
return 0;
}
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 */
(void)libhal_ctx_shutdown(hal_ctx, NULL);
(void)libhal_ctx_free(hal_ctx);
nodeDeviceUnlock(driverState);
+ virMutexDestroy(&driverState->lock);
VIR_FREE(driverState);
return 0;
}
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;
#include "internal.h"
#include "domain_conf.h"
+#include "threads.h"
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;
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;
#include "network_conf.h"
#include "domain_conf.h"
#include "domain_event.h"
+#include "threads.h"
#define qemudDebug(fmt, ...) do {} while(0)
/* Main driver state */
struct qemud_driver {
- PTHREAD_MUTEX_T(lock);
+ virMutex lock;
unsigned int qemuVersion;
int nextvmid;
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) {
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 */
brShutdown(qemu_driver->brctl);
qemuDriverUnlock(qemu_driver);
+ virMutexDestroy(&qemu_driver->lock);
VIR_FREE(qemu_driver);
return 0;
VIR_FREE(obj->configFile);
VIR_FREE(obj->autostartLink);
+
+ virMutexDestroy(&obj->lock);
+
VIR_FREE(obj);
}
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;
}
-#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
#include "internal.h"
#include "util.h"
+#include "threads.h"
/* Shared structs */
typedef virStoragePoolObj *virStoragePoolObjPtr;
struct _virStoragePoolObj {
- PTHREAD_MUTEX_T(lock);
+ virMutex lock;
char *configFile;
char *autostartLink;
typedef virStorageDriverState *virStorageDriverStatePtr;
struct _virStorageDriverState {
- PTHREAD_MUTEX_T(lock);
+ virMutex lock;
virStoragePoolObjList pools;
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
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) {
VIR_FREE(driverState->configDir);
VIR_FREE(driverState->autostartDir);
storageDriverUnlock(driverState);
+ virMutexDestroy(&driverState->lock);
VIR_FREE(driverState);
return 0;
#include "domain_conf.h"
#include "storage_conf.h"
#include "xml.h"
+#include "threads.h"
#define MAX_CPUS 128
#define MAX_CELLS 128
struct _testConn {
- PTHREAD_MUTEX_T(lock);
+ virMutex lock;
char path[PATH_MAX];
int nextDomID;
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) {
testError(conn, VIR_ERR_NO_MEMORY, "testConn");
return VIR_DRV_OPEN_ERROR;
}
- conn->privateData = privconn;
- pthread_mutex_init(&privconn->lock, NULL);
+ 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;
if (gettimeofday(&tv, NULL) < 0) {
testError(NULL, VIR_ERR_INTERNAL_ERROR, "%s", _("getting time of day"));
virStoragePoolObjUnlock(poolobj);
testDriverUnlock(privconn);
+
return VIR_DRV_OPEN_SUCCESS;
error:
virStoragePoolObjListFree(&privconn->pools);
virCapabilitiesFree(privconn->caps);
testDriverUnlock(privconn);
+ conn->privateData = NULL;
VIR_FREE(privconn);
return VIR_DRV_OPEN_ERROR;
}
testError(NULL, VIR_ERR_NO_MEMORY, "testConn");
return VIR_DRV_OPEN_ERROR;
}
- conn->privateData = privconn;
- pthread_mutex_init(&privconn->lock, NULL);
+ 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;
if (!(privconn->caps = testBuildCapabilities(conn)))
goto error;
virNetworkObjListFree(&privconn->networks);
virStoragePoolObjListFree(&privconn->pools);
testDriverUnlock(privconn);
+ virMutexDestroy(&privconn->lock);
VIR_FREE (privconn);
conn->privateData = NULL;
--- /dev/null
+/*
+ * threads-pthread.c: basic thread synchronization primitives
+ *
+ * Copyright (C) 2009 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);
+}
--- /dev/null
+/*
+ * threads.c: basic thread synchronization primitives
+ *
+ * Copyright (C) 2009 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;
+};
--- /dev/null
+/*
+ * threads-win32.c: basic thread synchronization primitives
+ *
+ * Copyright (C) 2009 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);
+}
--- /dev/null
+/*
+ * threads-win32.h basic thread synchronization primitives
+ *
+ * Copyright (C) 2009 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;
+};
--- /dev/null
+/*
+ * threads.c: basic thread synchronization primitives
+ *
+ * Copyright (C) 2009 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
--- /dev/null
+/*
+ * threads.h: basic thread synchronization primitives
+ *
+ * Copyright (C) 2009 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
#include "network_conf.h"
#include "domain_conf.h"
#include "virterror_internal.h"
+#include "threads.h"
#define umlDebug(fmt, ...) do {} while(0)
/* Main driver state */
struct uml_driver {
- PTHREAD_MUTEX_T(lock);
+ virMutex lock;
unsigned int umlVersion;
int nextvmid;
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);
}
if (VIR_ALLOC(uml_driver) < 0)
return -1;
- pthread_mutex_init(¨_driver->lock, NULL);
+ if (virMutexInit(¨_driver->lock) < 0) {
+ VIR_FREE(uml_driver);
+ return -1;
+ }
umlDriverLock(uml_driver);
/* Don't have a dom0 so start from 1 */
brShutdown(uml_driver->brctl);
umlDriverUnlock(uml_driver);
+ virMutexDestroy(¨_driver->lock);
VIR_FREE(uml_driver);
return 0;