summaryrefslogtreecommitdiff
path: root/vp8/common/rtcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'vp8/common/rtcd.c')
-rw-r--r--vp8/common/rtcd.c91
1 files changed, 83 insertions, 8 deletions
diff --git a/vp8/common/rtcd.c b/vp8/common/rtcd.c
index a7bb92ce4..01dad4691 100644
--- a/vp8/common/rtcd.c
+++ b/vp8/common/rtcd.c
@@ -11,20 +11,95 @@
#define RTCD_C
#include "vpx_rtcd.h"
+#if CONFIG_MULTITHREAD && defined(_WIN32)
+#include <windows.h>
+#include <stdlib.h>
+static void once(void (*func)(void))
+{
+ static CRITICAL_SECTION *lock;
+ static LONG waiters;
+ static int done;
+ void *lock_ptr = &lock;
+
+ /* If the initialization is complete, return early. This isn't just an
+ * optimization, it prevents races on the destruction of the global
+ * lock.
+ */
+ if(done)
+ return;
+
+ InterlockedIncrement(&waiters);
+
+ /* Get a lock. We create one and try to make it the one-true-lock,
+ * throwing it away if we lost the race.
+ */
+
+ {
+ /* Scope to protect access to new_lock */
+ CRITICAL_SECTION *new_lock = malloc(sizeof(CRITICAL_SECTION));
+ InitializeCriticalSection(new_lock);
+ if (InterlockedCompareExchangePointer(lock_ptr, new_lock, NULL) != NULL)
+ {
+ DeleteCriticalSection(new_lock);
+ free(new_lock);
+ }
+ }
+
+ /* At this point, we have a lock that can be synchronized on. We don't
+ * care which thread actually performed the allocation.
+ */
+
+ EnterCriticalSection(lock);
+
+ if (!done)
+ {
+ func();
+ done = 1;
+ }
+
+ LeaveCriticalSection(lock);
+
+ /* Last one out should free resources. The destructed objects are
+ * protected by checking if(done) above.
+ */
+ if(!InterlockedDecrement(&waiters))
+ {
+ DeleteCriticalSection(lock);
+ free(lock);
+ lock = NULL;
+ }
+}
+
+
+#elif CONFIG_MULTITHREAD && HAVE_PTHREAD_H
+#include <pthread.h>
+static void once(void (*func)(void))
+{
+ static pthread_once_t lock = PTHREAD_ONCE_INIT;
+ pthread_once(&lock, func);
+}
+
+
+#else
/* No-op version that performs no synchronization. vpx_rtcd() is idempotent,
* so as long as your platform provides atomic loads/stores of pointers
* no synchronization is strictly necessary.
*/
-static void once(void (*func)(void)) {
- static int done;
+static void once(void (*func)(void))
+{
+ static int done;
- if(!done) {
- func();
- done = 1;
- }
+ if(!done)
+ {
+ func();
+ done = 1;
+ }
}
+#endif
+
-void vpx_rtcd() {
- once(setup_rtcd_internal);
+void vpx_rtcd()
+{
+ once(setup_rtcd_internal);
}