From: Jens Axboe Date: Wed, 17 Dec 2014 05:40:37 +0000 (-0700) Subject: gettime: fix overflow in cycle to usec conversion X-Git-Tag: fio-2.2.0~5 X-Git-Url: https://git.kernel.dk/?p=fio.git;a=commitdiff_plain;h=b3fa625b38a638cd1783e9fdcac1b958e37e48fa gettime: fix overflow in cycle to usec conversion If this multiplication overflows: usecs = (t * inv_cycles_per_usec) / 16777216UL; then usecs is 2^64/2^24, which is 1099511627776. Divide that by 10^6 to get seconds, and that is 1099511. Since we cached the old value previously, we'd get stuck with this amount of seconds. To avoid turning this into an expensive division, have a check and only divide if we have to. This avoids the overflow. Signed-off-by: Jens Axboe --- diff --git a/gettime.c b/gettime.c index e2746711..30513e03 100644 --- a/gettime.c +++ b/gettime.c @@ -16,6 +16,7 @@ #if defined(ARCH_HAVE_CPU_CLOCK) && !defined(ARCH_CPU_CLOCK_CYCLES_PER_USEC) static unsigned long cycles_per_usec; static unsigned long inv_cycles_per_usec; +static uint64_t max_cycles_for_mult; #endif int tsc_reliable = 0; @@ -182,7 +183,10 @@ static void __fio_gettime(struct timeval *tp) #ifdef ARCH_CPU_CLOCK_CYCLES_PER_USEC usecs = t / ARCH_CPU_CLOCK_CYCLES_PER_USEC; #else - usecs = (t * inv_cycles_per_usec) / 16777216UL; + if (t < max_cycles_for_mult) + usecs = (t * inv_cycles_per_usec) / 16777216UL; + else + usecs = t / cycles_per_usec; #endif tp->tv_sec = usecs / 1000000; tp->tv_usec = usecs % 1000000; @@ -296,6 +300,7 @@ static int calibrate_cpu_clock(void) cycles_per_usec = avg; inv_cycles_per_usec = 16777216UL / cycles_per_usec; + max_cycles_for_mult = ~0ULL / inv_cycles_per_usec; dprint(FD_TIME, "inv_cycles_per_usec=%lu\n", inv_cycles_per_usec); return 0; }