/src/libvpx/vp8/common/threading.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2010 The WebM project authors. All Rights Reserved. |
3 | | * |
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 |
6 | | * tree. An additional intellectual property rights grant can be found |
7 | | * in the file PATENTS. All contributing project authors may |
8 | | * be found in the AUTHORS file in the root of the source tree. |
9 | | */ |
10 | | |
11 | | #ifndef VPX_VP8_COMMON_THREADING_H_ |
12 | | #define VPX_VP8_COMMON_THREADING_H_ |
13 | | |
14 | | #include "./vpx_config.h" |
15 | | |
16 | | #ifdef __cplusplus |
17 | | extern "C" { |
18 | | #endif |
19 | | |
20 | | #if CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD |
21 | | |
22 | | /* Thread management macros */ |
23 | | #if defined(_WIN32) && !HAVE_PTHREAD_H |
24 | | /* Win32 */ |
25 | | #include <process.h> |
26 | | #include <windows.h> |
27 | | #if defined(__GNUC__) && \ |
28 | | (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) |
29 | | #define THREAD_FUNCTION \ |
30 | | __attribute__((force_align_arg_pointer)) unsigned int __stdcall |
31 | | #else |
32 | | #define THREAD_FUNCTION unsigned int __stdcall |
33 | | #endif |
34 | | #define THREAD_FUNCTION_RETURN DWORD |
35 | | #define THREAD_SPECIFIC_INDEX DWORD |
36 | | #define pthread_t HANDLE |
37 | | #define pthread_attr_t DWORD |
38 | | #define pthread_detach(thread) \ |
39 | | if (thread != NULL) CloseHandle(thread) |
40 | | #define thread_sleep(nms) Sleep(nms) |
41 | | #define pthread_cancel(thread) terminate_thread(thread, 0) |
42 | | #define ts_key_create(ts_key, destructor) \ |
43 | | { ts_key = TlsAlloc(); }; |
44 | | #define pthread_getspecific(ts_key) TlsGetValue(ts_key) |
45 | | #define pthread_setspecific(ts_key, value) TlsSetValue(ts_key, (void *)value) |
46 | | #define pthread_self() GetCurrentThreadId() |
47 | | |
48 | | #elif defined(__OS2__) |
49 | | /* OS/2 */ |
50 | | #define INCL_DOS |
51 | | #include <os2.h> |
52 | | |
53 | | #include <stdlib.h> |
54 | | #define THREAD_FUNCTION void * |
55 | | #define THREAD_FUNCTION_RETURN void * |
56 | | #define THREAD_SPECIFIC_INDEX PULONG |
57 | | #define pthread_t TID |
58 | | #define pthread_attr_t ULONG |
59 | | #define pthread_detach(thread) 0 |
60 | | #define thread_sleep(nms) DosSleep(nms) |
61 | | #define pthread_cancel(thread) DosKillThread(thread) |
62 | | #define ts_key_create(ts_key, destructor) \ |
63 | | DosAllocThreadLocalMemory(1, &(ts_key)); |
64 | | #define pthread_getspecific(ts_key) ((void *)(*(ts_key))) |
65 | | #define pthread_setspecific(ts_key, value) (*(ts_key) = (ULONG)(value)) |
66 | | #define pthread_self() _gettid() |
67 | | #else |
68 | | #ifdef __APPLE__ |
69 | | #include <mach/mach_init.h> |
70 | | #include <mach/semaphore.h> |
71 | | #include <mach/task.h> |
72 | | #include <time.h> |
73 | | #include <unistd.h> |
74 | | |
75 | | #else |
76 | | #include <semaphore.h> |
77 | | #endif |
78 | | |
79 | | #include <pthread.h> |
80 | | /* pthreads */ |
81 | | /* Nearly everything is already defined */ |
82 | | #define THREAD_FUNCTION void * |
83 | | #define THREAD_FUNCTION_RETURN void * |
84 | | #define THREAD_SPECIFIC_INDEX pthread_key_t |
85 | | #define ts_key_create(ts_key, destructor) \ |
86 | | pthread_key_create(&(ts_key), destructor); |
87 | | #endif |
88 | | |
89 | | /* Synchronization macros: Win32 and Pthreads */ |
90 | | #if defined(_WIN32) && !HAVE_PTHREAD_H |
91 | | #define sem_t HANDLE |
92 | | #define pause(voidpara) __asm PAUSE |
93 | | #define sem_init(sem, sem_attr1, sem_init_value) \ |
94 | | (int)((*sem = CreateSemaphore(NULL, 0, 32768, NULL)) == NULL) |
95 | | #define sem_wait(sem) \ |
96 | | (int)(WAIT_OBJECT_0 != WaitForSingleObject(*sem, INFINITE)) |
97 | | #define sem_post(sem) ReleaseSemaphore(*sem, 1, NULL) |
98 | | #define sem_destroy(sem) \ |
99 | | if (*sem) ((int)(CloseHandle(*sem)) == TRUE) |
100 | | #define thread_sleep(nms) Sleep(nms) |
101 | | |
102 | | #elif defined(__OS2__) |
103 | | typedef struct { |
104 | | HEV event; |
105 | | HMTX wait_mutex; |
106 | | HMTX count_mutex; |
107 | | int count; |
108 | | } sem_t; |
109 | | |
110 | | static inline int sem_init(sem_t *sem, int pshared, unsigned int value) { |
111 | | DosCreateEventSem(NULL, &sem->event, pshared ? DC_SEM_SHARED : 0, |
112 | | value > 0 ? TRUE : FALSE); |
113 | | DosCreateMutexSem(NULL, &sem->wait_mutex, 0, FALSE); |
114 | | DosCreateMutexSem(NULL, &sem->count_mutex, 0, FALSE); |
115 | | |
116 | | sem->count = value; |
117 | | |
118 | | return 0; |
119 | | } |
120 | | |
121 | | static inline int sem_wait(sem_t *sem) { |
122 | | DosRequestMutexSem(sem->wait_mutex, -1); |
123 | | |
124 | | DosWaitEventSem(sem->event, -1); |
125 | | |
126 | | DosRequestMutexSem(sem->count_mutex, -1); |
127 | | |
128 | | sem->count--; |
129 | | if (sem->count == 0) { |
130 | | ULONG post_count; |
131 | | |
132 | | DosResetEventSem(sem->event, &post_count); |
133 | | } |
134 | | |
135 | | DosReleaseMutexSem(sem->count_mutex); |
136 | | |
137 | | DosReleaseMutexSem(sem->wait_mutex); |
138 | | |
139 | | return 0; |
140 | | } |
141 | | |
142 | | static inline int sem_post(sem_t *sem) { |
143 | | DosRequestMutexSem(sem->count_mutex, -1); |
144 | | |
145 | | if (sem->count < 32768) { |
146 | | sem->count++; |
147 | | DosPostEventSem(sem->event); |
148 | | } |
149 | | |
150 | | DosReleaseMutexSem(sem->count_mutex); |
151 | | |
152 | | return 0; |
153 | | } |
154 | | |
155 | | static inline int sem_destroy(sem_t *sem) { |
156 | | DosCloseEventSem(sem->event); |
157 | | DosCloseMutexSem(sem->wait_mutex); |
158 | | DosCloseMutexSem(sem->count_mutex); |
159 | | |
160 | | return 0; |
161 | | } |
162 | | |
163 | | #define thread_sleep(nms) DosSleep(nms) |
164 | | |
165 | | #else |
166 | | |
167 | | #ifdef __APPLE__ |
168 | | #define sem_t semaphore_t |
169 | | #define sem_init(X, Y, Z) \ |
170 | | semaphore_create(mach_task_self(), X, SYNC_POLICY_FIFO, Z) |
171 | | #define sem_wait(sem) (semaphore_wait(*sem)) |
172 | | #define sem_post(sem) semaphore_signal(*sem) |
173 | | #define sem_destroy(sem) semaphore_destroy(mach_task_self(), *sem) |
174 | | #else |
175 | | #include <unistd.h> |
176 | | #include <sched.h> |
177 | | #endif /* __APPLE__ */ |
178 | | /* Not Windows. Assume pthreads */ |
179 | | |
180 | | /* thread_sleep implementation: yield unless Linux/Unix. */ |
181 | | #if defined(__unix__) || defined(__APPLE__) |
182 | | #define thread_sleep(nms) |
183 | | /* {struct timespec ts;ts.tv_sec=0; |
184 | | ts.tv_nsec = 1000*nms;nanosleep(&ts, NULL);} */ |
185 | | #else |
186 | | #define thread_sleep(nms) sched_yield(); |
187 | | #endif /* __unix__ || __APPLE__ */ |
188 | | |
189 | | #endif |
190 | | |
191 | | #if VPX_ARCH_X86 || VPX_ARCH_X86_64 |
192 | | #include "vpx_ports/x86.h" |
193 | | #else |
194 | | #define x86_pause_hint() |
195 | | #endif |
196 | | |
197 | | #include "vpx_util/vpx_thread.h" |
198 | | #include "vpx_util/vpx_atomics.h" |
199 | | |
200 | | static INLINE void vp8_atomic_spin_wait( |
201 | | int mb_col, const vpx_atomic_int *last_row_current_mb_col, |
202 | 276k | const int nsync) { |
203 | 21.9M | while (mb_col > (vpx_atomic_load_acquire(last_row_current_mb_col) - nsync)) { |
204 | 21.7M | x86_pause_hint(); |
205 | 21.7M | thread_sleep(0); |
206 | 21.7M | } |
207 | 276k | } Unexecuted instantiation: vp8_dx_iface.c:vp8_atomic_spin_wait Unexecuted instantiation: onyxd_if.c:vp8_atomic_spin_wait threading.c:vp8_atomic_spin_wait Line | Count | Source | 202 | 276k | const int nsync) { | 203 | 21.9M | while (mb_col > (vpx_atomic_load_acquire(last_row_current_mb_col) - nsync)) { | 204 | 21.7M | x86_pause_hint(); | 205 | 21.7M | thread_sleep(0); | 206 | 21.7M | } | 207 | 276k | } |
Unexecuted instantiation: decodeframe.c:vp8_atomic_spin_wait Unexecuted instantiation: detokenize.c:vp8_atomic_spin_wait Unexecuted instantiation: decodemv.c:vp8_atomic_spin_wait |
208 | | |
209 | | #endif /* CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD */ |
210 | | |
211 | | #ifdef __cplusplus |
212 | | } // extern "C" |
213 | | #endif |
214 | | |
215 | | #endif // VPX_VP8_COMMON_THREADING_H_ |