[vlc-devel] [PATCH] posix/thread: use the monotonic clock for CV
Thomas Guillem
thomas at gllm.fr
Mon Feb 24 09:57:30 CET 2020
On Sun, Feb 23, 2020, at 16:26, RĂ©mi Denis-Courmont wrote:
> This gets the earlier timed-wait behaviour back on NetBSD and other
> platforms without futex.
> ---
> src/posix/wait.c | 58 ++++++++++++++++++++++++++++++++++++++----------
> 1 file changed, 46 insertions(+), 12 deletions(-)
>
> diff --git a/src/posix/wait.c b/src/posix/wait.c
> index 5c146b61e2..26bce27448 100644
> --- a/src/posix/wait.c
> +++ b/src/posix/wait.c
> @@ -32,6 +32,8 @@
> #include <sys/types.h>
> #include <pthread.h>
>
> +static clockid_t vlc_clock_id = CLOCK_REALTIME;
> +
> #define WAIT_BUCKET_INIT \
> { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0 }
> #define WAIT_BUCKET_INIT_2 WAIT_BUCKET_INIT, WAIT_BUCKET_INIT
> @@ -101,22 +103,29 @@ static int vlc_atomic_timedwait_timespec(void
> *addr, unsigned value,
> return ret;
> }
>
> -int vlc_atomic_timedwait(void *addr, unsigned value, vlc_tick_t deadline)
> +static void vlc_timespec_adjust(clockid_t cid, struct timespec *restrict ts)
> {
> - struct timespec ts;
> - vlc_tick_t delay = deadline - vlc_tick_now();
> - lldiv_t d = lldiv((delay >= 0) ? delay : 0, CLOCK_FREQ);
> + struct timespec now_from, now_to;
> + lldiv_t d;
> +
> + if (vlc_clock_id == cid)
> + return;
>
> - /* TODO: use monotonic clock directly */
> - clock_gettime(CLOCK_REALTIME, &ts);
> - ts.tv_sec += d.quot;
> - ts.tv_nsec += NS_FROM_VLC_TICK(d.rem);
> + clock_gettime(cid, &now_from);
> + clock_gettime(vlc_clock_id, &now_to);
>
> - if (ts.tv_nsec >= 1000000000) {
> - ts.tv_sec++;
> - ts.tv_nsec -= 1000000000;
> - }
> + d = lldiv((ts->tv_sec - now_from.tv_sec + now_to.tv_sec) * 1000000000LL
> + + ts->tv_nsec - now_from.tv_nsec - now_to.tv_nsec, 1000000000LL);
> +
> + ts->tv_sec = d.quot;
> + ts->tv_nsec = d.rem;
> +}
>
> +int vlc_atomic_timedwait(void *addr, unsigned value, vlc_tick_t deadline)
> +{
> + struct timespec ts = timespec_from_vlc_tick(deadline);
> +
> + vlc_timespec_adjust(CLOCK_MONOTONIC, &ts);
> return vlc_atomic_timedwait_timespec(addr, value, &ts);
> }
>
> @@ -124,6 +133,7 @@ int vlc_atomic_timedwait_daytime(void *addr,
> unsigned value, time_t deadline)
> {
> struct timespec ts = { .tv_sec = deadline, .tv_nsec = 0 };
>
> + vlc_timespec_adjust(CLOCK_REALTIME, &ts);
> return vlc_atomic_timedwait_timespec(addr, value, &ts);
> }
>
> @@ -141,3 +151,27 @@ void vlc_atomic_notify_all(void *addr)
> pthread_cond_broadcast(&bucket->wait);
> pthread_mutex_unlock(&bucket->lock);
> }
> +
> +#ifdef __ELF__
> +__attribute__((constructor))
> +static void vlc_atomic_clock_select(void)
> +{
> + pthread_condattr_t attr;
> +
> + pthread_condattr_init(&attr);
> + pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);
> +
> + for (size_t i = 0; i < ARRAY_SIZE(wait_buckets); i++)
> + pthread_cond_init(&wait_buckets[i].wait, &attr);
So, the condition variables end up being initialized two times ?
Here and by PTHREAD_COND_INITIALIZER.
Are we sure it's safe ?
> +
> + pthread_condattr_destroy(&attr);
> + vlc_clock_id = CLOCK_MONOTONIC;
> +}
> +
> +__attribute__((destructor))
> +static void vlc_atomic_clock_deselect(void)
> +{
> + for (size_t i = 0; i < ARRAY_SIZE(wait_buckets); i++)
> + pthread_cond_destroy(&wait_buckets[i].wait);
> +}
> +#endif
> --
> 2.25.1
>
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
More information about the vlc-devel
mailing list