From 4441427943db72f03a660e2ceb6b8e781c43739f Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Fri, 22 May 2020 20:45:59 +1000 Subject: [PATCH] [client] implemented better clock drift correction --- VERSION | 2 +- client/src/main.c | 42 +++++++++++------------------------- common/include/common/time.h | 36 +++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/VERSION b/VERSION index 3ef28929..f0c899ed 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -B2-rc1-6-g60f665a65c+1 \ No newline at end of file +B2-rc1-7-gf5da432d38+1 \ No newline at end of file diff --git a/client/src/main.c b/client/src/main.c index 9512c325..c73d271a 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -154,28 +154,23 @@ static int renderThread(void * unused) while(state.running) { - // if our clock is too far out of sync, resync it - // this can happen when switching to/from a TTY, or due to clock drift - // we only check this once every 100 frames - if (state.frameTime > 0 && ++resyncCheck == 100) + if (state.frameTime > 0) { - resyncCheck = 0; + tsAdd(&time, state.frameTime); - struct timespec tmp; - clock_gettime(CLOCK_REALTIME, &tmp); - if (tmp.tv_nsec - time.tv_nsec < 0) + // if our clock is too far out of sync, resync it + // this can happen when switching to/from a TTY, or due to clock drift + // we only check this once every 100 frames + if (++resyncCheck == 100) { - tmp.tv_sec -= time.tv_sec - 1; - tmp.tv_nsec = 1000000000 + tmp.tv_nsec - time.tv_nsec; - } - else - { - tmp.tv_sec -= time.tv_sec; - tmp.tv_nsec -= time.tv_nsec; - } + resyncCheck = 0; - if (tmp.tv_sec > 1) - clock_gettime(CLOCK_REALTIME, &time); + struct timespec end, diff; + clock_gettime(CLOCK_REALTIME, &end); + tsDiff(&diff, &time, &end); + if (diff.tv_sec > 0 || diff.tv_nsec > 1000000000) // 100ms + clock_gettime(CLOCK_REALTIME, &time); + } } if (state.lgrResize) @@ -218,18 +213,7 @@ static int renderThread(void * unused) } if (state.frameTime > 0) - { - uint64_t nsec = time.tv_nsec + state.frameTime; - if(nsec > 1e9) - { - time.tv_nsec = nsec - 1e9; - ++time.tv_sec; - } - else - time.tv_nsec = nsec; - lgWaitEventAbs(e_frame, &time); - } } state.running = false; diff --git a/common/include/common/time.h b/common/include/common/time.h index b1b0d9d0..7abada18 100644 --- a/common/include/common/time.h +++ b/common/include/common/time.h @@ -66,6 +66,42 @@ static inline void nsleep(uint64_t ns) }; nanosleep(&ts, NULL); } + +static inline void tsDiff(struct timespec *diff, const struct timespec *left, + const struct timespec *right) +{ + diff->tv_sec = left->tv_sec - right->tv_sec; + diff->tv_nsec = left->tv_nsec - right->tv_nsec; + if (diff->tv_nsec < 0) + { + --diff->tv_sec; + diff->tv_nsec += 1000000000; + } +} + +static inline uint32_t __iter_div_u64_rem(uint64_t dividend, uint32_t divisor, uint64_t *remainder) +{ + uint32_t ret = 0; + + while (dividend >= divisor) { + /* The following asm() prevents the compiler from + optimising this loop into a modulo operation. */ + asm("" : "+rm"(dividend)); + + dividend -= divisor; + ret++; + } + + *remainder = dividend; + + return ret; +} + +static inline void tsAdd(struct timespec *a, uint64_t ns) +{ + a->tv_sec += __iter_div_u64_rem(a->tv_nsec + ns, 1000000000L, &ns); + a->tv_nsec = ns; +} #endif typedef bool (*LGTimerFn)(void * udata);