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 #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 #include "vpx_util/vpx_thread.h" 195 #include "vpx_util/vpx_atomics.h" 196 197 static INLINE void vp8_atomic_spin_wait( 198 int mb_col, const vpx_atomic_int *last_row_current_mb_col, 199 const int nsync) { 200 while (mb_col > (vpx_atomic_load_acquire(last_row_current_mb_col) - nsync)) { 201 x86_pause_hint(); 202 thread_sleep(0); 203 } 204 } 205 206 #endif /* CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD */ 207 208 #ifdef __cplusplus 209 } // extern "C" 210 #endif 211 212 #endif // VPX_VP8_COMMON_THREADING_H_ 213