linux calibrate_delay

来源:互联网 发布:seo外包服务公司 编辑:程序博客网 时间:2024/05/17 03:52

1.内核启动信息

console [ttyS0] enabledCalibrating delay loop... 148.88 BogoMIPS (lpj=744448)pid_max: default: 32768 minimum: 301

2.BogoMIPS

BogoMIPS (Bogo--Bogus--伪的,MIPS--millions of instruction per second) 按照字面的解释是“不太真实的MIPS”。之所以不太真实,那是因为其计算方法并不十分精确。BogoMIPS的值在系统系统时,在一闪而过的启动信息里可以看到;也可以dmesg看到;还可以通过查看/proc/cpuifo看到。BogoMIPS 的值是 linux 内核通过在一个时钟节拍里不断的执行循环指令而估算出来,它实际上反应了 CPU 的速度。


3.calibrate_delay()

路径:linux-3.10.x\init\main.c-->start_kernel-->calibrate_delay

void __cpuinit calibrate_delay(void){unsigned long lpj;static bool printed;int this_cpu = smp_processor_id();if (per_cpu(cpu_loops_per_jiffy, this_cpu)) {lpj = per_cpu(cpu_loops_per_jiffy, this_cpu);if (!printed)pr_info("Calibrating delay loop (skipped) ""already calibrated this CPU");} else if (preset_lpj) {lpj = preset_lpj;if (!printed)pr_info("Calibrating delay loop (skipped) ""preset value.. ");} else if ((!printed) && lpj_fine) {lpj = lpj_fine;pr_info("Calibrating delay loop (skipped), ""value calculated using timer frequency.. ");} else if ((lpj = calibrate_delay_is_known())) {;} else if ((lpj = calibrate_delay_direct()) != 0) {if (!printed)pr_info("Calibrating delay using timer ""specific routine.. ");} else {if (!printed)pr_info("Calibrating delay loop... ");lpj = calibrate_delay_converge();}per_cpu(cpu_loops_per_jiffy, this_cpu) = lpj;if (!printed)pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",lpj/(500000/HZ),(lpj/(5000/HZ)) % 100, lpj);loops_per_jiffy = lpj;printed = true;}

BogoMIPS计算的核心函数:

static unsigned long __cpuinit calibrate_delay_converge(void){/* First stage - slowly accelerate to find initial bounds */unsigned long lpj, lpj_base, ticks, loopadd, loopadd_base, chop_limit;int trials = 0, band = 0, trial_in_band = 0;lpj = (1<<12);//1<<12=4096/* wait for "start of" clock tick */ticks = jiffies;while (ticks == jiffies)//等待下一个时钟节拍; /* nothing *//* Go .. */ticks = jiffies;do {if (++trial_in_band == (1<<band)) {//首次进入do{...}while(x)时if条件成立,初始化band=1和trial_in_band=0++band;trial_in_band = 0;}__delay(lpj * band);trials += band;} while (ticks == jiffies);//一个时钟节拍内的循环次数/* * We overshot, so retreat to a clear underestimate. Then estimate * the largest likely undershoot. This defines our chop bounds. */trials -= band;//去除上面do{...}while(x)里循环的最后一次,因为最后一次时钟节拍已经变更,所以不能统计到里面loopadd_base = lpj * band; //上面do{...}while(x)最后一次循环所需的时间,也是下一个时钟节拍的起始值lpj_base = lpj * trials; //一个时钟节拍需要的时间recalibrate:lpj = lpj_base; //一个时钟节拍需要的时间loopadd = loopadd_base; //上面do{...}while(x)最后一次循环所需的时间,也是下一个时钟节拍的起始值/* * Do a binary approximation to get lpj set to * equal one clock (up to LPS_PREC bits) */chop_limit = lpj >> LPS_PREC; //用于控制循环计算的次数,一个时钟节拍分频/2^8, 2^8=256while (loopadd > chop_limit) { //采用二分法的方式,无限靠近真值, 下一个时钟节拍的首次值 > 一个时钟节拍内256分频后的值,通过分析该while循环意思应该是要循环256次lpj += loopadd;ticks = jiffies;while (ticks == jiffies); /* nothing */ticks = jiffies;__delay(lpj);if (jiffies != ticks)/* longer than 1 tick */lpj -= loopadd; //时钟滴答切换,徐去除最后一次值,这里的loopadd由上面计算出,即是滴答更新时,上一次滴答的最后一次值loopadd >>= 1; //将时钟滴答切换时,上一次的时钟滴答最后一次的值进行“二分法”,已达到精确值}/* * If we incremented every single time possible, presume we've * massively underestimated initially, and retry with a higher * start, and larger range. (Only seen on x86_64, due to SMIs) */ //若每一次都是递增的(可能低估了lpj),则需要使用较大的初值和步幅if (lpj + loopadd * 2 == lpj_base + loopadd_base * 2) {lpj_base = lpj;loopadd_base <<= 2;goto recalibrate;}return lpj;}

根据报文中lpj=744448,Calibrating delay loop... 148.88 BogoMIPS (lpj=744448)