Chinaunix首页 | 论坛 | 博客
  • 博客访问: 610274
  • 博文数量: 197
  • 博客积分: 7001
  • 博客等级: 大校
  • 技术积分: 2155
  • 用 户 组: 普通用户
  • 注册时间: 2005-02-24 00:29
文章分类

全部博文(197)

文章存档

2022年(1)

2019年(2)

2015年(1)

2012年(100)

2011年(69)

2010年(14)

2007年(3)

2005年(7)

分类: LINUX

2010-05-10 23:42:13

              math is hard, lets go shopping!

1 用法

/**
 * cyc2ns - converts clocksource cycles to nanoseconds
 * @cs:        Pointer to clocksource
 * @cycles:    Cycles
 *
 * Uses the clocksource and ntp ajdustment to convert cycle_ts to nanoseconds.
 *
 * XXX - This could use some mult_lxl_ll() asm optimization
 */
static inline s64 cyc2ns(struct clocksource *cs, cycle_t cycles)
{
    u64 ret = (u64)cycles;
    ret = (ret * cs->mult) >> cs->shift;
    return ret;
}

2 动机

为什么不 cycles *NSEC_PER_SEC / freq?



1. convert the clock cycles to ns

ns = cyc * NSEC_PER_SEC / freq (freq is clock freq of the counter)
= use the scaling math. (please refer to arch/x86/kernel/tsc.c)
= (cyc * mult) >> shift (refer to clocksource_calc_mult_shift() )


另2.6.34
arch/x86/kernel/tsc.c
/* Accelerators for sched_clock()
 * convert from cycles(64bits) => nanoseconds (64bits)
 *  basic equation:
 *              ns = cycles / (freq / ns_per_sec)
 *              ns = cycles * (ns_per_sec / freq)
 *              ns = cycles * (10^9 / (cpu_khz * 10^3))
 *              ns = cycles * (10^6 / cpu_khz)
 *
 *      Then we use scaling math (suggested by george@mvista.com) to get:
 *              ns = cycles * (10^6 * SC / cpu_khz) / SC
 *              ns = cycles * cyc2ns_scale / SC
 *
 *      And since SC is a constant power of two, we can convert the div
 *  into a shift.
 *
 *  We can use khz divisor instead of mhz to keep a better precision, since
 *  cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
 *  (mathieu.desnoyers@polymtl.ca)
 *
 *                      -johnstul@us.ibm.com "math is hard, lets go shopping!"
 */


3 shift value和mult的选取



/**
+ * clocksource_hz2shift - calculates shift from hz and # of bits
+ * @bits: Number of bits this clocksource uses
+ * @hz: Clocksource frequency in Hz
+ *
+ * Helper functions that calculates the best shift value
+ * based on the hz and # of bits of any given clock.
+ */
+static inline u32 clocksource_hz2shift(u32 bits, u32 hz)
+{
+ u64 temp;
+
+ for (; bits > 0; bits--) {
+ temp = (u64) NSEC_PER_SEC << bits;
+ do_div(temp, hz);
+ if ((temp >> 32) == 0)
+ break;
+ }
+ return bits;
+}
结 合下面的解释,可以看到要保证shift足够大, 同时又要保证temp(即以后的mult) 必须 2^32-1 范围内



[patch 0/3] Provide generic function to calc mult/shift factors for clocks

The mult and shift factors of clock events differ in their data type
from those of clock sources for no reason. u32 is sufficient for
both. shift is always <= 32 and mult is limited to 2^32-1 to avoid
64bit multiplication overflows in the conversion.


2.6.34 有clocksource_calc_mult_shift函数
阅读(1323) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~