tile: avoid overflow in ns2cycles
authorHenrik Austad <henrik@austad.us>
Tue, 4 Mar 2014 08:20:53 +0000 (09:20 +0100)
committerChris Metcalf <cmetcalf@tilera.com>
Thu, 6 Mar 2014 16:53:12 +0000 (11:53 -0500)
In commit 4cecf6d401a ("sched, x86: Avoid unnecessary overflow in
sched_clock") and in recent patch "clocksource: avoid unnecessary
overflow in cyclecounter_cyc2ns()" https://lkml.org/lkml/2014/3/4/17,
the mult-shift approach is replaced by 2 steps to avoid storing a large,
intermediate value that could overflow.

arch/tile/kernel/time.c has a similar pattern in cycles2ns, and this
copies the same pattern in this function

CC: John Stultz <johnstul@us.ibm.com>
CC: Mike Galbraith <bitbucket@online.de>
CC: Salman Qazi <sqazi@google.com>
Signed-off-by: Henrik Austad <henrik@austad.us>
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
arch/tile/kernel/time.c

index 5d10642db63e8e9f98934e36200128a9dfd26073..462dcd0c1700221adda93563b5f7904511a9c656 100644 (file)
@@ -236,7 +236,15 @@ cycles_t ns2cycles(unsigned long nsecs)
         * clock frequency.
         */
        struct clock_event_device *dev = &__raw_get_cpu_var(tile_timer);
-       return ((u64)nsecs * dev->mult) >> dev->shift;
+
+       /*
+        * as in clocksource.h and x86's timer.h, we split the calculation
+        * into 2 parts to avoid unecessary overflow of the intermediate
+        * value. This will not lead to any loss of precision.
+        */
+       u64 quot = (u64)nsecs >> dev->shift;
+       u64 rem  = (u64)nsecs & ((1ULL << dev->shift) - 1);
+       return quot * dev->mult + ((rem * dev->mult) >> dev->shift);
 }
 
 void update_vsyscall_tz(void)