免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1972 | 回复: 0
打印 上一主题 下一主题

[内核入门] 2.6.11内核CPU频率(khz)的计算 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2013-03-17 11:19 |只看该作者 |倒序浏览
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数
  1. /* calculate cpu_khz */
  2. void __init init_cpu_khz(void)
  3. {
  4. if (cpu_has_tsc) {
  5.   unsigned long tsc_quotient = calibrate_tsc();
  6.   if (tsc_quotient) {
  7.    /* report CPU clock rate in Hz.
  8.     * The formula is (10^6 * 2^32) / (2^32 * 1 / (clocks/us)) =
  9.     * clock/second. Our precision is about 100 ppm.
  10.     */
  11.    { unsigned long eax=0, edx=1000;
  12.     __asm__("divl %2"
  13.            :"=a" (cpu_khz), "=d" (edx)
  14.                   :"r" (tsc_quotient),
  15.                   "0" (eax), "1" (edx));
  16.     printk("Detected %lu.%03lu MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000);
  17.    }
  18.   }
  19. }
  20. }
复制代码
----------------------------arch/i386/kernel/timers/Common.c--------------------

//计算并返回(CPU单个时钟周期的微秒数)*(2^32)的值
  1. unsigned long __init calibrate_tsc(void)
  2. {
  3. mach_prepare_counter();//设置5ms的计数器

  4. {
  5.   unsigned long startlow, starthigh;
  6.   unsigned long endlow, endhigh;
  7.   unsigned long count;

  8.   rdtsc(startlow,starthigh);//读取起始时间戳
  9.   mach_countup(&count);//等待5ms
  10.   rdtsc(endlow,endhigh);//读取结束时间戳


  11.   /* Error: ECTCNEVERSET */
  12.   if (count <= 1)
  13.    goto bad_ctc;

  14. //计算时间戳的计数差值,即5ms中CPU收到的时钟脉冲数

  15.   /* 64-bit subtract - gcc just messes up with long longs */
  16.   __asm__("subl %2,%0\n\t"
  17.    "sbbl %3,%1"
  18.    :"=a" (endlow), "=d" (endhigh)
  19.    :"g" (startlow), "g" (starthigh),
  20.     "0" (endlow), "1" (endhigh));

  21.   /* Error: ECPUTOOFAST */
  22.   if (endhigh)
  23.    goto bad_ctc;

  24.   /* Error: ECPUTOOSLOW */
  25.   if (endlow <= CALIBRATE_TIME)
  26.    goto bad_ctc;



  27. //计算出(每个clock的微秒数)*(2^32)的值并返回



  28.   __asm__("divl %2"
  29.    :"=a" (endlow), "=d" (endhigh)
  30.    :"r" (endlow), "0" (0), "1" (CALIBRATE_TIME));

  31.   return endlow;
  32. }

  33. /*
  34.   * The CTC wasn't reliable: we got a hit on the very first read,
  35.   * or the CPU was so fast/slow that the quotient wouldn't fit in
  36.   * 32 bits..
  37.   */
  38. bad_ctc:
  39. return 0;
  40. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP