diff mbox

[FFmpeg-devel,1/3] avutil/thread: Add pthread_cond_timedwait function.

Message ID CAHVN4mhVtUcDKquiJnooBkav5QMLtsZCFmHmvsPpKNPwce2fmw@mail.gmail.com
State Accepted
Headers show

Commit Message

Matt Oliver Dec. 7, 2016, 6:04 a.m. UTC
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(+)

 static inline int strict_pthread_once(pthread_once_t *once_control, void
(*init_routine)(void))
 {
     ASSERT_PTHREAD(pthread_once, once_control, init_routine);

Comments

Hendrik Leppkes Dec. 7, 2016, 10:32 a.m. UTC | #1
On Wed, Dec 7, 2016 at 7:04 AM, Matt Oliver <protogonoi@gmail.com> wrote:
> 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,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 does not return any error codes like the other implementations.

> +    }
> +
> +    /* 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
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
Matt Oliver Dec. 7, 2016, 10:56 a.m. UTC | #2
On 7 December 2016 at 21:32, Hendrik Leppkes <h.leppkes@gmail.com> wrote:

> On Wed, Dec 7, 2016 at 7:04 AM, Matt Oliver <protogonoi@gmail.com> wrote:
> > 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,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 does not return any error codes like the other implementations.
>

fixed locally be changing to:
+    if (cond_wait) {
+        if (cond_wait(cond, mutex, t) == WAIT_TIMEOUT)
+            return ETIMEDOUT;
+        return 0;
diff mbox

Patch

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;
+    }
+
+    /* 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);
+}
+