On Tue, Mar 05, 2013 at 02:17:59PM +0800, John Stultz wrote: > On 03/05/2013 12:32 PM, Jason Gunthorpe wrote: > >On Tue, Mar 05, 2013 at 11:53:02AM +0800, Feng Tang wrote: > > > >>>// Drops some small precision along the way but is simple.. > >>>static inline u64 cyclecounter_cyc2ns_128(const struct cyclecounter *cc, > >>> cycle_t cycles) > >>>{ > >>> u64 max = U64_MAX/cc->mult; > >>> u64 num = cycles/max; > >>> u64 result = num * ((max * cc->mult) >> cc->shift); > >>> return result + cyclecounter_cyc2ns(cc, cycles - num*cc->mult); > >>>} > > > Probably want to use clocksource instead of cyclecounter, but I > think Jason's approach sounds ok. I might suggest that you initially > make the function static to the timekeeping code, just so we don't > get unexpected users.
Thought more about it, can we directly make clocksource_cyc2ns() cover the overflow case? Something like: diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index aa7032c..1ecc872 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -274,7 +274,16 @@ static inline u32 clocksource_hz2mult(u32 hz, u32 shift_constant) */ static inline s64 clocksource_cyc2ns(cycle_t cycles, u32 mult, u32 shift) { - return ((u64) cycles * mult) >> shift; + u64 max = ULLONG_MAX / mult; + s64 nsec = 0; + + /* The (mult * cycles) may overflow 64 bits, so add a max check */ + if (cycles > max) { + nsec = ((max * mult) >> shift) * (cycles / max); + cycles %= max; + } + nsec += ((u64) cycles * mult) >> shift; + return nsec; } Thanks, Feng -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/