ref: 7949de70e00a1cac0229f2cfcc7413cb29f43e4e
parent: 3e643b1faa2854a7b685ae28b3f58166e872a3a4
author: Martin Storsjö <[email protected]>
date: Thu Jun 18 09:00:20 EDT 2020
cli: Avoid large intermediates in the windows get_time_nanos By multiplicating the performance counter value (within its own time base) by the intended target time base, and only then dividing, we reduce the available numeric range by the factor of the original time base times the new time base. On Windows 10 on ARM64, the performance counter frequency is 19200000 (on x86_64 in a virtual machine, it's 10000000), making the calculation overflow every (1 << 64) / (19200000 * 1000000000) = 960 seconds, i.e. 16 minutes - long before the actual uint64_t nanosecond return value wraps around.
--- a/tools/dav1d.c
+++ b/tools/dav1d.c
@@ -63,7 +63,9 @@
QueryPerformanceFrequency(&frequency);
LARGE_INTEGER t;
QueryPerformanceCounter(&t);
- return 1000000000 * t.QuadPart / frequency.QuadPart;
+ uint64_t seconds = t.QuadPart / frequency.QuadPart;
+ uint64_t fractions = t.QuadPart % frequency.QuadPart;
+ return 1000000000 * seconds + 1000000000 * fractions / frequency.QuadPart;
#elif defined(HAVE_CLOCK_GETTIME)
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);