Home | History | Annotate | Download | only in common
      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 #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  // VP8_COMMON_THREADING_H_
    213