[vlc-devel] [PATCH 3/3] threads: add vlc_atomic_timedwait_daytime()

RĂ©mi Denis-Courmont remi at remlab.net
Mon Feb 17 21:54:09 CET 2020


...because VLM still wants to wait for day time.
---
 include/vlc_threads.h |  2 ++
 src/linux/thread.c    | 29 +++++++++++++++++++++++++----
 src/misc/threads.c    | 16 +++++++++-------
 src/posix/wait.c      | 31 ++++++++++++++++++++++---------
 src/win32/thread.c    | 25 +++++++++++++++++++++++++
 5 files changed, 83 insertions(+), 20 deletions(-)

diff --git a/include/vlc_threads.h b/include/vlc_threads.h
index a1db42df06..cc0ee01c86 100644
--- a/include/vlc_threads.h
+++ b/include/vlc_threads.h
@@ -724,6 +724,8 @@ void vlc_atomic_wait(void *addr, unsigned val);
  */
 int vlc_atomic_timedwait(void *addr, unsigned val, vlc_tick_t deadline);
 
+int vlc_atomic_timedwait_daytime(void *addr, unsigned val, time_t deadline);
+
 /**
  * Wakes up one thread on an address.
  *
diff --git a/src/linux/thread.c b/src/linux/thread.c
index bf5f665003..fa8d0e4c26 100644
--- a/src/linux/thread.c
+++ b/src/linux/thread.c
@@ -60,7 +60,8 @@ static int vlc_futex_wake(void *addr, int nr)
     return sys_futex(addr, FUTEX_WAKE_PRIVATE, nr, NULL, NULL, 0);
 }
 
-static int vlc_futex_wait(void *addr, unsigned val, const struct timespec *to)
+static int vlc_futex_wait(void *addr, unsigned flags,
+                          unsigned val, const struct timespec *to)
 {
     int ret;
 
@@ -68,7 +69,7 @@ static int vlc_futex_wait(void *addr, unsigned val, const struct timespec *to)
     int type;
     pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &type);
 #endif
-    ret = sys_futex(addr, FUTEX_WAIT_BITSET_PRIVATE, val, to, NULL,
+    ret = sys_futex(addr, FUTEX_WAIT_BITSET_PRIVATE | flags, val, to, NULL,
                     FUTEX_BITSET_MATCH_ANY);
 #ifndef __ANDROID__
     pthread_setcanceltype(type, NULL);
@@ -88,14 +89,34 @@ void vlc_atomic_notify_all(void *addr)
 
 void vlc_atomic_wait(void *addr, unsigned val)
 {
-    vlc_futex_wait(addr, val, NULL);
+    vlc_futex_wait(addr, 0, val, NULL);
 }
 
 int vlc_atomic_timedwait(void *addr, unsigned val, vlc_tick_t deadline)
 {
     struct timespec ts = timespec_from_vlc_tick(deadline);
 
-    if (vlc_futex_wait(addr, val, &ts) == 0)
+    if (vlc_futex_wait(addr, 0, val, &ts) == 0)
+        return 0;
+
+    switch (errno) {
+        case EINTR:
+        case EAGAIN:
+            return 0;
+        case EFAULT:
+        case EINVAL:
+            vlc_assert_unreachable(); /* BUG! */
+        default:
+            break;
+     }
+     return errno;
+}
+
+int vlc_atomic_timedwait_daytime(void *addr, unsigned val, time_t deadline)
+{
+    struct timespec ts = { .tv_sec = deadline, .tv_nsec = 0 };
+
+    if (vlc_futex_wait(addr, FUTEX_CLOCK_REALTIME, val, &ts) == 0)
         return 0;
 
     switch (errno) {
diff --git a/src/misc/threads.c b/src/misc/threads.c
index debb66bdc8..a75ca50652 100644
--- a/src/misc/threads.c
+++ b/src/misc/threads.c
@@ -358,16 +358,18 @@ int vlc_cond_timedwait(vlc_cond_t *cond, vlc_mutex_t *mutex,
 }
 
 int vlc_cond_timedwait_daytime(vlc_cond_t *cond, vlc_mutex_t *mutex,
-                               time_t deadline_daytime)
+                               time_t deadline)
 {
-    struct timespec ts;
-    vlc_tick_t deadline = vlc_tick_from_sec(deadline_daytime);
+    struct vlc_cond_waiter waiter;
+    int ret;
 
-    timespec_get(&ts, TIME_UTC);
-    /* real-time to monotonic timestamp conversion */
-    deadline += vlc_tick_from_timespec(&ts) - vlc_tick_now();
+    vlc_cond_wait_prepare(&waiter, cond, mutex);
+    vlc_cleanup_push(vlc_cond_wait_cleanup, &waiter);
+    ret = vlc_atomic_timedwait_daytime(&waiter.value, 0, deadline);
+    vlc_cleanup_pop();
+    vlc_cond_wait_cleanup(&waiter);
 
-    return vlc_cond_timedwait(cond, mutex, deadline);
+    return ret;
 }
 #endif
 
diff --git a/src/posix/wait.c b/src/posix/wait.c
index 8e3156f514..5c146b61e2 100644
--- a/src/posix/wait.c
+++ b/src/posix/wait.c
@@ -85,14 +85,27 @@ void vlc_atomic_wait(void *addr, unsigned value)
     pthread_cleanup_pop(1);
 }
 
-int vlc_atomic_timedwait(void *addr, unsigned value, vlc_tick_t deadline)
+static int vlc_atomic_timedwait_timespec(void *addr, unsigned value,
+                                         const struct timespec *restrict ts)
 {
     atomic_uint *futex = addr;
-    struct wait_bucket *bucket;
+    struct wait_bucket *bucket = wait_bucket_enter(futex);
+    int ret = 0;
+
+    pthread_cleanup_push(wait_bucket_leave, bucket);
+
+    if (value == atomic_load_explicit(futex, memory_order_relaxed))
+        ret = pthread_cond_timedwait(&bucket->wait, &bucket->lock, ts);
+
+    pthread_cleanup_pop(1);
+    return ret;
+}
+
+int vlc_atomic_timedwait(void *addr, unsigned value, vlc_tick_t deadline)
+{
     struct timespec ts;
     vlc_tick_t delay = deadline - vlc_tick_now();
     lldiv_t d = lldiv((delay >= 0) ? delay : 0, CLOCK_FREQ);
-    int ret = 0;
 
     /* TODO: use monotonic clock directly */
     clock_gettime(CLOCK_REALTIME, &ts);
@@ -104,14 +117,14 @@ int vlc_atomic_timedwait(void *addr, unsigned value, vlc_tick_t deadline)
         ts.tv_nsec -= 1000000000;
     }
 
-    bucket = wait_bucket_enter(futex);
-    pthread_cleanup_push(wait_bucket_leave, bucket);
+    return vlc_atomic_timedwait_timespec(addr, value, &ts);
+}
 
-    if (value == atomic_load_explicit(futex, memory_order_relaxed))
-        ret = pthread_cond_timedwait(&bucket->wait, &bucket->lock, &ts);
+int vlc_atomic_timedwait_daytime(void *addr, unsigned value, time_t deadline)
+{
+    struct timespec ts = { .tv_sec = deadline, .tv_nsec = 0 };
 
-    pthread_cleanup_pop(1);
-    return ret;
+    return vlc_atomic_timedwait_timespec(addr, value, &ts);
 }
 
 void vlc_atomic_notify_one(void *addr)
diff --git a/src/win32/thread.c b/src/win32/thread.c
index 9f2c5e3f50..31c3324f76 100644
--- a/src/win32/thread.c
+++ b/src/win32/thread.c
@@ -403,6 +403,31 @@ int vlc_atomic_timedwait(void *addr, unsigned val, vlc_tick_t deadline)
     return ETIMEDOUT;
 }
 
+int vlc_atomic_timedwait_daytime(void *addr, unsigned val, time_t deadline)
+{
+    long delay;
+
+    do
+    {
+        long ms;
+
+        delay = deadline - time(NULL);
+
+        if (delay < 0)
+            ms = 0;
+        else if (delay >= (LONG_MAX / 1000))
+            ms = LONG_MAX;
+        else
+            ms = delay * 1000;
+
+        if (WaitOnAddress(addr, &val, sizeof (val), ms))
+            return 0;
+    }
+    while (delay > 0);
+
+    return ETIMEDOUT;
+}
+
 void vlc_atomic_notify_one(void *addr)
 {
     WakeByAddressSingle(addr);
-- 
2.25.0



More information about the vlc-devel mailing list