| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2011 The WebM project authors. All Rights Reserved. | 2 * Copyright (c) 2011 The WebM project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 #include "vpx_config.h" | 10 #include "vpx_config.h" |
| 11 #define RTCD_C | 11 #define RTCD_C |
| 12 #include "vpx_rtcd.h" | 12 #include "vp8_rtcd.h" |
| 13 #include "vpx_ports/vpx_once.h" |
| 13 | 14 |
| 14 #if CONFIG_MULTITHREAD && defined(_WIN32) | 15 extern void vpx_scale_rtcd(void); |
| 15 #include <windows.h> | 16 |
| 16 #include <stdlib.h> | 17 void vp8_rtcd() |
| 17 static void once(void (*func)(void)) | |
| 18 { | 18 { |
| 19 static CRITICAL_SECTION *lock; | 19 vpx_scale_rtcd(); |
| 20 static LONG waiters; | |
| 21 static int done; | |
| 22 void *lock_ptr = &lock; | |
| 23 | |
| 24 /* If the initialization is complete, return early. This isn't just an | |
| 25 * optimization, it prevents races on the destruction of the global | |
| 26 * lock. | |
| 27 */ | |
| 28 if(done) | |
| 29 return; | |
| 30 | |
| 31 InterlockedIncrement(&waiters); | |
| 32 | |
| 33 /* Get a lock. We create one and try to make it the one-true-lock, | |
| 34 * throwing it away if we lost the race. | |
| 35 */ | |
| 36 | |
| 37 { | |
| 38 /* Scope to protect access to new_lock */ | |
| 39 CRITICAL_SECTION *new_lock = malloc(sizeof(CRITICAL_SECTION)); | |
| 40 InitializeCriticalSection(new_lock); | |
| 41 if (InterlockedCompareExchangePointer(lock_ptr, new_lock, NULL) != NULL) | |
| 42 { | |
| 43 DeleteCriticalSection(new_lock); | |
| 44 free(new_lock); | |
| 45 } | |
| 46 } | |
| 47 | |
| 48 /* At this point, we have a lock that can be synchronized on. We don't | |
| 49 * care which thread actually performed the allocation. | |
| 50 */ | |
| 51 | |
| 52 EnterCriticalSection(lock); | |
| 53 | |
| 54 if (!done) | |
| 55 { | |
| 56 func(); | |
| 57 done = 1; | |
| 58 } | |
| 59 | |
| 60 LeaveCriticalSection(lock); | |
| 61 | |
| 62 /* Last one out should free resources. The destructed objects are | |
| 63 * protected by checking if(done) above. | |
| 64 */ | |
| 65 if(!InterlockedDecrement(&waiters)) | |
| 66 { | |
| 67 DeleteCriticalSection(lock); | |
| 68 free(lock); | |
| 69 lock = NULL; | |
| 70 } | |
| 71 } | |
| 72 | |
| 73 | |
| 74 #elif CONFIG_MULTITHREAD && HAVE_PTHREAD_H | |
| 75 #include <pthread.h> | |
| 76 static void once(void (*func)(void)) | |
| 77 { | |
| 78 static pthread_once_t lock = PTHREAD_ONCE_INIT; | |
| 79 pthread_once(&lock, func); | |
| 80 } | |
| 81 | |
| 82 | |
| 83 #else | |
| 84 /* No-op version that performs no synchronization. vpx_rtcd() is idempotent, | |
| 85 * so as long as your platform provides atomic loads/stores of pointers | |
| 86 * no synchronization is strictly necessary. | |
| 87 */ | |
| 88 | |
| 89 static void once(void (*func)(void)) | |
| 90 { | |
| 91 static int done; | |
| 92 | |
| 93 if(!done) | |
| 94 { | |
| 95 func(); | |
| 96 done = 1; | |
| 97 } | |
| 98 } | |
| 99 #endif | |
| 100 | |
| 101 | |
| 102 void vpx_rtcd() | |
| 103 { | |
| 104 once(setup_rtcd_internal); | 20 once(setup_rtcd_internal); |
| 105 } | 21 } |
| OLD | NEW |