threads: add one-time initialization support
mingw lacks the counterpart to PTHREAD_MUTEX_INITIALIZER, so the best we can do is portably expose once-only runtime initialization. * src/util/threads.h (virOnceControlPtr): New opaque type. (virOnceFunc): New callback type. (virOnce): New prototype. * src/util/threads-pthread.h (virOnceControl): Declare. (VIR_ONCE_CONTROL_INITIALIZER): Define. * src/util/threads-win32.h (virOnceControl) (VIR_ONCE_CONTROL_INITIALIZER): Likewise. * src/util/threads-pthread.c (virOnce): Implement in pthreads. * src/util/threads-win32.c (virOnce): Implement in WIN32. * src/libvirt_private.syms: Export it.
This commit is contained in:
parent
061956ccc7
commit
99de59900a
@ -866,6 +866,7 @@ virMutexInit;
|
|||||||
virMutexInitRecursive;
|
virMutexInitRecursive;
|
||||||
virMutexLock;
|
virMutexLock;
|
||||||
virMutexUnlock;
|
virMutexUnlock;
|
||||||
|
virOnce;
|
||||||
virThreadCreate;
|
virThreadCreate;
|
||||||
virThreadID;
|
virThreadID;
|
||||||
virThreadIsSelf;
|
virThreadIsSelf;
|
||||||
|
@ -40,6 +40,11 @@ void virThreadOnExit(void)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int virOnce(virOnceControlPtr once, virOnceFunc init)
|
||||||
|
{
|
||||||
|
return pthread_once(&once->once, init);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int virMutexInit(virMutexPtr m)
|
int virMutexInit(virMutexPtr m)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* threads.c: basic thread synchronization primitives
|
* threads.c: basic thread synchronization primitives
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Red Hat, Inc.
|
* Copyright (C) 2009, 2011 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -38,3 +38,12 @@ struct virThread {
|
|||||||
struct virThreadLocal {
|
struct virThreadLocal {
|
||||||
pthread_key_t key;
|
pthread_key_t key;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct virOnceControl {
|
||||||
|
pthread_once_t once;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VIR_ONCE_CONTROL_INITIALIZER \
|
||||||
|
{ \
|
||||||
|
.once = PTHREAD_ONCE_INIT \
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* threads-win32.c: basic thread synchronization primitives
|
* threads-win32.c: basic thread synchronization primitives
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009-2010 Red Hat, Inc.
|
* Copyright (C) 2009-2011 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -69,6 +69,27 @@ void virThreadOnExit(void)
|
|||||||
virMutexUnlock(&virThreadLocalLock);
|
virMutexUnlock(&virThreadLocalLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int virOnce(virOnceControlPtr once, virOnceFunc func)
|
||||||
|
{
|
||||||
|
if (!once->complete) {
|
||||||
|
if (InterlockedIncrement(&once->init) == 1) {
|
||||||
|
/* We're the first thread. */
|
||||||
|
func();
|
||||||
|
once->complete = 1;
|
||||||
|
} else {
|
||||||
|
/* We're a later thread. Decrement the init counter back
|
||||||
|
* to avoid overflow, then yield until the first thread
|
||||||
|
* marks that the function is complete. It is rare that
|
||||||
|
* multiple threads will be waiting here, and since each
|
||||||
|
* thread is yielding except the first, we should get out
|
||||||
|
* soon enough. */
|
||||||
|
InterlockedDecrement(&once->init);
|
||||||
|
while (!once->complete)
|
||||||
|
Sleep(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int virMutexInit(virMutexPtr m)
|
int virMutexInit(virMutexPtr m)
|
||||||
{
|
{
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* threads-win32.h basic thread synchronization primitives
|
* threads-win32.h basic thread synchronization primitives
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 Red Hat, Inc.
|
* Copyright (C) 2009, 2011 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -41,3 +41,10 @@ struct virThread {
|
|||||||
struct virThreadLocal {
|
struct virThreadLocal {
|
||||||
DWORD key;
|
DWORD key;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct virOnceControl {
|
||||||
|
volatile long init; /* 0 at startup, > 0 if init has started */
|
||||||
|
volatile long complete; /* 0 until first thread completes callback */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define VIR_ONCE_CONTROL_INITIALIZER { 0, 0 }
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* threads.h: basic thread synchronization primitives
|
* threads.h: basic thread synchronization primitives
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009-2010 Red Hat, Inc.
|
* Copyright (C) 2009-2011 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -36,6 +36,10 @@ typedef virThreadLocal *virThreadLocalPtr;
|
|||||||
typedef struct virThread virThread;
|
typedef struct virThread virThread;
|
||||||
typedef virThread *virThreadPtr;
|
typedef virThread *virThreadPtr;
|
||||||
|
|
||||||
|
typedef struct virOnceControl virOnceControl;
|
||||||
|
typedef virOnceControl *virOnceControlPtr;
|
||||||
|
|
||||||
|
typedef void (*virOnceFunc)(void);
|
||||||
|
|
||||||
int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK;
|
int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK;
|
||||||
void virThreadOnExit(void);
|
void virThreadOnExit(void);
|
||||||
@ -57,6 +61,21 @@ void virThreadJoin(virThreadPtr thread);
|
|||||||
int virThreadSelfID(void);
|
int virThreadSelfID(void);
|
||||||
int virThreadID(virThreadPtr thread);
|
int virThreadID(virThreadPtr thread);
|
||||||
|
|
||||||
|
/* Static initialization of mutexes is not possible, so we instead
|
||||||
|
* provide for guaranteed one-time initialization via a callback
|
||||||
|
* function. Usage:
|
||||||
|
* static virOnceControl once = VIR_ONCE_CONTROL_INITIALIZER;
|
||||||
|
* static void initializer(void) { ... }
|
||||||
|
* void myfunc()
|
||||||
|
* {
|
||||||
|
* if (virOnce(&once, initializer) < 0)
|
||||||
|
* goto error;
|
||||||
|
* ...now guaranteed that initializer has completed exactly once
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
int virOnce(virOnceControlPtr once, virOnceFunc init)
|
||||||
|
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
|
||||||
|
|
||||||
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