mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-24 14:45:24 +00:00
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
This commit is contained in:
parent
bdb28f4426
commit
64d6750709
@ -722,6 +722,10 @@ virMutexInit;
|
||||
virMutexInitRecursive;
|
||||
virMutexLock;
|
||||
virMutexUnlock;
|
||||
virThreadCreate;
|
||||
virThreadIsSelf;
|
||||
virThreadJoin;
|
||||
virThreadSelf;
|
||||
|
||||
|
||||
# usb.h
|
||||
|
@ -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)
|
||||
|
@ -31,6 +31,10 @@ struct virCond {
|
||||
pthread_cond_t cond;
|
||||
};
|
||||
|
||||
struct virThread {
|
||||
pthread_t thread;
|
||||
};
|
||||
|
||||
struct virThreadLocal {
|
||||
pthread_key_t key;
|
||||
};
|
||||
|
@ -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)
|
||||
|
@ -33,6 +33,10 @@ struct virCond {
|
||||
HANDLE *waiters;
|
||||
};
|
||||
|
||||
struct virThread {
|
||||
HANDLE thread;
|
||||
bool joinable;
|
||||
};
|
||||
|
||||
struct virThreadLocal {
|
||||
DWORD key;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user