公司使用的是mips处理器,每秒钟jiffs是250个,内核变量HZ值就是250,由此我引发一个疑问,一个jiffs时钟中断耗时4ms,没法做到毫秒微妙甚至纳秒的精度,那么内核延时函数mdelay udelay ndelya是如何实现的呢,于是研究了一下,就找到了linux内核中一个有趣的函数calibrate_delay()。
calibrate_delay()函数可以计算出cpu在一秒钟内执行了多少次一个极短的循环,最终计算出来的值赋给变量loop_per_jiffs,经过处理后得到BogoMIPS 值,Bogo是Bogus(伪)的意思,MIPS是millions of instructions per second(百万条指令每秒)的缩写。这样我们就知道了其实这个函数是linux内核中一个cpu性能测试函数。对于内核延时函数,关键点就是loop_per_jiffs,udelay函数就是利用这个变量计算出自己延时所需要的短循环。来实现微秒级延时。由于内核对这个数值的要求不高,所以内 核使用了一个十分简单而有效的算法用于得到这个值。如果你想了解自己机器的BogoMIPS,你可以察看 /proc/cpuinfo文件中的bogomips。让我们一起来看看 calibrate_delay函数是怎么完成工作的。
下面是2.6.21版本内核下calibrate_delay的源代码,这个函数是在内核启动函数start_kernel中调用。
108 /*
109 * This is the number of bits of precision for the loops_per_jiffy. Each
110 * bit takes on average 1.5/HZ seconds. This (like the original) is a little
111 * better than 1%
112 */
113 #define LPS_PREC 8
114
115 void __devinit calibrate_delay(void)
116 {
117 unsigned long ticks, loopbit;
118 int lps_precision = LPS_PREC;
119
120 if (preset_lpj) {
121 loops_per_jiffy = preset_lpj;
122 printk("Calibrating delay loop (skipped)... "
123 "%lu.%02lu BogoMIPS preset\n",
124 loops_per_jiffy/(500000/HZ),
125 (loops_per_jiffy/(5000/HZ)) % 100);
126 } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
calibrate_delay()函数可以计算出cpu在一秒钟内执行了多少次一个极短的循环,最终计算出来的值赋给变量loop_per_jiffs,经过处理后得到BogoMIPS 值,Bogo是Bogus(伪)的意思,MIPS是millions of instructions per second(百万条指令每秒)的缩写。这样我们就知道了其实这个函数是linux内核中一个cpu性能测试函数。对于内核延时函数,关键点就是loop_per_jiffs,udelay函数就是利用这个变量计算出自己延时所需要的短循环。来实现微秒级延时。由于内核对这个数值的要求不高,所以内 核使用了一个十分简单而有效的算法用于得到这个值。如果你想了解自己机器的BogoMIPS,你可以察看 /proc/cpuinfo文件中的bogomips。让我们一起来看看 calibrate_delay函数是怎么完成工作的。
下面是2.6.21版本内核下calibrate_delay的源代码,这个函数是在内核启动函数start_kernel中调用。
108 /*
109 * This is the number of bits of precision for the loops_per_jiffy. Each
110 * bit takes on average 1.5/HZ seconds. This (like the original) is a little
111 * better than 1%
112 */
113 #define LPS_PREC 8
114
115 void __devinit calibrate_delay(void)
116 {
117 unsigned long ticks, loopbit;
118 int lps_precision = LPS_PREC;
119
120 if (preset_lpj) {
121 loops_per_jiffy = preset_lpj;
122 printk("Calibrating delay loop (skipped)... "
123 "%lu.%02lu BogoMIPS preset\n",
124 loops_per_jiffy/(500000/HZ),
125 (loops_per_jiffy/(5000/HZ)) % 100);
126 } else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {