From f47a4fc3d900e14653bc059717e2805ad4964a67 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 18 May 2014 16:36:08 +0200 Subject: threads: use mpv time for mpthread_cond_timedwait wrapper Use the time as returned by mp_time_us() for mpthread_cond_timedwait(), instead of calculating the struct timespec value based on a timeout. This (probably) makes it easier to wait for a specific deadline. --- osdep/timer.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) (limited to 'osdep/timer.c') diff --git a/osdep/timer.c b/osdep/timer.c index 4f506b3d46..de37653a67 100644 --- a/osdep/timer.c +++ b/osdep/timer.c @@ -17,9 +17,15 @@ #include #include +#include +#include +#include +#include +#include -#include "timer.h" +#include "common/common.h" #include "common/msg.h" +#include "timer.h" static uint64_t raw_time_offset; pthread_once_t timer_init_once = PTHREAD_ONCE_INIT; @@ -60,21 +66,75 @@ int64_t mp_time_relative_us(int64_t *t) return r; } +int64_t mp_add_timeout(int64_t time_us, double timeout_sec) +{ + assert(time_us > 0); // mp_time_us() returns strictly positive values + double t = timeout_sec * 1000 * 1000; + if (t >= (double)(INT64_MAX - time_us)) + return INT64_MAX; + if (t <= (double)time_us) + return 1; + return time_us + (int64_t)t; +} + +static void get_realtime(struct timespec *out_ts) +{ +#if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0 + clock_gettime(CLOCK_REALTIME, out_ts); +#else + // OSX + struct timeval tv; + gettimeofday(&tv, NULL); + out_ts->tv_sec = tv.tv_sec; + out_ts->tv_nsec = tv.tv_usec * 1000UL; +#endif +} + +struct timespec mp_time_us_to_timespec(int64_t time_us) +{ + struct timespec ts; + get_realtime(&ts); + // We don't know what time source mp_time_us() uses, but usually it's not + // CLOCK_REALTIME - so we have to remap the times. + int64_t unow = mp_time_us(); + int64_t diff_us = time_us - unow; + long diff_secs = diff_us / (1000L * 1000L); + unsigned long diff_nsecs = (diff_us - diff_secs * (1000L * 1000L)) * 1000UL; + if (diff_nsecs + ts.tv_nsec >= 1000000000UL) { + diff_secs += 1; + diff_nsecs -= 1000000000UL; + } + ts.tv_sec += diff_secs; + ts.tv_nsec += diff_nsecs; + return ts; +} + #if 0 #include +#include "threads.h" + +#define TEST_SLEEP 1 int main(void) { - int c = 200; + int c = 2000000; int64_t j, r, t = 0; + pthread_mutex_t mtx; + pthread_mutex_init(&mtx, NULL); + pthread_cond_t cnd; + pthread_cond_init(&cnd, NULL); mp_time_init(); for (int i = 0; i < c; i++) { const int delay = rand() / (RAND_MAX / 1e5); r = mp_time_us(); +#if TEST_SLEEP mp_sleep_us(delay); +#else + mpthread_cond_timedwait(&cnd, &mtx, r + delay); +#endif j = (mp_time_us() - r) - delay; - printf("sleep time: sleep=%8i err=%5i\n", delay, (int)j); + printf("sleep time: t=%"PRId64" sleep=%8i err=%5i\n", r, delay, (int)j); t += j; } fprintf(stderr, "average error:\t%i\n", (int)(t / c)); -- cgit v1.2.3