Index: source/libvpx/vp9/decoder/vp9_thread.h |
=================================================================== |
--- source/libvpx/vp9/decoder/vp9_thread.h (revision 251189) |
+++ source/libvpx/vp9/decoder/vp9_thread.h (working copy) |
@@ -26,7 +26,8 @@ |
#if CONFIG_MULTITHREAD |
#if defined(_WIN32) |
- |
+#include <errno.h> // NOLINT |
+#include <process.h> // NOLINT |
#include <windows.h> // NOLINT |
typedef HANDLE pthread_t; |
typedef CRITICAL_SECTION pthread_mutex_t; |
@@ -36,12 +37,120 @@ |
HANDLE signal_event_; |
} pthread_cond_t; |
-#else |
+//------------------------------------------------------------------------------ |
+// simplistic pthread emulation layer |
+// _beginthreadex requires __stdcall |
+#define THREADFN unsigned int __stdcall |
+#define THREAD_RETURN(val) (unsigned int)((DWORD_PTR)val) |
+ |
+static INLINE int pthread_create(pthread_t* const thread, const void* attr, |
+ unsigned int (__stdcall *start)(void*), |
+ void* arg) { |
+ (void)attr; |
+ *thread = (pthread_t)_beginthreadex(NULL, /* void *security */ |
+ 0, /* unsigned stack_size */ |
+ start, |
+ arg, |
+ 0, /* unsigned initflag */ |
+ NULL); /* unsigned *thrdaddr */ |
+ if (*thread == NULL) return 1; |
+ SetThreadPriority(*thread, THREAD_PRIORITY_ABOVE_NORMAL); |
+ return 0; |
+} |
+ |
+static INLINE int pthread_join(pthread_t thread, void** value_ptr) { |
+ (void)value_ptr; |
+ return (WaitForSingleObject(thread, INFINITE) != WAIT_OBJECT_0 || |
+ CloseHandle(thread) == 0); |
+} |
+ |
+// Mutex |
+static INLINE int pthread_mutex_init(pthread_mutex_t *const mutex, |
+ void* mutexattr) { |
+ (void)mutexattr; |
+ InitializeCriticalSection(mutex); |
+ return 0; |
+} |
+ |
+static INLINE int pthread_mutex_trylock(pthread_mutex_t *const mutex) { |
+ return TryEnterCriticalSection(mutex) ? 0 : EBUSY; |
+} |
+ |
+static INLINE int pthread_mutex_lock(pthread_mutex_t *const mutex) { |
+ EnterCriticalSection(mutex); |
+ return 0; |
+} |
+ |
+static INLINE int pthread_mutex_unlock(pthread_mutex_t *const mutex) { |
+ LeaveCriticalSection(mutex); |
+ return 0; |
+} |
+ |
+static INLINE int pthread_mutex_destroy(pthread_mutex_t *const mutex) { |
+ DeleteCriticalSection(mutex); |
+ return 0; |
+} |
+ |
+// Condition |
+static INLINE int pthread_cond_destroy(pthread_cond_t *const condition) { |
+ int ok = 1; |
+ ok &= (CloseHandle(condition->waiting_sem_) != 0); |
+ ok &= (CloseHandle(condition->received_sem_) != 0); |
+ ok &= (CloseHandle(condition->signal_event_) != 0); |
+ return !ok; |
+} |
+ |
+static INLINE int pthread_cond_init(pthread_cond_t *const condition, |
+ void* cond_attr) { |
+ (void)cond_attr; |
+ condition->waiting_sem_ = CreateSemaphore(NULL, 0, 1, NULL); |
+ condition->received_sem_ = CreateSemaphore(NULL, 0, 1, NULL); |
+ condition->signal_event_ = CreateEvent(NULL, FALSE, FALSE, NULL); |
+ if (condition->waiting_sem_ == NULL || |
+ condition->received_sem_ == NULL || |
+ condition->signal_event_ == NULL) { |
+ pthread_cond_destroy(condition); |
+ return 1; |
+ } |
+ return 0; |
+} |
+ |
+static INLINE int pthread_cond_signal(pthread_cond_t *const condition) { |
+ int ok = 1; |
+ if (WaitForSingleObject(condition->waiting_sem_, 0) == WAIT_OBJECT_0) { |
+ // a thread is waiting in pthread_cond_wait: allow it to be notified |
+ ok = SetEvent(condition->signal_event_); |
+ // wait until the event is consumed so the signaler cannot consume |
+ // the event via its own pthread_cond_wait. |
+ ok &= (WaitForSingleObject(condition->received_sem_, INFINITE) != |
+ WAIT_OBJECT_0); |
+ } |
+ return !ok; |
+} |
+ |
+static INLINE int pthread_cond_wait(pthread_cond_t *const condition, |
+ pthread_mutex_t *const mutex) { |
+ int ok; |
+ // note that there is a consumer available so the signal isn't dropped in |
+ // pthread_cond_signal |
+ if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL)) |
+ return 1; |
+ // now unlock the mutex so pthread_cond_signal may be issued |
+ pthread_mutex_unlock(mutex); |
+ ok = (WaitForSingleObject(condition->signal_event_, INFINITE) == |
+ WAIT_OBJECT_0); |
+ ok &= ReleaseSemaphore(condition->received_sem_, 1, NULL); |
+ pthread_mutex_lock(mutex); |
+ return !ok; |
+} |
+#else // _WIN32 |
#include <pthread.h> // NOLINT |
+# define THREADFN void* |
+# define THREAD_RETURN(val) val |
+#endif |
-#endif /* _WIN32 */ |
-#endif /* CONFIG_MULTITHREAD */ |
+#endif // CONFIG_MULTITHREAD |
// State of the worker thread object |
typedef enum { |