rtcd: merge rtcd.c from master
Pick up changes to multithreading and once() implementations. Change-Id: I4a98df6b714f3208643798e0e7f74e373a7931e3
This commit is contained in:
parent
d94d2b75ea
commit
47dcdf11b9
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user