threading.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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. #ifndef VPX_VP8_COMMON_THREADING_H_
  11. #define VPX_VP8_COMMON_THREADING_H_
  12. #include "./vpx_config.h"
  13. #ifdef __cplusplus
  14. extern "C" {
  15. #endif
  16. #if CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD
  17. /* Thread management macros */
  18. #if defined(_WIN32) && !HAVE_PTHREAD_H
  19. /* Win32 */
  20. #include <process.h>
  21. #include <windows.h>
  22. #if defined(__GNUC__) && \
  23. (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
  24. #define THREAD_FUNCTION \
  25. __attribute__((force_align_arg_pointer)) unsigned int __stdcall
  26. #else
  27. #define THREAD_FUNCTION unsigned int __stdcall
  28. #endif
  29. #define THREAD_FUNCTION_RETURN DWORD
  30. #define THREAD_SPECIFIC_INDEX DWORD
  31. #define pthread_t HANDLE
  32. #define pthread_attr_t DWORD
  33. #define pthread_detach(thread) \
  34. if (thread != NULL) CloseHandle(thread)
  35. #define thread_sleep(nms) Sleep(nms)
  36. #define pthread_cancel(thread) terminate_thread(thread, 0)
  37. #define ts_key_create(ts_key, destructor) \
  38. { ts_key = TlsAlloc(); };
  39. #define pthread_getspecific(ts_key) TlsGetValue(ts_key)
  40. #define pthread_setspecific(ts_key, value) TlsSetValue(ts_key, (void *)value)
  41. #define pthread_self() GetCurrentThreadId()
  42. #elif defined(__OS2__)
  43. /* OS/2 */
  44. #define INCL_DOS
  45. #include <os2.h>
  46. #include <stdlib.h>
  47. #define THREAD_FUNCTION void *
  48. #define THREAD_FUNCTION_RETURN void *
  49. #define THREAD_SPECIFIC_INDEX PULONG
  50. #define pthread_t TID
  51. #define pthread_attr_t ULONG
  52. #define pthread_detach(thread) 0
  53. #define thread_sleep(nms) DosSleep(nms)
  54. #define pthread_cancel(thread) DosKillThread(thread)
  55. #define ts_key_create(ts_key, destructor) \
  56. DosAllocThreadLocalMemory(1, &(ts_key));
  57. #define pthread_getspecific(ts_key) ((void *)(*(ts_key)))
  58. #define pthread_setspecific(ts_key, value) (*(ts_key) = (ULONG)(value))
  59. #define pthread_self() _gettid()
  60. #else
  61. #ifdef __APPLE__
  62. #include <mach/mach_init.h>
  63. #include <mach/semaphore.h>
  64. #include <mach/task.h>
  65. #include <time.h>
  66. #include <unistd.h>
  67. #else
  68. #include <semaphore.h>
  69. #endif
  70. #include <pthread.h>
  71. /* pthreads */
  72. /* Nearly everything is already defined */
  73. #define THREAD_FUNCTION void *
  74. #define THREAD_FUNCTION_RETURN void *
  75. #define THREAD_SPECIFIC_INDEX pthread_key_t
  76. #define ts_key_create(ts_key, destructor) \
  77. pthread_key_create(&(ts_key), destructor);
  78. #endif
  79. /* Synchronization macros: Win32 and Pthreads */
  80. #if defined(_WIN32) && !HAVE_PTHREAD_H
  81. #define sem_t HANDLE
  82. #define pause(voidpara) __asm PAUSE
  83. #define sem_init(sem, sem_attr1, sem_init_value) \
  84. (int)((*sem = CreateSemaphore(NULL, 0, 32768, NULL)) == NULL)
  85. #define sem_wait(sem) \
  86. (int)(WAIT_OBJECT_0 != WaitForSingleObject(*sem, INFINITE))
  87. #define sem_post(sem) ReleaseSemaphore(*sem, 1, NULL)
  88. #define sem_destroy(sem) \
  89. if (*sem) ((int)(CloseHandle(*sem)) == TRUE)
  90. #define thread_sleep(nms) Sleep(nms)
  91. #elif defined(__OS2__)
  92. typedef struct {
  93. HEV event;
  94. HMTX wait_mutex;
  95. HMTX count_mutex;
  96. int count;
  97. } sem_t;
  98. static inline int sem_init(sem_t *sem, int pshared, unsigned int value) {
  99. DosCreateEventSem(NULL, &sem->event, pshared ? DC_SEM_SHARED : 0,
  100. value > 0 ? TRUE : FALSE);
  101. DosCreateMutexSem(NULL, &sem->wait_mutex, 0, FALSE);
  102. DosCreateMutexSem(NULL, &sem->count_mutex, 0, FALSE);
  103. sem->count = value;
  104. return 0;
  105. }
  106. static inline int sem_wait(sem_t *sem) {
  107. DosRequestMutexSem(sem->wait_mutex, -1);
  108. DosWaitEventSem(sem->event, -1);
  109. DosRequestMutexSem(sem->count_mutex, -1);
  110. sem->count--;
  111. if (sem->count == 0) {
  112. ULONG post_count;
  113. DosResetEventSem(sem->event, &post_count);
  114. }
  115. DosReleaseMutexSem(sem->count_mutex);
  116. DosReleaseMutexSem(sem->wait_mutex);
  117. return 0;
  118. }
  119. static inline int sem_post(sem_t *sem) {
  120. DosRequestMutexSem(sem->count_mutex, -1);
  121. if (sem->count < 32768) {
  122. sem->count++;
  123. DosPostEventSem(sem->event);
  124. }
  125. DosReleaseMutexSem(sem->count_mutex);
  126. return 0;
  127. }
  128. static inline int sem_destroy(sem_t *sem) {
  129. DosCloseEventSem(sem->event);
  130. DosCloseMutexSem(sem->wait_mutex);
  131. DosCloseMutexSem(sem->count_mutex);
  132. return 0;
  133. }
  134. #define thread_sleep(nms) DosSleep(nms)
  135. #else
  136. #ifdef __APPLE__
  137. #define sem_t semaphore_t
  138. #define sem_init(X, Y, Z) \
  139. semaphore_create(mach_task_self(), X, SYNC_POLICY_FIFO, Z)
  140. #define sem_wait(sem) (semaphore_wait(*sem))
  141. #define sem_post(sem) semaphore_signal(*sem)
  142. #define sem_destroy(sem) semaphore_destroy(mach_task_self(), *sem)
  143. #define thread_sleep(nms) { struct timespec ts;ts.tv_sec=0; ts.tv_nsec = 1000*nms;sched_yield();nanosleep(&ts, NULL);}
  144. #else
  145. #include <unistd.h>
  146. #include <sched.h>
  147. #define thread_sleep(nms) {struct timespec ts;ts.tv_sec=0; ts.tv_nsec = 1000*nms;sched_yield();clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);}
  148. #endif
  149. /* Not Windows. Assume pthreads */
  150. #endif
  151. #if ARCH_X86 || ARCH_X86_64
  152. #include "vpx_ports/x86.h"
  153. #else
  154. #define x86_pause_hint()
  155. #endif
  156. #include "vpx_util/vpx_thread.h"
  157. #include "vpx_util/vpx_atomics.h"
  158. static INLINE void vp8_atomic_spin_wait(
  159. int mb_col, const vpx_atomic_int *last_row_current_mb_col,
  160. const int nsync) {
  161. while (mb_col > (vpx_atomic_load_acquire(last_row_current_mb_col) - nsync)) {
  162. x86_pause_hint();
  163. thread_sleep(1);
  164. }
  165. }
  166. #endif /* CONFIG_OS_SUPPORT && CONFIG_MULTITHREAD */
  167. #ifdef __cplusplus
  168. } // extern "C"
  169. #endif
  170. #endif // VPX_VP8_COMMON_THREADING_H_