Line data Source code
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 VP8_COMMON_THREADING_H_
12 : #define 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 : #define thread_sleep(nms)
175 : /* { struct timespec ts;ts.tv_sec=0; ts.tv_nsec =
176 : 1000*nms;nanosleep(&ts, NULL);} */
177 : #else
178 : #include <unistd.h>
179 : #include <sched.h>
180 : #define thread_sleep(nms) sched_yield();
181 : /* {struct timespec ts;ts.tv_sec=0;
182 : ts.tv_nsec = 1000*nms;nanosleep(&ts, NULL);} */
183 : #endif
184 : /* Not Windows. Assume pthreads */
185 :
186 : #endif
187 :
188 : #if ARCH_X86 || ARCH_X86_64
189 : #include "vpx_ports/x86.h"
190 : #else
191 : #define x86_pause_hint()
192 : #endif
193 :
194 : #if defined(__has_feature)
195 : #if __has_feature(thread_sanitizer)
196 : #define USE_MUTEX_LOCK 1
197 : #endif
198 : #endif
199 :
200 : #include "vpx_util/vpx_thread.h"
201 :
202 0 : static INLINE int protected_read(pthread_mutex_t *const mutex, const int *p) {
203 : (void)mutex;
204 : #if defined(USE_MUTEX_LOCK)
205 : int ret;
206 : pthread_mutex_lock(mutex);
207 : ret = *p;
208 : pthread_mutex_unlock(mutex);
209 : return ret;
210 : #endif
211 0 : return *p;
212 : }
213 :
214 0 : static INLINE void sync_read(pthread_mutex_t *const mutex, int mb_col,
215 : const int *last_row_current_mb_col,
216 : const int nsync) {
217 0 : while (mb_col > (protected_read(mutex, last_row_current_mb_col) - nsync)) {
218 0 : x86_pause_hint();
219 0 : thread_sleep(0);
220 : }
221 0 : }
222 :
223 0 : static INLINE void protected_write(pthread_mutex_t *mutex, int *p, int v) {
224 : (void)mutex;
225 : #if defined(USE_MUTEX_LOCK)
226 : pthread_mutex_lock(mutex);
227 : *p = v;
228 : pthread_mutex_unlock(mutex);
229 : return;
230 : #endif
231 0 : *p = v;
232 0 : }
233 :
234 : #undef USE_MUTEX_LOCK
235 : #endif /* CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD */
236 :
237 : #ifdef __cplusplus
238 : } // extern "C"
239 : #endif
240 :
241 : #endif // VP8_COMMON_THREADING_H_
|