From fc6fde22c34ac9ae39f16494238140ba40456efd Mon Sep 17 00:00:00 2001 From: Matt Oliver Date: Wed, 7 Dec 2016 16:55:35 +1100 Subject: [PATCH] avutil/thread: Add pthread_cond_timedwait function v2: fix calculating milisecond times and use SleepConditionVariableSRW. Signed-off-by: Matt Oliver --- compat/os2threads.h | 25 +++++++++++++++++++++++++ compat/w32pthreads.h | 18 ++++++++++++++++++ libavutil/thread.h | 7 +++++++ 3 files changed, 50 insertions(+) diff --git a/compat/os2threads.h b/compat/os2threads.h index 2177a033ec..eec6f40ae7 100644 --- a/compat/os2threads.h +++ b/compat/os2threads.h @@ -31,11 +31,14 @@ #undef __STRICT_ANSI__ /* for _beginthread() */ #include +#include #include #include #include "libavutil/attributes.h" +#include "libavutil/common.h" +#include "libavutil/time.h" typedef struct { TID tid; @@ -163,6 +166,28 @@ static av_always_inline int pthread_cond_broadcast(pthread_cond_t *cond) return 0; } +static av_always_inline int pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + int64_t abs_milli = abstime->tv_sec * 1000LL + abstime->tv_nsec / 1000000; + ULONG t = av_clip64(abs_milli - av_gettime() / 1000, 0, ULONG_MAX); + + __atomic_increment(&cond->wait_count); + + pthread_mutex_unlock(mutex); + + APIRET ret = DosWaitEventSem(cond->event_sem, t); + + __atomic_decrement(&cond->wait_count); + + DosPostEventSem(cond->ack_sem); + + pthread_mutex_lock(mutex); + + return (ret == ERROR_TIMEOUT) ? ETIMEDOUT : 0; +} + static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { diff --git a/compat/w32pthreads.h b/compat/w32pthreads.h index 21acfd2ba1..7df33b7da4 100644 --- a/compat/w32pthreads.h +++ b/compat/w32pthreads.h @@ -38,11 +38,13 @@ #define WIN32_LEAN_AND_MEAN #include #include +#include #include "libavutil/attributes.h" #include "libavutil/common.h" #include "libavutil/internal.h" #include "libavutil/mem.h" +#include "libavutil/time.h" typedef struct pthread_t { void *handle; @@ -156,6 +158,22 @@ static inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex return 0; } +static inline int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + int64_t abs_milli = abstime->tv_sec * 1000LL + abstime->tv_nsec / 1000000; + DWORD t = av_clip64(abs_milli - av_gettime() / 1000, 0, UINT32_MAX); + + if (!SleepConditionVariableSRW(cond, mutex, t, 0)) { + DWORD err = GetLastError(); + if (err == ERROR_TIMEOUT) + return ETIMEDOUT; + else + return EINVAL; + } + return 0; +} + static inline int pthread_cond_signal(pthread_cond_t *cond) { WakeConditionVariable(cond); diff --git a/libavutil/thread.h b/libavutil/thread.h index cc5272d379..65b97ef303 100644 --- a/libavutil/thread.h +++ b/libavutil/thread.h @@ -109,6 +109,12 @@ static inline int strict_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t ASSERT_PTHREAD(pthread_cond_wait, cond, mutex); } +static inline int strict_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, + const struct timespec *abstime) +{ + ASSERT_PTHREAD(pthread_cond_timedwait, cond, mutex, abstime); +} + static inline int strict_pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { ASSERT_PTHREAD(pthread_once, once_control, init_routine); @@ -124,6 +130,7 @@ static inline int strict_pthread_once(pthread_once_t *once_control, void (*init_ #define pthread_cond_signal strict_pthread_cond_signal #define pthread_cond_broadcast strict_pthread_cond_broadcast #define pthread_cond_wait strict_pthread_cond_wait +#define pthread_cond_timedwait strict_pthread_cond_timedwait #define pthread_once strict_pthread_once #endif