From: John Koleszar Date: Wed, 10 Oct 2012 19:30:16 +0000 (-0700) Subject: rtcd: merge rtcd.c from master X-Git-Tag: v1.3.0~1217^2~220^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=47dcdf11b9532f1a22f1f2d48c17632271fa3f1c;p=libvpx rtcd: merge rtcd.c from master Pick up changes to multithreading and once() implementations. Change-Id: I4a98df6b714f3208643798e0e7f74e373a7931e3 --- 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 +#include +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 +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); }