提交 64d67507 编写于 作者: D Daniel P. Berrange

Introduce portability APIs for creating threads

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
上级 bdb28f44
...@@ -722,6 +722,10 @@ virMutexInit; ...@@ -722,6 +722,10 @@ virMutexInit;
virMutexInitRecursive; virMutexInitRecursive;
virMutexLock; virMutexLock;
virMutexUnlock; virMutexUnlock;
virThreadCreate;
virThreadIsSelf;
virThreadJoin;
virThreadSelf;
# usb.h # usb.h
......
...@@ -129,6 +129,51 @@ void virCondBroadcast(virCondPtr c) ...@@ -129,6 +129,51 @@ void virCondBroadcast(virCondPtr c)
pthread_cond_broadcast(&c->cond); 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, int virThreadLocalInit(virThreadLocalPtr l,
virThreadLocalCleanup c) virThreadLocalCleanup c)
......
...@@ -31,6 +31,10 @@ struct virCond { ...@@ -31,6 +31,10 @@ struct virCond {
pthread_cond_t cond; pthread_cond_t cond;
}; };
struct virThread {
pthread_t thread;
};
struct virThreadLocal { struct virThreadLocal {
pthread_key_t key; pthread_key_t key;
}; };
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#include <config.h> #include <config.h>
#include <process.h>
#include "memory.h" #include "memory.h"
struct virThreadLocalData { struct virThreadLocalData {
...@@ -33,7 +35,7 @@ typedef virThreadLocalData *virThreadLocalDataPtr; ...@@ -33,7 +35,7 @@ typedef virThreadLocalData *virThreadLocalDataPtr;
virMutex virThreadLocalLock; virMutex virThreadLocalLock;
unsigned int virThreadLocalCount = 0; unsigned int virThreadLocalCount = 0;
virThreadLocalDataPtr virThreadLocalList = NULL; virThreadLocalDataPtr virThreadLocalList = NULL;
DWORD selfkey;
virThreadLocal virCondEvent; virThreadLocal virCondEvent;
...@@ -45,7 +47,8 @@ int virThreadInitialize(void) ...@@ -45,7 +47,8 @@ int virThreadInitialize(void)
return -1; return -1;
if (virThreadLocalInit(&virCondEvent, virCondEventCleanup) < 0) if (virThreadLocalInit(&virCondEvent, virCondEventCleanup) < 0)
return -1; return -1;
if ((selfkey = TlsAlloc()) == TLS_OUT_OF_INDEXES)
return -1;
return 0; return 0;
} }
...@@ -205,6 +208,96 @@ void virCondBroadcast(virCondPtr c) ...@@ -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, int virThreadLocalInit(virThreadLocalPtr l,
virThreadLocalCleanup c) virThreadLocalCleanup c)
......
...@@ -33,6 +33,10 @@ struct virCond { ...@@ -33,6 +33,10 @@ struct virCond {
HANDLE *waiters; HANDLE *waiters;
}; };
struct virThread {
HANDLE thread;
bool joinable;
};
struct virThreadLocal { struct virThreadLocal {
DWORD key; DWORD key;
......
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#ifndef __THREADS_H_ #ifndef __THREADS_H_
# define __THREADS_H_ # define __THREADS_H_
# include <stdbool.h>
# include "internal.h" # include "internal.h"
typedef struct virMutex virMutex; typedef struct virMutex virMutex;
...@@ -33,10 +35,23 @@ typedef virCond *virCondPtr; ...@@ -33,10 +35,23 @@ typedef virCond *virCondPtr;
typedef struct virThreadLocal virThreadLocal; typedef struct virThreadLocal virThreadLocal;
typedef virThreadLocal *virThreadLocalPtr; typedef virThreadLocal *virThreadLocalPtr;
typedef struct virThread virThread;
typedef virThread *virThreadPtr;
int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK; int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK;
void virThreadOnExit(void); 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 virMutexInit(virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
int virMutexInitRecursive(virMutexPtr m) ATTRIBUTE_RETURN_CHECK; int virMutexInitRecursive(virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
void virMutexDestroy(virMutexPtr m); void virMutexDestroy(virMutexPtr m);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册