- 论坛徽章:
- 0
|
CPU频率的计算使用了两个函数init_cpu_khz()和calibrate_tsc()
----------------------------arch/i386/kernel/timers/Common.c--------------------
//tsc_quotient中保存通过calibrate_tsc()计算得出(CPU单个时钟周期的微秒数)*(2^32)的值,然后用1毫秒的微秒数即1000乘以2^32,再除以tsc_quotient,
//分子分母中的2^32抵消,最后的结果是1毫秒内的时钟周期数,即cpu频率的khz数- /* calculate cpu_khz */
- void __init init_cpu_khz(void)
- {
- if (cpu_has_tsc) {
- unsigned long tsc_quotient = calibrate_tsc();
- if (tsc_quotient) {
- /* report CPU clock rate in Hz.
- * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
- * clock/second. Our precision is about 100 ppm.
- */
- { unsigned long eax=0, edx=1000;
- __asm__("divl %2"
- :"=a" (cpu_khz), "=d" (edx)
- :"r" (tsc_quotient),
- "0" (eax), "1" (edx));
- printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
- }
- }
- }
- }
复制代码 ----------------------------arch/i386/kernel/timers/Common.c--------------------
//计算并返回(CPU单个时钟周期的微秒数)*(2^32)的值- unsigned long __init calibrate_tsc(void)
- {
- mach_prepare_counter();//设置5ms的计数器
- {
- unsigned long startlow, starthigh;
- unsigned long endlow, endhigh;
- unsigned long count;
- rdtsc(startlow,starthigh);//读取起始时间戳
- mach_countup(&count);//等待5ms
- rdtsc(endlow,endhigh);//读取结束时间戳
- /* Error: ECTCNEVERSET */
- if (count <= 1)
- goto bad_ctc;
- //计算时间戳的计数差值,即5ms中CPU收到的时钟脉冲数
- /* 64-bit subtract - gcc just messes up with long longs */
- __asm__("subl %2,%0\n\t"
- "sbbl %3,%1"
- :"=a" (endlow), "=d" (endhigh)
- :"g" (startlow), "g" (starthigh),
- "0" (endlow), "1" (endhigh));
- /* Error: ECPUTOOFAST */
- if (endhigh)
- goto bad_ctc;
- /* Error: ECPUTOOSLOW */
- if (endlow <= CALIBRATE_TIME)
- goto bad_ctc;
-
- //计算出(每个clock的微秒数)*(2^32)的值并返回
-
- __asm__("divl %2"
- :"=a" (endlow), "=d" (endhigh)
- :"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));
- return endlow;
- }
- /*
- * The CTC wasn't reliable: we got a hit on the very first read,
- * or the CPU was so fast/slow that the quotient wouldn't fit in
- * 32 bits..
- */
- bad_ctc:
- return 0;
- }
复制代码 |
|