mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-25 22:15:20 +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;
|
virMutexInitRecursive;
|
||||||
virMutexLock;
|
virMutexLock;
|
||||||
virMutexUnlock;
|
virMutexUnlock;
|
||||||
|
virThreadCreate;
|
||||||
|
virThreadIsSelf;
|
||||||
|
virThreadJoin;
|
||||||
|
virThreadSelf;
|
||||||
|
|
||||||
|
|
||||||
# usb.h
|
# usb.h
|
||||||
|
@ -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 {
|
|||||||
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 @@
|
|||||||
|
|
||||||
#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;
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 {
|
|||||||
HANDLE *waiters;
|
HANDLE *waiters;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct virThread {
|
||||||
|
HANDLE thread;
|
||||||
|
bool joinable;
|
||||||
|
};
|
||||||
|
|
||||||
struct virThreadLocal {
|
struct virThreadLocal {
|
||||||
DWORD key;
|
DWORD key;
|
||||||
|
@ -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;
|
|||||||
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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user