From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> --- daemon/libvirtd.c | 1 - daemon/libvirtd.h | 2 +- src/Makefile.am | 8 +- src/conf/device_conf.h | 2 +- src/conf/domain_conf.h | 2 +- src/conf/interface_conf.h | 2 +- src/conf/network_conf.h | 2 +- src/conf/node_device_conf.h | 2 +- src/conf/storage_conf.h | 2 +- src/conf/virconsole.c | 2 +- src/datatypes.h | 2 +- src/libvirt.c | 2 +- src/locking/lock_daemon.h | 2 +- src/lxc/lxc_conf.h | 2 +- src/lxc/lxc_monitor.c | 2 +- src/nwfilter/nwfilter_learnipaddr.c | 2 +- src/openvz/openvz_conf.h | 2 +- src/parallels/parallels_utils.h | 2 +- src/qemu/qemu_conf.h | 2 +- src/qemu/qemu_domain.h | 2 +- src/rpc/virkeepalive.c | 2 +- src/rpc/virnetclient.c | 2 +- src/rpc/virnetclientprogram.c | 2 +- src/rpc/virnetclientstream.c | 2 +- src/rpc/virnetsaslcontext.c | 2 +- src/rpc/virnetserver.c | 2 +- src/rpc/virnetserverclient.c | 2 +- src/rpc/virnetserverprogram.c | 2 +- src/rpc/virnetserverservice.c | 2 +- src/rpc/virnetsocket.c | 2 +- src/rpc/virnetsshsession.c | 2 +- src/rpc/virnettlscontext.c | 2 +- src/secret/secret_driver.c | 2 +- src/test/test_driver.c | 2 +- src/uml/uml_conf.h | 2 +- src/util/iohelper.c | 2 +- src/util/threads-pthread.c | 263 ------------------------ src/util/threads-pthread.h | 49 ----- src/util/threads-win32.c | 392 ------------------------------------ src/util/threads-win32.h | 53 ----- src/util/threads.c | 34 ---- src/util/threads.h | 166 --------------- src/util/util.c | 2 +- src/util/virdbus.c | 2 +- src/util/virebtables.c | 2 +- src/util/vireventpoll.c | 2 +- src/util/viriptables.c | 2 +- src/util/virlockspace.c | 2 +- src/util/virlog.c | 2 +- src/util/virnetlink.c | 2 +- src/util/virnodesuspend.c | 2 +- src/util/virobject.c | 2 +- src/util/virrandom.c | 2 +- src/util/virterror.c | 2 +- src/util/virthread.c | 34 ++++ src/util/virthread.h | 166 +++++++++++++++ src/util/virthreadpool.c | 2 +- src/util/virthreadpthread.c | 263 ++++++++++++++++++++++++ src/util/virthreadpthread.h | 49 +++++ src/util/virthreadwin32.c | 392 ++++++++++++++++++++++++++++++++++++ src/util/virthreadwin32.h | 53 +++++ src/vmware/vmware_conf.h | 2 +- src/xen/xen_hypervisor.c | 2 +- tests/eventtest.c | 2 +- tests/nwfilterxml2xmltest.c | 2 +- tests/qemumonitorjsontest.c | 2 +- tests/qemumonitortestutils.c | 2 +- tests/testutils.c | 2 +- tests/viratomictest.c | 2 +- tools/console.c | 2 +- tools/virsh.c | 2 +- tools/virsh.h | 2 +- 72 files changed, 1019 insertions(+), 1020 deletions(-) delete mode 100644 src/util/threads-pthread.c delete mode 100644 src/util/threads-pthread.h delete mode 100644 src/util/threads-win32.c delete mode 100644 src/util/threads-win32.h delete mode 100644 src/util/threads.c delete mode 100644 src/util/threads.h create mode 100644 src/util/virthread.c create mode 100644 src/util/virthread.h create mode 100644 src/util/virthreadpthread.c create mode 100644 src/util/virthreadpthread.h create mode 100644 src/util/virthreadwin32.c create mode 100644 src/util/virthreadwin32.h diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 903f8c2..dc1d2c5 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -50,7 +50,6 @@ #include "virconf.h" #include "virnetlink.h" #include "virnetserver.h" -#include "threads.h" #include "remote.h" #include "remote_driver.h" #include "virhooks.h" diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h index b04cc71..69a77ea 100644 --- a/daemon/libvirtd.h +++ b/daemon/libvirtd.h @@ -34,7 +34,7 @@ # include "remote_protocol.h" # include "qemu_protocol.h" # include "virlog.h" -# include "threads.h" +# include "virthread.h" # if HAVE_SASL # include "virnetsaslcontext.h" # endif diff --git a/src/Makefile.am b/src/Makefile.am index e74a3a3..d8d96f8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -53,9 +53,6 @@ augeastest_DATA = # These files are not related to driver APIs. Simply generic # helper APIs for various purposes UTIL_SOURCES = \ - util/threads.c util/threads.h \ - util/threads-pthread.h \ - util/threads-win32.h \ util/uuid.c util/uuid.h \ util/util.c util/util.h \ util/viralloc.c util/viralloc.h \ @@ -85,6 +82,9 @@ UTIL_SOURCES = \ util/virstatslinux.c util/virstatslinux.h \ util/virstoragefile.c util/virstoragefile.h \ util/virsysinfo.c util/virsysinfo.h \ + util/virthread.c util/virthread.h \ + util/virthreadpthread.h \ + util/virthreadwin32.h \ util/virthreadpool.c util/virthreadpool.h \ util/virtypedparam.c util/virtypedparam.h \ util/xml.c util/xml.h \ @@ -125,7 +125,7 @@ $(srcdir)/util/virkeymaps.h: $(srcdir)/util/keymaps.csv \ $(srcdir)/util/virkeycode-mapgen.py $(AM_V_GEN)$(PYTHON) $(srcdir)/util/virkeycode-mapgen.py <$(srcdir)/util/keymaps.csv >$@ -EXTRA_DIST += util/threads-pthread.c util/threads-win32.c +EXTRA_DIST += util/virthreadpthread.c util/virthreadwin32.c # Internal generic driver infrastructure NODE_INFO_SOURCES = nodeinfo.h nodeinfo.c diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h index 09d6be9..c1bf096 100644 --- a/src/conf/device_conf.h +++ b/src/conf/device_conf.h @@ -29,7 +29,7 @@ # include "internal.h" # include "util.h" -# include "threads.h" +# include "virthread.h" # include "virbuffer.h" enum virDeviceAddressPciMulti { diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 718c6a9..56aece2 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -33,7 +33,7 @@ # include "storage_encryption_conf.h" # include "cpu_conf.h" # include "util.h" -# include "threads.h" +# include "virthread.h" # include "virhash.h" # include "virsocketaddr.h" # include "nwfilter_params.h" diff --git a/src/conf/interface_conf.h b/src/conf/interface_conf.h index 1749629..d6f98f1 100644 --- a/src/conf/interface_conf.h +++ b/src/conf/interface_conf.h @@ -30,7 +30,7 @@ # include "internal.h" # include "util.h" -# include "threads.h" +# include "virthread.h" /* There is currently 3 types of interfaces */ diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h index 4d70fe6..4c634ed 100644 --- a/src/conf/network_conf.h +++ b/src/conf/network_conf.h @@ -31,7 +31,7 @@ # include <libxml/xpath.h> # include "internal.h" -# include "threads.h" +# include "virthread.h" # include "virsocketaddr.h" # include "virnetdevbandwidth.h" # include "virnetdevvportprofile.h" diff --git a/src/conf/node_device_conf.h b/src/conf/node_device_conf.h index e394042..9860f67 100644 --- a/src/conf/node_device_conf.h +++ b/src/conf/node_device_conf.h @@ -27,7 +27,7 @@ # include "internal.h" # include "util.h" -# include "threads.h" +# include "virthread.h" # include <libxml/tree.h> diff --git a/src/conf/storage_conf.h b/src/conf/storage_conf.h index 743b768..573c3db 100644 --- a/src/conf/storage_conf.h +++ b/src/conf/storage_conf.h @@ -27,7 +27,7 @@ # include "internal.h" # include "util.h" # include "storage_encryption_conf.h" -# include "threads.h" +# include "virthread.h" # include <libxml/tree.h> diff --git a/src/conf/virconsole.c b/src/conf/virconsole.c index 757573d..515c5fa 100644 --- a/src/conf/virconsole.c +++ b/src/conf/virconsole.c @@ -31,7 +31,7 @@ #include "virhash.h" #include "fdstream.h" #include "internal.h" -#include "threads.h" +#include "virthread.h" #include "viralloc.h" #include "virpidfile.h" #include "virlog.h" diff --git a/src/datatypes.h b/src/datatypes.h index 55f97ed..a1dfc1e 100644 --- a/src/datatypes.h +++ b/src/datatypes.h @@ -25,7 +25,7 @@ # include "internal.h" # include "driver.h" -# include "threads.h" +# include "virthread.h" # include "virobject.h" extern virClassPtr virConnectClass; diff --git a/src/libvirt.c b/src/libvirt.c index ed7dcae..5654d53 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -59,7 +59,7 @@ #include "vircommand.h" #include "virrandom.h" #include "viruri.h" -#include "threads.h" +#include "virthread.h" #ifdef WITH_TEST # include "test/test_driver.h" diff --git a/src/locking/lock_daemon.h b/src/locking/lock_daemon.h index 619f8f2..da62edc 100644 --- a/src/locking/lock_daemon.h +++ b/src/locking/lock_daemon.h @@ -24,7 +24,7 @@ # define __VIR_LOCK_DAEMON_H__ # include "virlockspace.h" -# include "threads.h" +# include "virthread.h" typedef struct _virLockDaemon virLockDaemon; typedef virLockDaemon *virLockDaemonPtr; diff --git a/src/lxc/lxc_conf.h b/src/lxc/lxc_conf.h index c02966f..b0b7711 100644 --- a/src/lxc/lxc_conf.h +++ b/src/lxc/lxc_conf.h @@ -31,7 +31,7 @@ # include "domain_conf.h" # include "domain_event.h" # include "capabilities.h" -# include "threads.h" +# include "virthread.h" # include "vircgroup.h" # include "security/security_manager.h" # include "configmake.h" diff --git a/src/lxc/lxc_monitor.c b/src/lxc/lxc_monitor.c index 90637eb..b0da21f 100644 --- a/src/lxc/lxc_monitor.c +++ b/src/lxc/lxc_monitor.c @@ -29,7 +29,7 @@ #include "virterror_internal.h" #include "virlog.h" -#include "threads.h" +#include "virthread.h" #include "rpc/virnetclient.h" #define VIR_FROM_THIS VIR_FROM_LXC diff --git a/src/nwfilter/nwfilter_learnipaddr.c b/src/nwfilter/nwfilter_learnipaddr.c index 8c4bbcf..442cc83 100644 --- a/src/nwfilter/nwfilter_learnipaddr.c +++ b/src/nwfilter/nwfilter_learnipaddr.c @@ -47,7 +47,7 @@ #include "datatypes.h" #include "virnetdev.h" #include "virterror_internal.h" -#include "threads.h" +#include "virthread.h" #include "conf/nwfilter_params.h" #include "conf/domain_conf.h" #include "nwfilter_gentech_driver.h" diff --git a/src/openvz/openvz_conf.h b/src/openvz/openvz_conf.h index 3eb2b3e..c1007f0 100644 --- a/src/openvz/openvz_conf.h +++ b/src/openvz/openvz_conf.h @@ -31,7 +31,7 @@ # include "internal.h" # include "domain_conf.h" -# include "threads.h" +# include "virthread.h" /* OpenVZ commands - Replace with wrapper scripts later? */ diff --git a/src/parallels/parallels_utils.h b/src/parallels/parallels_utils.h index 7c31707..cf006e8 100644 --- a/src/parallels/parallels_utils.h +++ b/src/parallels/parallels_utils.h @@ -24,11 +24,11 @@ # define PARALLELS_UTILS_H # include "driver.h" -# include "util/threads.h" # include "conf/domain_conf.h" # include "conf/storage_conf.h" # include "conf/domain_event.h" # include "conf/network_conf.h" +# include "virthread.h" # include "virjson.h" # define parallelsParseError() \ diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 0d4816e..1aa56cc 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -32,7 +32,7 @@ # include "network_conf.h" # include "domain_conf.h" # include "domain_event.h" -# include "threads.h" +# include "virthread.h" # include "security/security_manager.h" # include "vircgroup.h" # include "virpci.h" diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 11670b9..00648cf 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -24,7 +24,7 @@ #ifndef __QEMU_DOMAIN_H__ # define __QEMU_DOMAIN_H__ -# include "threads.h" +# include "virthread.h" # include "domain_conf.h" # include "snapshot_conf.h" # include "qemu_monitor.h" diff --git a/src/rpc/virkeepalive.c b/src/rpc/virkeepalive.c index 91af315..5c14e14 100644 --- a/src/rpc/virkeepalive.c +++ b/src/rpc/virkeepalive.c @@ -23,7 +23,7 @@ #include <config.h> #include "viralloc.h" -#include "threads.h" +#include "virthread.h" #include "virfile.h" #include "virlog.h" #include "util.h" diff --git a/src/rpc/virnetclient.c b/src/rpc/virnetclient.c index b4fe4d9..85787f0 100644 --- a/src/rpc/virnetclient.c +++ b/src/rpc/virnetclient.c @@ -31,7 +31,7 @@ #include "virnetsocket.h" #include "virkeepalive.h" #include "viralloc.h" -#include "threads.h" +#include "virthread.h" #include "virfile.h" #include "virlog.h" #include "util.h" diff --git a/src/rpc/virnetclientprogram.c b/src/rpc/virnetclientprogram.c index 7396971..00948e0 100644 --- a/src/rpc/virnetclientprogram.c +++ b/src/rpc/virnetclientprogram.c @@ -33,7 +33,7 @@ #include "virlog.h" #include "util.h" #include "virfile.h" -#include "threads.h" +#include "virthread.h" #define VIR_FROM_THIS VIR_FROM_RPC diff --git a/src/rpc/virnetclientstream.c b/src/rpc/virnetclientstream.c index 4877b0c..7e1f9c7 100644 --- a/src/rpc/virnetclientstream.c +++ b/src/rpc/virnetclientstream.c @@ -27,7 +27,7 @@ #include "viralloc.h" #include "virterror_internal.h" #include "virlog.h" -#include "threads.h" +#include "virthread.h" #define VIR_FROM_THIS VIR_FROM_RPC diff --git a/src/rpc/virnetsaslcontext.c b/src/rpc/virnetsaslcontext.c index adc4f1e..cd30f4d 100644 --- a/src/rpc/virnetsaslcontext.c +++ b/src/rpc/virnetsaslcontext.c @@ -27,7 +27,7 @@ #include "virterror_internal.h" #include "viralloc.h" -#include "threads.h" +#include "virthread.h" #include "virlog.h" #define VIR_FROM_THIS VIR_FROM_RPC diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c index 26ceb0c..b48af5e 100644 --- a/src/rpc/virnetserver.c +++ b/src/rpc/virnetserver.c @@ -31,7 +31,7 @@ #include "virlog.h" #include "viralloc.h" #include "virterror_internal.h" -#include "threads.h" +#include "virthread.h" #include "virthreadpool.h" #include "util.h" #include "virfile.h" diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c index 7f028b8..f1eb69b 100644 --- a/src/rpc/virnetserverclient.c +++ b/src/rpc/virnetserverclient.c @@ -32,7 +32,7 @@ #include "virlog.h" #include "virterror_internal.h" #include "viralloc.h" -#include "threads.h" +#include "virthread.h" #include "virkeepalive.h" #define VIR_FROM_THIS VIR_FROM_RPC diff --git a/src/rpc/virnetserverprogram.c b/src/rpc/virnetserverprogram.c index 287282e..a8f875c 100644 --- a/src/rpc/virnetserverprogram.c +++ b/src/rpc/virnetserverprogram.c @@ -30,7 +30,7 @@ #include "virterror_internal.h" #include "virlog.h" #include "virfile.h" -#include "threads.h" +#include "virthread.h" #define VIR_FROM_THIS VIR_FROM_RPC diff --git a/src/rpc/virnetserverservice.c b/src/rpc/virnetserverservice.c index 92b5cef..9992983 100644 --- a/src/rpc/virnetserverservice.c +++ b/src/rpc/virnetserverservice.c @@ -27,7 +27,7 @@ #include "viralloc.h" #include "virterror_internal.h" -#include "threads.h" +#include "virthread.h" #define VIR_FROM_THIS VIR_FROM_RPC diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index 8c62a2a..442850a 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -46,7 +46,7 @@ #include "virterror_internal.h" #include "virlog.h" #include "virfile.h" -#include "threads.h" +#include "virthread.h" #include "virprocess.h" #include "passfd.h" diff --git a/src/rpc/virnetsshsession.c b/src/rpc/virnetsshsession.c index 8a7d5f9..663b7cd 100644 --- a/src/rpc/virnetsshsession.c +++ b/src/rpc/virnetsshsession.c @@ -30,7 +30,7 @@ #include "viralloc.h" #include "virlog.h" #include "configmake.h" -#include "threads.h" +#include "virthread.h" #include "util.h" #include "virterror_internal.h" #include "virobject.h" diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c index d9354e0..1ff40cf 100644 --- a/src/rpc/virnettlscontext.c +++ b/src/rpc/virnettlscontext.c @@ -34,7 +34,7 @@ #include "virterror_internal.h" #include "util.h" #include "virlog.h" -#include "threads.h" +#include "virthread.h" #include "configmake.h" #define DH_BITS 1024 diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c index fb2024b..672ff54 100644 --- a/src/secret/secret_driver.c +++ b/src/secret/secret_driver.c @@ -36,7 +36,7 @@ #include "viralloc.h" #include "secret_conf.h" #include "secret_driver.h" -#include "threads.h" +#include "virthread.h" #include "util.h" #include "uuid.h" #include "virterror_internal.h" diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 3abd289..185bb3b 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -47,7 +47,7 @@ #include "storage_conf.h" #include "node_device_conf.h" #include "xml.h" -#include "threads.h" +#include "virthread.h" #include "virlog.h" #include "virfile.h" #include "virtypedparam.h" diff --git a/src/uml/uml_conf.h b/src/uml/uml_conf.h index 09a0305..dfa168e 100644 --- a/src/uml/uml_conf.h +++ b/src/uml/uml_conf.h @@ -30,7 +30,7 @@ # include "domain_conf.h" # include "domain_event.h" # include "virterror_internal.h" -# include "threads.h" +# include "virthread.h" # include "vircommand.h" # include "virhash.h" diff --git a/src/util/iohelper.c b/src/util/iohelper.c index 1b16d5c..dcb5c14 100644 --- a/src/util/iohelper.c +++ b/src/util/iohelper.c @@ -34,7 +34,7 @@ #include <stdlib.h> #include "util.h" -#include "threads.h" +#include "virthread.h" #include "virfile.h" #include "viralloc.h" #include "virterror_internal.h" diff --git a/src/util/threads-pthread.c b/src/util/threads-pthread.c deleted file mode 100644 index 37d8902..0000000 --- a/src/util/threads-pthread.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * threads-pthread.c: basic thread synchronization primitives - * - * Copyright (C) 2009-2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * <http://www.gnu.org/licenses/>. - * - */ - -#include <config.h> - -#include <unistd.h> -#include <inttypes.h> -#if HAVE_SYS_SYSCALL_H -# include <sys/syscall.h> -#endif - -#include "viralloc.h" - - -/* Nothing special required for pthreads */ -int virThreadInitialize(void) -{ - return 0; -} - -void virThreadOnExit(void) -{ -} - -int virOnce(virOnceControlPtr once, virOnceFunc init) -{ - return pthread_once(&once->once, init); -} - - -int virMutexInit(virMutexPtr m) -{ - int ret; - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); - ret = pthread_mutex_init(&m->lock, &attr); - pthread_mutexattr_destroy(&attr); - if (ret != 0) { - errno = ret; - return -1; - } - return 0; -} - -int virMutexInitRecursive(virMutexPtr m) -{ - int ret; - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - ret = pthread_mutex_init(&m->lock, &attr); - pthread_mutexattr_destroy(&attr); - if (ret != 0) { - errno = ret; - return -1; - } - return 0; -} - -void virMutexDestroy(virMutexPtr m) -{ - pthread_mutex_destroy(&m->lock); -} - -void virMutexLock(virMutexPtr m){ - pthread_mutex_lock(&m->lock); -} - -void virMutexUnlock(virMutexPtr m) -{ - pthread_mutex_unlock(&m->lock); -} - - -int virCondInit(virCondPtr c) -{ - int ret; - if ((ret = pthread_cond_init(&c->cond, NULL)) != 0) { - errno = ret; - return -1; - } - return 0; -} - -int virCondDestroy(virCondPtr c) -{ - int ret; - if ((ret = pthread_cond_destroy(&c->cond)) != 0) { - errno = ret; - return -1; - } - return 0; -} - -int virCondWait(virCondPtr c, virMutexPtr m) -{ - int ret; - if ((ret = pthread_cond_wait(&c->cond, &m->lock)) != 0) { - errno = ret; - return -1; - } - return 0; -} - -int virCondWaitUntil(virCondPtr c, virMutexPtr m, unsigned long long whenms) -{ - int ret; - struct timespec ts; - - ts.tv_sec = whenms / 1000; - ts.tv_nsec = (whenms % 1000) * 1000; - - if ((ret = pthread_cond_timedwait(&c->cond, &m->lock, &ts)) != 0) { - errno = ret; - return -1; - } - return 0; -} - -void virCondSignal(virCondPtr c) -{ - pthread_cond_signal(&c->cond); -} - -void virCondBroadcast(virCondPtr c) -{ - pthread_cond_broadcast(&c->cond); -} - -struct virThreadArgs { - virThreadFunc func; - void *opaque; -}; - -static void *virThreadHelper(void *data) -{ - struct virThreadArgs *args = data; - struct virThreadArgs local = *args; - - /* Free args early, rather than tying it up during the entire thread. */ - VIR_FREE(args); - local.func(local.opaque); - return NULL; -} - -int virThreadCreate(virThreadPtr thread, - bool joinable, - virThreadFunc func, - void *opaque) -{ - struct virThreadArgs *args; - pthread_attr_t attr; - int ret = -1; - int err; - - if ((err = pthread_attr_init(&attr)) != 0) - goto cleanup; - if (VIR_ALLOC(args) < 0) { - err = ENOMEM; - goto cleanup; - } - - args->func = func; - args->opaque = opaque; - - if (!joinable) - pthread_attr_setdetachstate(&attr, 1); - - err = pthread_create(&thread->thread, &attr, virThreadHelper, args); - if (err != 0) { - VIR_FREE(args); - goto cleanup; - } - /* New thread owns 'args' in success case, so don't free */ - - ret = 0; -cleanup: - pthread_attr_destroy(&attr); - if (ret < 0) - errno = err; - return ret; -} - -void virThreadSelf(virThreadPtr thread) -{ - thread->thread = pthread_self(); -} - -bool virThreadIsSelf(virThreadPtr thread) -{ - return pthread_equal(pthread_self(), thread->thread) ? true : false; -} - -/* For debugging use only; this result is not guaranteed unique on BSD - * systems when pthread_t is a 64-bit pointer. */ -int virThreadSelfID(void) -{ -#if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid) - pid_t tid; - tid = syscall(SYS_gettid); - return (int)tid; -#else - return (int)(intptr_t)(void *)pthread_self(); -#endif -} - -/* For debugging use only; this result is not guaranteed unique on BSD - * systems when pthread_t is a 64-bit pointer, nor does it match the - * thread id of virThreadSelfID on Linux. */ -int virThreadID(virThreadPtr thread) -{ - return (int)(uintptr_t)thread->thread; -} - -void virThreadJoin(virThreadPtr thread) -{ - pthread_join(thread->thread, NULL); -} - -int virThreadLocalInit(virThreadLocalPtr l, - virThreadLocalCleanup c) -{ - int ret; - if ((ret = pthread_key_create(&l->key, c)) != 0) { - errno = ret; - return -1; - } - return 0; -} - -void *virThreadLocalGet(virThreadLocalPtr l) -{ - return pthread_getspecific(l->key); -} - -int virThreadLocalSet(virThreadLocalPtr l, void *val) -{ - int err = pthread_setspecific(l->key, val); - if (err) { - errno = err; - return -1; - } - return 0; -} diff --git a/src/util/threads-pthread.h b/src/util/threads-pthread.h deleted file mode 100644 index ddaedb7..0000000 --- a/src/util/threads-pthread.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * threads.c: basic thread synchronization primitives - * - * Copyright (C) 2009, 2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * <http://www.gnu.org/licenses/>. - * - */ - -#include "internal.h" - -#include <pthread.h> - -struct virMutex { - pthread_mutex_t lock; -}; - -struct virCond { - pthread_cond_t cond; -}; - -struct virThread { - pthread_t thread; -}; - -struct virThreadLocal { - pthread_key_t key; -}; - -struct virOnceControl { - pthread_once_t once; -}; - -#define VIR_ONCE_CONTROL_INITIALIZER \ -{ \ - .once = PTHREAD_ONCE_INIT \ -} diff --git a/src/util/threads-win32.c b/src/util/threads-win32.c deleted file mode 100644 index c9f16c1..0000000 --- a/src/util/threads-win32.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * threads-win32.c: basic thread synchronization primitives - * - * Copyright (C) 2009-2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * <http://www.gnu.org/licenses/>. - * - */ - -#include <config.h> - -#include <process.h> - -#include "viralloc.h" - -struct virThreadLocalData { - DWORD key; - virThreadLocalCleanup cleanup; -}; -typedef struct virThreadLocalData virThreadLocalData; -typedef virThreadLocalData *virThreadLocalDataPtr; - -virMutex virThreadLocalLock; -unsigned int virThreadLocalCount = 0; -virThreadLocalDataPtr virThreadLocalList = NULL; -DWORD selfkey; - -virThreadLocal virCondEvent; - -void virCondEventCleanup(void *data); - -int virThreadInitialize(void) -{ - if (virMutexInit(&virThreadLocalLock) < 0) - return -1; - if (virThreadLocalInit(&virCondEvent, virCondEventCleanup) < 0) - return -1; - if ((selfkey = TlsAlloc()) == TLS_OUT_OF_INDEXES) - return -1; - return 0; -} - -void virThreadOnExit(void) -{ - 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 virOnce(virOnceControlPtr once, virOnceFunc func) -{ - if (!once->complete) { - if (InterlockedIncrement(&once->init) == 1) { - /* We're the first thread. */ - func(); - once->complete = 1; - } else { - /* We're a later thread. Decrement the init counter back - * to avoid overflow, then yield until the first thread - * marks that the function is complete. It is rare that - * multiple threads will be waiting here, and since each - * thread is yielding except the first, we should get out - * soon enough. */ - InterlockedDecrement(&once->init); - while (!once->complete) - Sleep(0); - } - } - return 0; -} - -int virMutexInit(virMutexPtr m) -{ - return virMutexInitRecursive(m); -} - -int virMutexInitRecursive(virMutexPtr m) -{ - if (!(m->lock = CreateMutex(NULL, FALSE, NULL))) { - errno = ESRCH; - return -1; - } - return 0; -} - -void virMutexDestroy(virMutexPtr m) -{ - CloseHandle(m->lock); -} - -void virMutexLock(virMutexPtr m) -{ - WaitForSingleObject(m->lock, INFINITE); -} - -void virMutexUnlock(virMutexPtr m) -{ - ReleaseMutex(m->lock); -} - - - -int virCondInit(virCondPtr c) -{ - c->waiters = NULL; - if (virMutexInit(&c->lock) < 0) - return -1; - return 0; -} - -int virCondDestroy(virCondPtr c) -{ - if (c->waiters) { - errno = EINVAL; - return -1; - } - virMutexDestroy(&c->lock); - return 0; -} - -void virCondEventCleanup(void *data) -{ - HANDLE event = data; - CloseHandle(event); -} - -int virCondWait(virCondPtr c, virMutexPtr m) -{ - HANDLE event = virThreadLocalGet(&virCondEvent); - - if (!event) { - event = CreateEvent(0, FALSE, FALSE, NULL); - if (!event) { - return -1; - } - if (virThreadLocalSet(&virCondEvent, event) < 0) { - CloseHandle(event); - return -1; - } - } - - virMutexLock(&c->lock); - - if (VIR_REALLOC_N(c->waiters, c->nwaiters + 1) < 0) { - virMutexUnlock(&c->lock); - return -1; - } - c->waiters[c->nwaiters] = event; - c->nwaiters++; - - virMutexUnlock(&c->lock); - - virMutexUnlock(m); - - if (WaitForSingleObject(event, INFINITE) == WAIT_FAILED) { - virMutexLock(m); - errno = EINVAL; - return -1; - } - - virMutexLock(m); - return 0; -} - -int virCondWaitUntil(virCondPtr c ATTRIBUTE_UNUSED, - virMutexPtr m ATTRIBUTE_UNUSED, - unsigned long long whenms ATTRIBUTE_UNUSED) -{ - /* FIXME: this function is currently only used by the QEMU driver that - * is not compiled on Windows, so it's okay for now to just - * miss an implementation */ - return -1; -} - -void virCondSignal(virCondPtr c) -{ - virMutexLock(&c->lock); - - if (c->nwaiters) { - HANDLE event = c->waiters[0]; - if (c->nwaiters > 1) - memmove(c->waiters, - c->waiters + 1, - sizeof(c->waiters[0]) * (c->nwaiters-1)); - if (VIR_REALLOC_N(c->waiters, c->nwaiters - 1) < 0) { - ; - } - c->nwaiters--; - SetEvent(event); - } - - virMutexUnlock(&c->lock); -} - -void virCondBroadcast(virCondPtr c) -{ - virMutexLock(&c->lock); - - if (c->nwaiters) { - 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); -} - - -struct virThreadArgs { - virThreadFunc func; - void *opaque; -}; - -static void virThreadHelperDaemon(void *data) -{ - struct virThreadArgs *args = data; - virThread self; - HANDLE handle = GetCurrentThread(); - HANDLE process = GetCurrentProcess(); - - self.joinable = false; - DuplicateHandle(process, handle, process, - &self.thread, 0, FALSE, - DUPLICATE_SAME_ACCESS); - TlsSetValue(selfkey, &self); - - args->func(args->opaque); - - TlsSetValue(selfkey, NULL); - CloseHandle(self.thread); - - VIR_FREE(args); -} - -static unsigned int __stdcall virThreadHelperJoinable(void *data) -{ - struct virThreadArgs *args = data; - virThread self; - HANDLE handle = GetCurrentThread(); - HANDLE process = GetCurrentProcess(); - - self.joinable = true; - DuplicateHandle(process, handle, process, - &self.thread, 0, FALSE, - DUPLICATE_SAME_ACCESS); - TlsSetValue(selfkey, &self); - - args->func(args->opaque); - - TlsSetValue(selfkey, NULL); - CloseHandle(self.thread); - - VIR_FREE(args); - return 0; -} - -int virThreadCreate(virThreadPtr thread, - bool joinable, - virThreadFunc func, - void *opaque) -{ - struct virThreadArgs *args; - uintptr_t ret; - - if (VIR_ALLOC(args) < 0) - return -1; - - args->func = func; - args->opaque = opaque; - - thread->joinable = joinable; - if (joinable) { - ret = _beginthreadex(NULL, 0, - virThreadHelperJoinable, - args, 0, NULL); - if (ret == 0) - return -1; - } else { - ret = _beginthread(virThreadHelperDaemon, - 0, args); - if (ret == -1L) - return -1; - } - - thread->thread = (HANDLE)ret; - - return 0; -} - -void virThreadSelf(virThreadPtr thread) -{ - virThreadPtr self = TlsGetValue(selfkey); - - if (self == NULL) { - /* called on a thread not created by virThreadCreate, e.g. the main thread */ - thread->thread = 0; - thread->joinable = false; - } else { - thread->thread = self->thread; - thread->joinable = self->joinable; - } -} - -bool virThreadIsSelf(virThreadPtr thread) -{ - virThread self; - virThreadSelf(&self); - return self.thread == thread->thread ? true : false; -} - -/* For debugging use only; see comments in threads-pthread.c. */ -int virThreadSelfID(void) -{ - return (int)GetCurrentThreadId(); -} - -/* For debugging use only; see comments in threads-pthread.c. */ -int virThreadID(virThreadPtr thread) -{ - return (intptr_t)thread->thread; -} - - -void virThreadJoin(virThreadPtr thread) -{ - if (thread->joinable) { - WaitForSingleObject(thread->thread, INFINITE); - CloseHandle(thread->thread); - thread->thread = 0; - thread->joinable = false; - } -} - - -int virThreadLocalInit(virThreadLocalPtr l, - virThreadLocalCleanup c) -{ - if ((l->key = TlsAlloc()) == TLS_OUT_OF_INDEXES) { - errno = ESRCH; - return -1; - } - TlsSetValue(l->key, NULL); - - if (c) { - virMutexLock(&virThreadLocalLock); - if (VIR_REALLOC_N(virThreadLocalList, - virThreadLocalCount + 1) < 0) - return -1; - virThreadLocalList[virThreadLocalCount].key = l->key; - virThreadLocalList[virThreadLocalCount].cleanup = c; - virThreadLocalCount++; - virMutexUnlock(&virThreadLocalLock); - } - - return 0; -} - -void *virThreadLocalGet(virThreadLocalPtr l) -{ - return TlsGetValue(l->key); -} - -int virThreadLocalSet(virThreadLocalPtr l, void *val) -{ - return TlsSetValue(l->key, val) == 0 ? -1 : 0; -} diff --git a/src/util/threads-win32.h b/src/util/threads-win32.h deleted file mode 100644 index 07a1bf5..0000000 --- a/src/util/threads-win32.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * threads-win32.h basic thread synchronization primitives - * - * Copyright (C) 2009, 2011-2012 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * <http://www.gnu.org/licenses/>. - * - */ - -#include "internal.h" - -#ifdef HAVE_WINSOCK2_H -# include <winsock2.h> -#endif -#include <windows.h> - -struct virMutex { - HANDLE lock; -}; - -struct virCond { - virMutex lock; - unsigned int nwaiters; - HANDLE *waiters; -}; - -struct virThread { - HANDLE thread; - bool joinable; -}; - -struct virThreadLocal { - DWORD key; -}; - -struct virOnceControl { - volatile long init; /* 0 at startup, > 0 if init has started */ - volatile long complete; /* 0 until first thread completes callback */ -}; - -#define VIR_ONCE_CONTROL_INITIALIZER { 0, 0 } diff --git a/src/util/threads.c b/src/util/threads.c deleted file mode 100644 index d0d5b83..0000000 --- a/src/util/threads.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * threads.c: basic thread synchronization primitives - * - * Copyright (C) 2009-2010 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * <http://www.gnu.org/licenses/>. - * - */ - -#include <config.h> - -#include "threads.h" - -/* On mingw, we prefer native threading over the sometimes-broken - * pthreads-win32 library wrapper. */ -#ifdef WIN32 -# include "threads-win32.c" -#elif defined HAVE_PTHREAD_MUTEXATTR_INIT -# include "threads-pthread.c" -#else -# error "Either pthreads or Win32 threads are required" -#endif diff --git a/src/util/threads.h b/src/util/threads.h deleted file mode 100644 index 9761764..0000000 --- a/src/util/threads.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * threads.h: basic thread synchronization primitives - * - * Copyright (C) 2009-2011 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see - * <http://www.gnu.org/licenses/>. - * - */ - -#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; - -typedef struct virThread virThread; -typedef virThread *virThreadPtr; - -typedef struct virOnceControl virOnceControl; -typedef virOnceControl *virOnceControlPtr; - -typedef void (*virOnceFunc)(void); - -int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK; -void virThreadOnExit(void); - -typedef void (*virThreadFunc)(void *opaque); - -int virThreadCreate(virThreadPtr thread, - bool joinable, - virThreadFunc func, - void *opaque) ATTRIBUTE_RETURN_CHECK; -void virThreadSelf(virThreadPtr thread); -bool virThreadIsSelf(virThreadPtr thread); -void virThreadJoin(virThreadPtr thread); - -/* These next two functions are for debugging only, since they are not - * guaranteed to give unique values for distinct threads on all - * architectures, nor are the two functions guaranteed to give the same - * value for the same thread. */ -int virThreadSelfID(void); -int virThreadID(virThreadPtr thread); - -/* Static initialization of mutexes is not possible, so we instead - * provide for guaranteed one-time initialization via a callback - * function. Usage: - * static virOnceControl once = VIR_ONCE_CONTROL_INITIALIZER; - * static void initializer(void) { ... } - * void myfunc() - * { - * if (virOnce(&once, initializer) < 0) - * goto error; - * ...now guaranteed that initializer has completed exactly once - * } - */ -int virOnce(virOnceControlPtr once, virOnceFunc init) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; - -int virMutexInit(virMutexPtr m) ATTRIBUTE_RETURN_CHECK; -int virMutexInitRecursive(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; - -/* virCondWait, virCondWaitUntil: - * These functions can return without the associated predicate - * changing value. Therefore in nearly all cases they - * should be enclosed in a while loop that checks the predicate. - */ -int virCondWait(virCondPtr c, virMutexPtr m) ATTRIBUTE_RETURN_CHECK; -int virCondWaitUntil(virCondPtr c, virMutexPtr m, unsigned long long whenms) 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); -int virThreadLocalSet(virThreadLocalPtr l, void*) ATTRIBUTE_RETURN_CHECK; - -# ifdef WIN32 -# include "threads-win32.h" -# elif defined HAVE_PTHREAD_MUTEXATTR_INIT -# include "threads-pthread.h" -# else -# error "Either pthreads or Win32 threads are required" -# endif - - -/** - * VIR_ONCE_GLOBAL_INIT: - * classname: base classname - * - * This macro simplifies the setup of a one-time only - * global file initializer. - * - * Assuming a class called "virMyObject", and a method - * implemented like: - * - * int virMyObjectOnceInit(void) { - * ...do init tasks... - * } - * - * Then invoking the macro: - * - * VIR_ONCE_GLOBAL_INIT(virMyObject) - * - * Will create a method - * - * int virMyObjectInitialize(void); - * - * Which will ensure that 'virMyObjectOnceInit' is - * guaranteed to be invoked exactly once. - */ -# define VIR_ONCE_GLOBAL_INIT(classname) \ - static virOnceControl classname ## OnceControl = VIR_ONCE_CONTROL_INITIALIZER; \ - static virErrorPtr classname ## OnceError = NULL; \ - \ - static void classname ## Once(void) \ - { \ - if (classname ## OnceInit() < 0) \ - classname ## OnceError = virSaveLastError(); \ - } \ - \ - static int classname ## Initialize(void) \ - { \ - if (virOnce(&classname ## OnceControl, classname ## Once) < 0) \ - return -1; \ - \ - if (classname ## OnceError) { \ - virSetError(classname ## OnceError); \ - return -1; \ - } \ - \ - return 0; \ - } - -#endif diff --git a/src/util/util.c b/src/util/util.c index 5d32995..c7d4aa5 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -81,7 +81,7 @@ #include "util.h" #include "virstoragefile.h" #include "viralloc.h" -#include "threads.h" +#include "virthread.h" #include "verify.h" #include "virfile.h" #include "vircommand.h" diff --git a/src/util/virdbus.c b/src/util/virdbus.c index 34c46b2..f45074c 100644 --- a/src/util/virdbus.c +++ b/src/util/virdbus.c @@ -25,7 +25,7 @@ #include "viralloc.h" #include "virterror_internal.h" #include "virlog.h" -#include "threads.h" +#include "virthread.h" #define VIR_FROM_THIS VIR_FROM_DBUS diff --git a/src/util/virebtables.c b/src/util/virebtables.c index 1beb085..edf4956 100644 --- a/src/util/virebtables.c +++ b/src/util/virebtables.c @@ -45,7 +45,7 @@ #include "viralloc.h" #include "virterror_internal.h" #include "virlog.h" -#include "threads.h" +#include "virthread.h" #if HAVE_FIREWALLD static char *firewall_cmd_path = NULL; diff --git a/src/util/vireventpoll.c b/src/util/vireventpoll.c index cf4dc41..1180fda 100644 --- a/src/util/vireventpoll.c +++ b/src/util/vireventpoll.c @@ -31,7 +31,7 @@ #include <unistd.h> #include <fcntl.h> -#include "threads.h" +#include "virthread.h" #include "virlog.h" #include "vireventpoll.h" #include "viralloc.h" diff --git a/src/util/viriptables.c b/src/util/viriptables.c index 178580d..eb8acf5 100644 --- a/src/util/viriptables.c +++ b/src/util/viriptables.c @@ -43,7 +43,7 @@ #include "viralloc.h" #include "virterror_internal.h" #include "virlog.h" -#include "threads.h" +#include "virthread.h" #if HAVE_FIREWALLD static char *firewall_cmd_path = NULL; diff --git a/src/util/virlockspace.c b/src/util/virlockspace.c index 509b162..961e171 100644 --- a/src/util/virlockspace.c +++ b/src/util/virlockspace.c @@ -28,7 +28,7 @@ #include "util.h" #include "virfile.h" #include "virhash.h" -#include "threads.h" +#include "virthread.h" #include <fcntl.h> #include <unistd.h> diff --git a/src/util/virlog.c b/src/util/virlog.c index cb15a22..0c6c13a 100644 --- a/src/util/virlog.c +++ b/src/util/virlog.c @@ -45,7 +45,7 @@ #include "viralloc.h" #include "util.h" #include "virbuffer.h" -#include "threads.h" +#include "virthread.h" #include "virfile.h" #include "virtime.h" #include "intprops.h" diff --git a/src/util/virnetlink.c b/src/util/virnetlink.c index b132d9a..fdd4c0d 100644 --- a/src/util/virnetlink.c +++ b/src/util/virnetlink.c @@ -38,7 +38,7 @@ #include "virnetlink.h" #include "virlog.h" #include "viralloc.h" -#include "threads.h" +#include "virthread.h" #include "virmacaddr.h" #include "virterror_internal.h" diff --git a/src/util/virnodesuspend.c b/src/util/virnodesuspend.c index 1528cf1..878be1d 100644 --- a/src/util/virnodesuspend.c +++ b/src/util/virnodesuspend.c @@ -23,7 +23,7 @@ #include "virnodesuspend.h" #include "vircommand.h" -#include "threads.h" +#include "virthread.h" #include "datatypes.h" #include "viralloc.h" diff --git a/src/util/virobject.c b/src/util/virobject.c index 5cdd2e8..aca6182 100644 --- a/src/util/virobject.c +++ b/src/util/virobject.c @@ -22,7 +22,7 @@ #include <config.h> #include "virobject.h" -#include "threads.h" +#include "virthread.h" #include "viralloc.h" #include "viratomic.h" #include "virterror_internal.h" diff --git a/src/util/virrandom.c b/src/util/virrandom.c index c24bf3b..1dd96cf 100644 --- a/src/util/virrandom.c +++ b/src/util/virrandom.c @@ -27,7 +27,7 @@ #include <strings.h> #include "virrandom.h" -#include "threads.h" +#include "virthread.h" #include "count-one-bits.h" #include "util.h" #include "virterror_internal.h" diff --git a/src/util/virterror.c b/src/util/virterror.c index ce2d837..6c773d3 100644 --- a/src/util/virterror.c +++ b/src/util/virterror.c @@ -31,7 +31,7 @@ #include "datatypes.h" #include "virlog.h" #include "viralloc.h" -#include "threads.h" +#include "virthread.h" #include "util.h" virThreadLocal virLastErr; diff --git a/src/util/virthread.c b/src/util/virthread.c new file mode 100644 index 0000000..a062fd6 --- /dev/null +++ b/src/util/virthread.c @@ -0,0 +1,34 @@ +/* + * threads.c: basic thread synchronization primitives + * + * Copyright (C) 2009-2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <config.h> + +#include "virthread.h" + +/* On mingw, we prefer native threading over the sometimes-broken + * pthreads-win32 library wrapper. */ +#ifdef WIN32 +# include "virthreadwin32.c" +#elif defined HAVE_PTHREAD_MUTEXATTR_INIT +# include "virthreadpthread.c" +#else +# error "Either pthreads or Win32 threads are required" +#endif diff --git a/src/util/virthread.h b/src/util/virthread.h new file mode 100644 index 0000000..90aa5ce --- /dev/null +++ b/src/util/virthread.h @@ -0,0 +1,166 @@ +/* + * threads.h: basic thread synchronization primitives + * + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#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; + +typedef struct virThread virThread; +typedef virThread *virThreadPtr; + +typedef struct virOnceControl virOnceControl; +typedef virOnceControl *virOnceControlPtr; + +typedef void (*virOnceFunc)(void); + +int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK; +void virThreadOnExit(void); + +typedef void (*virThreadFunc)(void *opaque); + +int virThreadCreate(virThreadPtr thread, + bool joinable, + virThreadFunc func, + void *opaque) ATTRIBUTE_RETURN_CHECK; +void virThreadSelf(virThreadPtr thread); +bool virThreadIsSelf(virThreadPtr thread); +void virThreadJoin(virThreadPtr thread); + +/* These next two functions are for debugging only, since they are not + * guaranteed to give unique values for distinct threads on all + * architectures, nor are the two functions guaranteed to give the same + * value for the same thread. */ +int virThreadSelfID(void); +int virThreadID(virThreadPtr thread); + +/* Static initialization of mutexes is not possible, so we instead + * provide for guaranteed one-time initialization via a callback + * function. Usage: + * static virOnceControl once = VIR_ONCE_CONTROL_INITIALIZER; + * static void initializer(void) { ... } + * void myfunc() + * { + * if (virOnce(&once, initializer) < 0) + * goto error; + * ...now guaranteed that initializer has completed exactly once + * } + */ +int virOnce(virOnceControlPtr once, virOnceFunc init) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK; + +int virMutexInit(virMutexPtr m) ATTRIBUTE_RETURN_CHECK; +int virMutexInitRecursive(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; + +/* virCondWait, virCondWaitUntil: + * These functions can return without the associated predicate + * changing value. Therefore in nearly all cases they + * should be enclosed in a while loop that checks the predicate. + */ +int virCondWait(virCondPtr c, virMutexPtr m) ATTRIBUTE_RETURN_CHECK; +int virCondWaitUntil(virCondPtr c, virMutexPtr m, unsigned long long whenms) 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); +int virThreadLocalSet(virThreadLocalPtr l, void*) ATTRIBUTE_RETURN_CHECK; + +# ifdef WIN32 +# include "virthreadwin32.h" +# elif defined HAVE_PTHREAD_MUTEXATTR_INIT +# include "virthreadpthread.h" +# else +# error "Either pthreads or Win32 threads are required" +# endif + + +/** + * VIR_ONCE_GLOBAL_INIT: + * classname: base classname + * + * This macro simplifies the setup of a one-time only + * global file initializer. + * + * Assuming a class called "virMyObject", and a method + * implemented like: + * + * int virMyObjectOnceInit(void) { + * ...do init tasks... + * } + * + * Then invoking the macro: + * + * VIR_ONCE_GLOBAL_INIT(virMyObject) + * + * Will create a method + * + * int virMyObjectInitialize(void); + * + * Which will ensure that 'virMyObjectOnceInit' is + * guaranteed to be invoked exactly once. + */ +# define VIR_ONCE_GLOBAL_INIT(classname) \ + static virOnceControl classname ## OnceControl = VIR_ONCE_CONTROL_INITIALIZER; \ + static virErrorPtr classname ## OnceError = NULL; \ + \ + static void classname ## Once(void) \ + { \ + if (classname ## OnceInit() < 0) \ + classname ## OnceError = virSaveLastError(); \ + } \ + \ + static int classname ## Initialize(void) \ + { \ + if (virOnce(&classname ## OnceControl, classname ## Once) < 0) \ + return -1; \ + \ + if (classname ## OnceError) { \ + virSetError(classname ## OnceError); \ + return -1; \ + } \ + \ + return 0; \ + } + +#endif diff --git a/src/util/virthreadpool.c b/src/util/virthreadpool.c index c13b078..307cefb 100644 --- a/src/util/virthreadpool.c +++ b/src/util/virthreadpool.c @@ -27,7 +27,7 @@ #include "virthreadpool.h" #include "viralloc.h" -#include "threads.h" +#include "virthread.h" #include "virterror_internal.h" #define VIR_FROM_THIS VIR_FROM_NONE diff --git a/src/util/virthreadpthread.c b/src/util/virthreadpthread.c new file mode 100644 index 0000000..37d8902 --- /dev/null +++ b/src/util/virthreadpthread.c @@ -0,0 +1,263 @@ +/* + * threads-pthread.c: basic thread synchronization primitives + * + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <config.h> + +#include <unistd.h> +#include <inttypes.h> +#if HAVE_SYS_SYSCALL_H +# include <sys/syscall.h> +#endif + +#include "viralloc.h" + + +/* Nothing special required for pthreads */ +int virThreadInitialize(void) +{ + return 0; +} + +void virThreadOnExit(void) +{ +} + +int virOnce(virOnceControlPtr once, virOnceFunc init) +{ + return pthread_once(&once->once, init); +} + + +int virMutexInit(virMutexPtr m) +{ + int ret; + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + ret = pthread_mutex_init(&m->lock, &attr); + pthread_mutexattr_destroy(&attr); + if (ret != 0) { + errno = ret; + return -1; + } + return 0; +} + +int virMutexInitRecursive(virMutexPtr m) +{ + int ret; + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); + ret = pthread_mutex_init(&m->lock, &attr); + pthread_mutexattr_destroy(&attr); + if (ret != 0) { + errno = ret; + return -1; + } + return 0; +} + +void virMutexDestroy(virMutexPtr m) +{ + pthread_mutex_destroy(&m->lock); +} + +void virMutexLock(virMutexPtr m){ + pthread_mutex_lock(&m->lock); +} + +void virMutexUnlock(virMutexPtr m) +{ + pthread_mutex_unlock(&m->lock); +} + + +int virCondInit(virCondPtr c) +{ + int ret; + if ((ret = pthread_cond_init(&c->cond, NULL)) != 0) { + errno = ret; + return -1; + } + return 0; +} + +int virCondDestroy(virCondPtr c) +{ + int ret; + if ((ret = pthread_cond_destroy(&c->cond)) != 0) { + errno = ret; + return -1; + } + return 0; +} + +int virCondWait(virCondPtr c, virMutexPtr m) +{ + int ret; + if ((ret = pthread_cond_wait(&c->cond, &m->lock)) != 0) { + errno = ret; + return -1; + } + return 0; +} + +int virCondWaitUntil(virCondPtr c, virMutexPtr m, unsigned long long whenms) +{ + int ret; + struct timespec ts; + + ts.tv_sec = whenms / 1000; + ts.tv_nsec = (whenms % 1000) * 1000; + + if ((ret = pthread_cond_timedwait(&c->cond, &m->lock, &ts)) != 0) { + errno = ret; + return -1; + } + return 0; +} + +void virCondSignal(virCondPtr c) +{ + pthread_cond_signal(&c->cond); +} + +void virCondBroadcast(virCondPtr c) +{ + pthread_cond_broadcast(&c->cond); +} + +struct virThreadArgs { + virThreadFunc func; + void *opaque; +}; + +static void *virThreadHelper(void *data) +{ + struct virThreadArgs *args = data; + struct virThreadArgs local = *args; + + /* Free args early, rather than tying it up during the entire thread. */ + VIR_FREE(args); + local.func(local.opaque); + return NULL; +} + +int virThreadCreate(virThreadPtr thread, + bool joinable, + virThreadFunc func, + void *opaque) +{ + struct virThreadArgs *args; + pthread_attr_t attr; + int ret = -1; + int err; + + if ((err = pthread_attr_init(&attr)) != 0) + goto cleanup; + if (VIR_ALLOC(args) < 0) { + err = ENOMEM; + goto cleanup; + } + + args->func = func; + args->opaque = opaque; + + if (!joinable) + pthread_attr_setdetachstate(&attr, 1); + + err = pthread_create(&thread->thread, &attr, virThreadHelper, args); + if (err != 0) { + VIR_FREE(args); + goto cleanup; + } + /* New thread owns 'args' in success case, so don't free */ + + ret = 0; +cleanup: + pthread_attr_destroy(&attr); + if (ret < 0) + errno = err; + return ret; +} + +void virThreadSelf(virThreadPtr thread) +{ + thread->thread = pthread_self(); +} + +bool virThreadIsSelf(virThreadPtr thread) +{ + return pthread_equal(pthread_self(), thread->thread) ? true : false; +} + +/* For debugging use only; this result is not guaranteed unique on BSD + * systems when pthread_t is a 64-bit pointer. */ +int virThreadSelfID(void) +{ +#if defined(HAVE_SYS_SYSCALL_H) && defined(SYS_gettid) + pid_t tid; + tid = syscall(SYS_gettid); + return (int)tid; +#else + return (int)(intptr_t)(void *)pthread_self(); +#endif +} + +/* For debugging use only; this result is not guaranteed unique on BSD + * systems when pthread_t is a 64-bit pointer, nor does it match the + * thread id of virThreadSelfID on Linux. */ +int virThreadID(virThreadPtr thread) +{ + return (int)(uintptr_t)thread->thread; +} + +void virThreadJoin(virThreadPtr thread) +{ + pthread_join(thread->thread, NULL); +} + +int virThreadLocalInit(virThreadLocalPtr l, + virThreadLocalCleanup c) +{ + int ret; + if ((ret = pthread_key_create(&l->key, c)) != 0) { + errno = ret; + return -1; + } + return 0; +} + +void *virThreadLocalGet(virThreadLocalPtr l) +{ + return pthread_getspecific(l->key); +} + +int virThreadLocalSet(virThreadLocalPtr l, void *val) +{ + int err = pthread_setspecific(l->key, val); + if (err) { + errno = err; + return -1; + } + return 0; +} diff --git a/src/util/virthreadpthread.h b/src/util/virthreadpthread.h new file mode 100644 index 0000000..ddaedb7 --- /dev/null +++ b/src/util/virthreadpthread.h @@ -0,0 +1,49 @@ +/* + * threads.c: basic thread synchronization primitives + * + * Copyright (C) 2009, 2011 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "internal.h" + +#include <pthread.h> + +struct virMutex { + pthread_mutex_t lock; +}; + +struct virCond { + pthread_cond_t cond; +}; + +struct virThread { + pthread_t thread; +}; + +struct virThreadLocal { + pthread_key_t key; +}; + +struct virOnceControl { + pthread_once_t once; +}; + +#define VIR_ONCE_CONTROL_INITIALIZER \ +{ \ + .once = PTHREAD_ONCE_INIT \ +} diff --git a/src/util/virthreadwin32.c b/src/util/virthreadwin32.c new file mode 100644 index 0000000..c9f16c1 --- /dev/null +++ b/src/util/virthreadwin32.c @@ -0,0 +1,392 @@ +/* + * threads-win32.c: basic thread synchronization primitives + * + * Copyright (C) 2009-2011 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <config.h> + +#include <process.h> + +#include "viralloc.h" + +struct virThreadLocalData { + DWORD key; + virThreadLocalCleanup cleanup; +}; +typedef struct virThreadLocalData virThreadLocalData; +typedef virThreadLocalData *virThreadLocalDataPtr; + +virMutex virThreadLocalLock; +unsigned int virThreadLocalCount = 0; +virThreadLocalDataPtr virThreadLocalList = NULL; +DWORD selfkey; + +virThreadLocal virCondEvent; + +void virCondEventCleanup(void *data); + +int virThreadInitialize(void) +{ + if (virMutexInit(&virThreadLocalLock) < 0) + return -1; + if (virThreadLocalInit(&virCondEvent, virCondEventCleanup) < 0) + return -1; + if ((selfkey = TlsAlloc()) == TLS_OUT_OF_INDEXES) + return -1; + return 0; +} + +void virThreadOnExit(void) +{ + 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 virOnce(virOnceControlPtr once, virOnceFunc func) +{ + if (!once->complete) { + if (InterlockedIncrement(&once->init) == 1) { + /* We're the first thread. */ + func(); + once->complete = 1; + } else { + /* We're a later thread. Decrement the init counter back + * to avoid overflow, then yield until the first thread + * marks that the function is complete. It is rare that + * multiple threads will be waiting here, and since each + * thread is yielding except the first, we should get out + * soon enough. */ + InterlockedDecrement(&once->init); + while (!once->complete) + Sleep(0); + } + } + return 0; +} + +int virMutexInit(virMutexPtr m) +{ + return virMutexInitRecursive(m); +} + +int virMutexInitRecursive(virMutexPtr m) +{ + if (!(m->lock = CreateMutex(NULL, FALSE, NULL))) { + errno = ESRCH; + return -1; + } + return 0; +} + +void virMutexDestroy(virMutexPtr m) +{ + CloseHandle(m->lock); +} + +void virMutexLock(virMutexPtr m) +{ + WaitForSingleObject(m->lock, INFINITE); +} + +void virMutexUnlock(virMutexPtr m) +{ + ReleaseMutex(m->lock); +} + + + +int virCondInit(virCondPtr c) +{ + c->waiters = NULL; + if (virMutexInit(&c->lock) < 0) + return -1; + return 0; +} + +int virCondDestroy(virCondPtr c) +{ + if (c->waiters) { + errno = EINVAL; + return -1; + } + virMutexDestroy(&c->lock); + return 0; +} + +void virCondEventCleanup(void *data) +{ + HANDLE event = data; + CloseHandle(event); +} + +int virCondWait(virCondPtr c, virMutexPtr m) +{ + HANDLE event = virThreadLocalGet(&virCondEvent); + + if (!event) { + event = CreateEvent(0, FALSE, FALSE, NULL); + if (!event) { + return -1; + } + if (virThreadLocalSet(&virCondEvent, event) < 0) { + CloseHandle(event); + return -1; + } + } + + virMutexLock(&c->lock); + + if (VIR_REALLOC_N(c->waiters, c->nwaiters + 1) < 0) { + virMutexUnlock(&c->lock); + return -1; + } + c->waiters[c->nwaiters] = event; + c->nwaiters++; + + virMutexUnlock(&c->lock); + + virMutexUnlock(m); + + if (WaitForSingleObject(event, INFINITE) == WAIT_FAILED) { + virMutexLock(m); + errno = EINVAL; + return -1; + } + + virMutexLock(m); + return 0; +} + +int virCondWaitUntil(virCondPtr c ATTRIBUTE_UNUSED, + virMutexPtr m ATTRIBUTE_UNUSED, + unsigned long long whenms ATTRIBUTE_UNUSED) +{ + /* FIXME: this function is currently only used by the QEMU driver that + * is not compiled on Windows, so it's okay for now to just + * miss an implementation */ + return -1; +} + +void virCondSignal(virCondPtr c) +{ + virMutexLock(&c->lock); + + if (c->nwaiters) { + HANDLE event = c->waiters[0]; + if (c->nwaiters > 1) + memmove(c->waiters, + c->waiters + 1, + sizeof(c->waiters[0]) * (c->nwaiters-1)); + if (VIR_REALLOC_N(c->waiters, c->nwaiters - 1) < 0) { + ; + } + c->nwaiters--; + SetEvent(event); + } + + virMutexUnlock(&c->lock); +} + +void virCondBroadcast(virCondPtr c) +{ + virMutexLock(&c->lock); + + if (c->nwaiters) { + 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); +} + + +struct virThreadArgs { + virThreadFunc func; + void *opaque; +}; + +static void virThreadHelperDaemon(void *data) +{ + struct virThreadArgs *args = data; + virThread self; + HANDLE handle = GetCurrentThread(); + HANDLE process = GetCurrentProcess(); + + self.joinable = false; + DuplicateHandle(process, handle, process, + &self.thread, 0, FALSE, + DUPLICATE_SAME_ACCESS); + TlsSetValue(selfkey, &self); + + args->func(args->opaque); + + TlsSetValue(selfkey, NULL); + CloseHandle(self.thread); + + VIR_FREE(args); +} + +static unsigned int __stdcall virThreadHelperJoinable(void *data) +{ + struct virThreadArgs *args = data; + virThread self; + HANDLE handle = GetCurrentThread(); + HANDLE process = GetCurrentProcess(); + + self.joinable = true; + DuplicateHandle(process, handle, process, + &self.thread, 0, FALSE, + DUPLICATE_SAME_ACCESS); + TlsSetValue(selfkey, &self); + + args->func(args->opaque); + + TlsSetValue(selfkey, NULL); + CloseHandle(self.thread); + + VIR_FREE(args); + return 0; +} + +int virThreadCreate(virThreadPtr thread, + bool joinable, + virThreadFunc func, + void *opaque) +{ + struct virThreadArgs *args; + uintptr_t ret; + + if (VIR_ALLOC(args) < 0) + return -1; + + args->func = func; + args->opaque = opaque; + + thread->joinable = joinable; + if (joinable) { + ret = _beginthreadex(NULL, 0, + virThreadHelperJoinable, + args, 0, NULL); + if (ret == 0) + return -1; + } else { + ret = _beginthread(virThreadHelperDaemon, + 0, args); + if (ret == -1L) + return -1; + } + + thread->thread = (HANDLE)ret; + + return 0; +} + +void virThreadSelf(virThreadPtr thread) +{ + virThreadPtr self = TlsGetValue(selfkey); + + if (self == NULL) { + /* called on a thread not created by virThreadCreate, e.g. the main thread */ + thread->thread = 0; + thread->joinable = false; + } else { + thread->thread = self->thread; + thread->joinable = self->joinable; + } +} + +bool virThreadIsSelf(virThreadPtr thread) +{ + virThread self; + virThreadSelf(&self); + return self.thread == thread->thread ? true : false; +} + +/* For debugging use only; see comments in threads-pthread.c. */ +int virThreadSelfID(void) +{ + return (int)GetCurrentThreadId(); +} + +/* For debugging use only; see comments in threads-pthread.c. */ +int virThreadID(virThreadPtr thread) +{ + return (intptr_t)thread->thread; +} + + +void virThreadJoin(virThreadPtr thread) +{ + if (thread->joinable) { + WaitForSingleObject(thread->thread, INFINITE); + CloseHandle(thread->thread); + thread->thread = 0; + thread->joinable = false; + } +} + + +int virThreadLocalInit(virThreadLocalPtr l, + virThreadLocalCleanup c) +{ + if ((l->key = TlsAlloc()) == TLS_OUT_OF_INDEXES) { + errno = ESRCH; + return -1; + } + TlsSetValue(l->key, NULL); + + if (c) { + virMutexLock(&virThreadLocalLock); + if (VIR_REALLOC_N(virThreadLocalList, + virThreadLocalCount + 1) < 0) + return -1; + virThreadLocalList[virThreadLocalCount].key = l->key; + virThreadLocalList[virThreadLocalCount].cleanup = c; + virThreadLocalCount++; + virMutexUnlock(&virThreadLocalLock); + } + + return 0; +} + +void *virThreadLocalGet(virThreadLocalPtr l) +{ + return TlsGetValue(l->key); +} + +int virThreadLocalSet(virThreadLocalPtr l, void *val) +{ + return TlsSetValue(l->key, val) == 0 ? -1 : 0; +} diff --git a/src/util/virthreadwin32.h b/src/util/virthreadwin32.h new file mode 100644 index 0000000..07a1bf5 --- /dev/null +++ b/src/util/virthreadwin32.h @@ -0,0 +1,53 @@ +/* + * threads-win32.h basic thread synchronization primitives + * + * Copyright (C) 2009, 2011-2012 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "internal.h" + +#ifdef HAVE_WINSOCK2_H +# include <winsock2.h> +#endif +#include <windows.h> + +struct virMutex { + HANDLE lock; +}; + +struct virCond { + virMutex lock; + unsigned int nwaiters; + HANDLE *waiters; +}; + +struct virThread { + HANDLE thread; + bool joinable; +}; + +struct virThreadLocal { + DWORD key; +}; + +struct virOnceControl { + volatile long init; /* 0 at startup, > 0 if init has started */ + volatile long complete; /* 0 until first thread completes callback */ +}; + +#define VIR_ONCE_CONTROL_INITIALIZER { 0, 0 } diff --git a/src/vmware/vmware_conf.h b/src/vmware/vmware_conf.h index b7a35a3..22d5240 100644 --- a/src/vmware/vmware_conf.h +++ b/src/vmware/vmware_conf.h @@ -25,7 +25,7 @@ # include "internal.h" # include "domain_conf.h" -# include "threads.h" +# include "virthread.h" # define VIR_FROM_THIS VIR_FROM_VMWARE # define PROGRAM_SENTINAL ((char *)0x1) diff --git a/src/xen/xen_hypervisor.c b/src/xen/xen_hypervisor.c index b308605..5c8fe37 100644 --- a/src/xen/xen_hypervisor.c +++ b/src/xen/xen_hypervisor.c @@ -77,7 +77,7 @@ #include "virbuffer.h" #include "capabilities.h" #include "viralloc.h" -#include "threads.h" +#include "virthread.h" #include "virfile.h" #include "virnodesuspend.h" #include "virtypedparam.h" diff --git a/tests/eventtest.c b/tests/eventtest.c index cd36a2d..6d00ea8 100644 --- a/tests/eventtest.c +++ b/tests/eventtest.c @@ -28,7 +28,7 @@ #include "testutils.h" #include "internal.h" -#include "threads.h" +#include "virthread.h" #include "virlog.h" #include "util.h" #include "vireventpoll.h" diff --git a/tests/nwfilterxml2xmltest.c b/tests/nwfilterxml2xmltest.c index 224ca93..8c29a46 100644 --- a/tests/nwfilterxml2xmltest.c +++ b/tests/nwfilterxml2xmltest.c @@ -11,7 +11,7 @@ #include "internal.h" #include "testutils.h" #include "xml.h" -#include "threads.h" +#include "virthread.h" #include "nwfilter_params.h" #include "nwfilter_conf.h" #include "testutilsqemu.h" diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index 264c140..e1b6c56 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -22,7 +22,7 @@ #include "testutils.h" #include "testutilsqemu.h" #include "qemumonitortestutils.h" -#include "threads.h" +#include "virthread.h" #include "virterror_internal.h" diff --git a/tests/qemumonitortestutils.c b/tests/qemumonitortestutils.c index 1e3f0da..cc38803 100644 --- a/tests/qemumonitortestutils.c +++ b/tests/qemumonitortestutils.c @@ -26,7 +26,7 @@ #include "qemumonitortestutils.h" -#include "threads.h" +#include "virthread.h" #include "qemu/qemu_monitor.h" #include "rpc/virnetsocket.h" #include "viralloc.h" diff --git a/tests/testutils.c b/tests/testutils.c index 7bb88f0..c6b1d23 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -41,7 +41,7 @@ #include "internal.h" #include "viralloc.h" #include "util.h" -#include "threads.h" +#include "virthread.h" #include "virterror_internal.h" #include "virbuffer.h" #include "virlog.h" diff --git a/tests/viratomictest.c b/tests/viratomictest.c index 88f387b..1ed1707 100644 --- a/tests/viratomictest.c +++ b/tests/viratomictest.c @@ -26,7 +26,7 @@ #include "viratomic.h" #include "virrandom.h" -#include "threads.h" +#include "virthread.h" static int testTypes(const void *data ATTRIBUTE_UNUSED) diff --git a/tools/console.c b/tools/console.c index 1d21189..d031308 100644 --- a/tools/console.c +++ b/tools/console.c @@ -42,7 +42,7 @@ # include "util.h" # include "virfile.h" # include "viralloc.h" -# include "threads.h" +# include "virthread.h" # include "virterror_internal.h" /* diff --git a/tools/virsh.c b/tools/virsh.c index e894aff..91a9677 100644 --- a/tools/virsh.c +++ b/tools/virsh.c @@ -64,7 +64,7 @@ #include "libvirt/libvirt-qemu.h" #include "virfile.h" #include "configmake.h" -#include "threads.h" +#include "virthread.h" #include "vircommand.h" #include "virkeycode.h" #include "virnetdevbandwidth.h" diff --git a/tools/virsh.h b/tools/virsh.h index 6913ed1..6e6d3ee 100644 --- a/tools/virsh.h +++ b/tools/virsh.h @@ -35,7 +35,7 @@ # include "internal.h" # include "virterror_internal.h" -# include "threads.h" +# include "virthread.h" # include "virnetdevbandwidth.h" # define VSH_MAX_XML_FILE (10*1024*1024) -- 1.7.11.7 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list