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 |