]> xenbits.xensource.com Git - libvirt.git/commitdiff
Introduce portability APIs for creating threads
authorDaniel P. Berrange <berrange@redhat.com>
Tue, 2 Nov 2010 17:17:47 +0000 (17:17 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Thu, 11 Nov 2010 16:03:09 +0000 (16:03 +0000)
The util/threads.c/h code already has APIs for mutexes,
condition variables and thread locals. This commit adds
in code for actually creating threads.

* src/libvirt_private.syms: Export new symbols
* src/util/threads.h: Define APIs virThreadCreate, virThreadSelf,
  virThreadIsSelf and virThreadJoin
* src/util/threads-win32.c, src/util/threads-win32.h: Win32
  impl of threads
* src/util/threads-pthread.c, src/util/threads-pthread.h: POSIX
  impl of threads

src/libvirt_private.syms
src/util/threads-pthread.c
src/util/threads-pthread.h
src/util/threads-win32.c
src/util/threads-win32.h
src/util/threads.h

index a4c41e4401cc8ddc03a06fd840ddfabc3cba0455..0b9794c8fdad724360a4e9e431c71118f624ce36 100644 (file)
@@ -722,6 +722,10 @@ virMutexInit;
 virMutexInitRecursive;
 virMutexLock;
 virMutexUnlock;
+virThreadCreate;
+virThreadIsSelf;
+virThreadJoin;
+virThreadSelf;
 
 
 # usb.h
index 030b33fcafbf324b986067324809ab1600a28d88..34d9ce847483defa75e8305dbe85848e0590728d 100644 (file)
@@ -129,6 +129,51 @@ void virCondBroadcast(virCondPtr c)
     pthread_cond_broadcast(&c->cond);
 }
 
+struct virThreadArgs {
+    virThreadFunc func;
+    void *opaque;
+};
+
+static void *virThreadHelper(void *data)
+{
+    struct virThreadArgs *args = data;
+    args->func(args->opaque);
+    return NULL;
+}
+
+int virThreadCreate(virThreadPtr thread,
+                    bool joinable,
+                    virThreadFunc func,
+                    void *opaque)
+{
+    struct virThreadArgs args = { func, opaque };
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    if (!joinable)
+        pthread_attr_setdetachstate(&attr, 1);
+
+    int ret = pthread_create(&thread->thread, &attr, virThreadHelper, &args);
+    if (ret != 0) {
+        errno = ret;
+        return -1;
+    }
+    return 0;
+}
+
+void virThreadSelf(virThreadPtr thread)
+{
+    thread->thread = pthread_self();
+}
+
+bool virThreadIsSelf(virThreadPtr thread)
+{
+    return pthread_equal(pthread_self(), thread->thread) ? true : false;
+}
+
+void virThreadJoin(virThreadPtr thread)
+{
+    pthread_join(thread->thread, NULL);
+}
 
 int virThreadLocalInit(virThreadLocalPtr l,
                        virThreadLocalCleanup c)
index 6404d1dccbc2ad555c738233dc3e2334e1a6f130..b25d0c20e7c18ab56c157b6f2e028563b68b2aa0 100644 (file)
@@ -31,6 +31,10 @@ struct virCond {
     pthread_cond_t cond;
 };
 
+struct virThread {
+    pthread_t thread;
+};
+
 struct virThreadLocal {
     pthread_key_t key;
 };
index fe1fcd062781b18dd7a6c719422adfb943c8a3c5..de73fd56857a03a2a5bd7febec7db9c33c930fa6 100644 (file)
@@ -21,6 +21,8 @@
 
 #include <config.h>
 
+#include <process.h>
+
 #include "memory.h"
 
 struct virThreadLocalData {
@@ -33,7 +35,7 @@ typedef virThreadLocalData *virThreadLocalDataPtr;
 virMutex virThreadLocalLock;
 unsigned int virThreadLocalCount = 0;
 virThreadLocalDataPtr virThreadLocalList = NULL;
-
+DWORD selfkey;
 
 virThreadLocal virCondEvent;
 
@@ -45,7 +47,8 @@ int virThreadInitialize(void)
         return -1;
     if (virThreadLocalInit(&virCondEvent, virCondEventCleanup) < 0)
         return -1;
-
+    if ((selfkey = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+        return -1;
     return 0;
 }
 
@@ -205,6 +208,96 @@ void virCondBroadcast(virCondPtr c)
 }
 
 
+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);
+}
+
+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);
+    return 0;
+}
+
+int virThreadCreate(virThreadPtr thread,
+                    bool joinable,
+                    virThreadFunc func,
+                    void *opaque)
+{
+    struct virThreadArgs args = { func, opaque };
+    thread->joinable = joinable;
+    if (joinable) {
+        thread->thread = (HANDLE)_beginthreadex(NULL, 0,
+                                                virThreadHelperJoinable,
+                                                &args, 0, NULL);
+        if (thread->thread == 0)
+            return -1;
+    } else {
+        thread->thread = (HANDLE)_beginthread(virThreadHelperDaemon,
+                                              0, &args);
+        if (thread->thread == (HANDLE)-1L)
+            return -1;
+    }
+    return 0;
+}
+
+void virThreadSelf(virThreadPtr thread)
+{
+    virThreadPtr self = TlsGetValue(selfkey);
+    thread->thread = self->thread;
+    thread->joinable = self->joinable;
+}
+
+bool virThreadIsSelf(virThreadPtr thread)
+{
+    virThread self;
+    virThreadSelf(&self);
+    return self.thread == thread->thread ? true : false;
+}
+
+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)
index 783d91d7eb6848f5d6b0a074b397b87150399e82..bb7c455e968e63580f118abf20fe40bb69de4c6e 100644 (file)
@@ -33,6 +33,10 @@ struct virCond {
     HANDLE *waiters;
 };
 
+struct virThread {
+    HANDLE thread;
+    bool joinable;
+};
 
 struct virThreadLocal {
     DWORD key;
index db54ea011d21638b0de6f5a3b836e94bafe4acd0..b3b827d3e538c4dff36e2ea731d12eb24edb6c8e 100644 (file)
@@ -22,6 +22,8 @@
 #ifndef __THREADS_H_
 # define __THREADS_H_
 
+# include <stdbool.h>
+
 # include "internal.h"
 
 typedef struct virMutex virMutex;
@@ -33,10 +35,23 @@ typedef virCond *virCondPtr;
 typedef struct virThreadLocal virThreadLocal;
 typedef virThreadLocal *virThreadLocalPtr;
 
+typedef struct virThread virThread;
+typedef virThread *virThreadPtr;
+
 
 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);
+
 int virMutexInit(virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
 int virMutexInitRecursive(virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
 void virMutexDestroy(virMutexPtr m);