Skip to content

Instantly share code, notes, and snippets.

@Sibras
Created December 14, 2016 04:53
Show Gist options
  • Save Sibras/6792316413f3a595d8a941d924cbe653 to your computer and use it in GitHub Desktop.
Save Sibras/6792316413f3a595d8a941d924cbe653 to your computer and use it in GitHub Desktop.
[PATCH 1/3] avutil/thread: Add pthread_cond_timedwait function.
From f4a48300bf545227b5fb9121bf46a95f40e8923a Mon Sep 17 00:00:00 2001
From: Matt Oliver <protogonoi@gmail.com>
Date: Wed, 7 Dec 2016 16:55:35 +1100
Subject: [PATCH 1/3] avutil/thread: Add pthread_cond_timedwait function.
Signed-off-by: Matt Oliver <protogonoi@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,45 @@ 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) {
+ if (cond_wait(cond, mutex, t) == WAIT_TIMEOUT)
+ return ETIMEDOUT;
+ return 0;
+ }
+
+ /* 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);
+}
+
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment