[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