diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/x86/include/asm/timer.h | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/arch/x86/include/asm/timer.h b/arch/x86/include/asm/timer.h index fa7b9176b76..431793e5d48 100644 --- a/arch/x86/include/asm/timer.h +++ b/arch/x86/include/asm/timer.h | |||
| @@ -32,6 +32,22 @@ extern int no_timer_check; | |||
| 32 | * (mathieu.desnoyers@polymtl.ca) | 32 | * (mathieu.desnoyers@polymtl.ca) |
| 33 | * | 33 | * |
| 34 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" | 34 | * -johnstul@us.ibm.com "math is hard, lets go shopping!" |
| 35 | * | ||
| 36 | * In: | ||
| 37 | * | ||
| 38 | * ns = cycles * cyc2ns_scale / SC | ||
| 39 | * | ||
| 40 | * Although we may still have enough bits to store the value of ns, | ||
| 41 | * in some cases, we may not have enough bits to store cycles * cyc2ns_scale, | ||
| 42 | * leading to an incorrect result. | ||
| 43 | * | ||
| 44 | * To avoid this, we can decompose 'cycles' into quotient and remainder | ||
| 45 | * of division by SC. Then, | ||
| 46 | * | ||
| 47 | * ns = (quot * SC + rem) * cyc2ns_scale / SC | ||
| 48 | * = quot * cyc2ns_scale + (rem * cyc2ns_scale) / SC | ||
| 49 | * | ||
| 50 | * - sqazi@google.com | ||
| 35 | */ | 51 | */ |
| 36 | 52 | ||
| 37 | DECLARE_PER_CPU(unsigned long, cyc2ns); | 53 | DECLARE_PER_CPU(unsigned long, cyc2ns); |
| @@ -41,9 +57,14 @@ DECLARE_PER_CPU(unsigned long long, cyc2ns_offset); | |||
| 41 | 57 | ||
| 42 | static inline unsigned long long __cycles_2_ns(unsigned long long cyc) | 58 | static inline unsigned long long __cycles_2_ns(unsigned long long cyc) |
| 43 | { | 59 | { |
| 60 | unsigned long long quot; | ||
| 61 | unsigned long long rem; | ||
| 44 | int cpu = smp_processor_id(); | 62 | int cpu = smp_processor_id(); |
| 45 | unsigned long long ns = per_cpu(cyc2ns_offset, cpu); | 63 | unsigned long long ns = per_cpu(cyc2ns_offset, cpu); |
| 46 | ns += cyc * per_cpu(cyc2ns, cpu) >> CYC2NS_SCALE_FACTOR; | 64 | quot = (cyc >> CYC2NS_SCALE_FACTOR); |
| 65 | rem = cyc & ((1ULL << CYC2NS_SCALE_FACTOR) - 1); | ||
| 66 | ns += quot * per_cpu(cyc2ns, cpu) + | ||
| 67 | ((rem * per_cpu(cyc2ns, cpu)) >> CYC2NS_SCALE_FACTOR); | ||
| 47 | return ns; | 68 | return ns; |
| 48 | } | 69 | } |
| 49 | 70 | ||
