Messages in this thread Patch in this message | | | Date | Wed, 6 Mar 2013 11:31:14 +0800 | From | Feng Tang <> | Subject | Re: [RFC PATCH v2 0/4] Add support for S3 non-stop TSC support. |
| |
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
| |