Re: [FFmpeg-devel] [PATCH 1/2] avutil/thread: Add pthread_cond_timedwait function.

2016-12-02 Thread James Almer
On 12/2/2016 5:21 AM, Matt Oliver wrote:
> Signed-off-by: Matt Oliver 
> ---
>  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 
> +#include 
>  
>  #include 
>  #include 
>  
>  #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(>wait_count);
> +
> +pthread_mutex_unlock(mutex);
> +
> +APIRET ret = DosWaitEventSem(cond->event_sem, t);
> +
> +__atomic_decrement(>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 
>  #include 
> +#include 
>  
>  #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(_cond->mtx_broadcast);
> +pthread_mutex_lock(_cond->mtx_waiter_count);
> +win32_cond->waiter_count++;
> +pthread_mutex_unlock(_cond->mtx_waiter_count);
> +pthread_mutex_unlock(_cond->mtx_broadcast);
> +
> +// unlock the external mutex
> +pthread_mutex_unlock(mutex);
> +DWORD ret = WaitForSingleObject(win32_cond->semaphore, t);
> +
> +pthread_mutex_lock(_cond->mtx_waiter_count);
> +win32_cond->waiter_count--;
> +last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast;
> +pthread_mutex_unlock(_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 

[FFmpeg-devel] [PATCH 1/2] avutil/thread: Add pthread_cond_timedwait function.

2016-12-02 Thread Matt Oliver
Signed-off-by: Matt Oliver 
---
 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 
+#include 

 #include 
 #include 

 #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(>wait_count);
+
+pthread_mutex_unlock(mutex);
+
+APIRET ret = DosWaitEventSem(cond->event_sem, t);
+
+__atomic_decrement(>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 
 #include 
+#include 

 #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;
+}
+
+/* non native condition variables */
+pthread_mutex_lock(_cond->mtx_broadcast);
+pthread_mutex_lock(_cond->mtx_waiter_count);
+win32_cond->waiter_count++;
+pthread_mutex_unlock(_cond->mtx_waiter_count);
+pthread_mutex_unlock(_cond->mtx_broadcast);
+
+// unlock the external mutex
+pthread_mutex_unlock(mutex);
+DWORD ret = WaitForSingleObject(win32_cond->semaphore, t);
+
+pthread_mutex_lock(_cond->mtx_waiter_count);
+win32_cond->waiter_count--;
+last_waiter = !win32_cond->waiter_count || !win32_cond->is_broadcast;
+pthread_mutex_unlock(_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


0001-avutil-thread-Add-pthread_cond_timedwait-function.patch
Description: Binary data