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:
Daniel P. Berrange 2010-11-02 17:17:47 +00:00
parent bdb28f4426
commit 64d6750709
6 changed files with 167 additions and 2 deletions

View File

@ -722,6 +722,10 @@ virMutexInit;
virMutexInitRecursive;
virMutexLock;
virMutexUnlock;
virThreadCreate;
virThreadIsSelf;
virThreadJoin;
virThreadSelf;
# usb.h

View 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)

View File

@ -31,6 +31,10 @@ struct virCond {
pthread_cond_t cond;
};
struct virThread {
pthread_t thread;
};
struct virThreadLocal {
pthread_key_t key;
};

View 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)

View File

@ -33,6 +33,10 @@ struct virCond {
HANDLE *waiters;
};
struct virThread {
HANDLE thread;
bool joinable;
};
struct virThreadLocal {
DWORD key;

View 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);