[FFmpeg-devel] [PATCH 1/2] avutil/thread: Add pthread_cond_timedwait function.
James Almer
jamrial at gmail.com
Fri Dec 2 15:59:12 EET 2016
On 12/2/2016 5:21 AM, Matt Oliver wrote:
> Signed-off-by: Matt Oliver <protogonoi at gmail.com>
> ---
> compat/os2threads.h | 24 ++++++++++++++++++++++++
> compat/w32pthreads.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
> libavutil/thread.h | 6 ++++++
> 3 files changed, 80 insertions(+)
>
> diff --git a/compat/os2threads.h b/compat/os2threads.h
> index 40a119f..a8b7824 100644
> --- a/compat/os2threads.h
> +++ b/compat/os2threads.h
> @@ -31,11 +31,13 @@
>
> #undef __STRICT_ANSI__ /* for _beginthread() */
> #include <stdlib.h>
> +#include <time.h>
>
> #include <sys/builtin.h>
> #include <sys/fmutex.h>
>
> #include "libavutil/attributes.h"
> +#include "libavutil/time.h"
>
> typedef struct {
> TID tid;
> @@ -161,6 +163,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_nsec * 1000LL + abstime->tv_nsec / 1.0e6;
> + ULONG t = FFMAX(abs_milli - av_gettime(), 0LL);
> +
> + __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 4ac2a99..abd54b2 100644
> --- a/compat/w32pthreads.h
> +++ b/compat/w32pthreads.h
> @@ -38,6 +38,7 @@
> #define WIN32_LEAN_AND_MEAN
> #include <windows.h>
> #include <process.h>
> +#include <time.h>
>
> #if _WIN32_WINNT < 0x0600 && defined(__MINGW32__)
> #undef MemoryBarrier
> @@ -48,6 +49,7 @@
> #include "libavutil/common.h"
> #include "libavutil/internal.h"
> #include "libavutil/mem.h"
> +#include "libavutil/time.h"
>
> typedef struct pthread_t {
> void *handle;
> @@ -171,6 +173,17 @@ 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_nsec * 1000LL + abstime->tv_nsec / 1.0e6;
> + DWORD t = FFMAX(abs_milli - av_gettime(), 0LL);
> +
> + if (SleepConditionVariableCS(cond, mutex, t) == WAIT_TIMEOUT)
> + return ETIMEDOUT;
> + return 0;
> +}
> +
> static inline int pthread_cond_signal(pthread_cond_t *cond)
> {
> WakeConditionVariable(cond);
> @@ -367,6 +380,43 @@ static av_unused int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mu
> return pthread_mutex_lock(mutex);
> }
>
> +static inline int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
> + const struct timespec *abstime)
> +{
> + win32_cond_t *win32_cond = cond->Ptr;
> + int last_waiter;
> + int64_t abs_milli = abstime->tv_nsec * 1000LL + abstime->tv_nsec / 1.0e6;
> + DWORD t = FFMAX(abs_milli - av_gettime(), 0LL);
> + if (cond_wait) {
> + cond_wait(cond, mutex, t);
> + return 0;
This is not doing the same as the native version above. Is that intended?
> + }
> +
> + /* non native condition variables */
> + pthread_mutex_lock(&win32_cond->mtx_broadcast);
> + pthread_mutex_lock(&win32_cond->mtx_waiter_count);
> + win32_cond->waiter_count++;
> + pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
> + pthread_mutex_unlock(&win32_cond->mtx_broadcast);
> +
> + // unlock the external mutex
> + pthread_mutex_unlock(mutex);
> + DWORD ret = WaitForSingleObject(win32_cond->semaphore, t);
> +
> + pthread_mutex_lock(&win32_cond->mtx_waiter_count);
> + win32_cond->waiter_count--;
> + last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast;
> + pthread_mutex_unlock(&win32_cond->mtx_waiter_count);
> +
> + if (last_waiter)
> + SetEvent(win32_cond->waiters_done);
> +
> + // lock the external mutex
> + pthread_mutex_lock(mutex);
> +
> + return (ret == WAIT_TIMEOUT) ? ETIMEDOUT : 0;
> +}
> +
> static av_unused int pthread_cond_signal(pthread_cond_t *cond)
> {
> win32_cond_t *win32_cond = cond->Ptr;
> diff --git a/libavutil/thread.h b/libavutil/thread.h
> index 32ddf40..9d611f2 100644
> --- a/libavutil/thread.h
> +++ b/libavutil/thread.h
> @@ -108,6 +108,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);
> +}
> +
This also needs the line
#define pthread_cond_timedwait strict_pthread_cond_timedwait
At the end of the ASSERT_LEVEL section.
> static inline int strict_pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
> {
> ASSERT_PTHREAD(pthread_once, once_control, init_routine);
> -- 2.10.2.windows.1
More information about the ffmpeg-devel
mailing list