virMutexInitRecursive;
virMutexLock;
virMutexUnlock;
+virOnce;
virThreadCreate;
virThreadID;
virThreadIsSelf;
{
}
+int virOnce(virOnceControlPtr once, virOnceFunc init)
+{
+ return pthread_once(&once->once, init);
+}
+
int virMutexInit(virMutexPtr m)
{
/*
* 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
* modify it under the terms of the GNU Lesser General Public
struct virThreadLocal {
pthread_key_t key;
};
+
+struct virOnceControl {
+ pthread_once_t once;
+};
+
+#define VIR_ONCE_CONTROL_INITIALIZER \
+{ \
+ .once = PTHREAD_ONCE_INIT \
+}
/*
* 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
* modify it under the terms of the GNU Lesser General Public
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)
{
/*
* 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
* modify it under the terms of the GNU Lesser General Public
struct virThreadLocal {
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 }
/*
* 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
* modify it under the terms of the GNU Lesser General Public
typedef struct virThread virThread;
typedef virThread *virThreadPtr;
+typedef struct virOnceControl virOnceControl;
+typedef virOnceControl *virOnceControlPtr;
+
+typedef void (*virOnceFunc)(void);
int virThreadInitialize(void) ATTRIBUTE_RETURN_CHECK;
void virThreadOnExit(void);
int virThreadSelfID(void);
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 virMutexInitRecursive(virMutexPtr m) ATTRIBUTE_RETURN_CHECK;
void virMutexDestroy(virMutexPtr m);