Linux内核(2.6.31) init/calibrate.c
void __cpuinit calibrate_delay(void)
unsigned long ticks, loopbit;
int lps_precision = LPS_PREC;
if (preset_lpj) {
loops_per_jiffy = preset_lpj;
printk(KERN_INFO
"Calibrating delay loop (skipped) preset value.. ");
} else if ((smp_processor_id() == 0) && lpj_fine) {
loops_per_jiffy = lpj_fine;
printk(KERN_INFO
"Calibrating delay loop (skipped), "
"value calculated using timer frequency.. ");
} else if ((loops_per_jiffy = calibrate_delay_direct()) != 0) {
printk(KERN_INFO
"Calibrating delay using timer specific routine.. ");
} else {
loops_per_jiffy = (1<<12);
printk(KERN_INFO "Calibrating delay loop... ");
while ((loops_per_jiffy <<= 1) != 0) {
/* wait for "start of" clock tick */
ticks = jiffies;
while (ticks == jiffies)
/* nothing */;
/* Go .. */
ticks = jiffies;
__delay(loops_per_jiffy); //__delay(T): do T tiny loops.
ticks = jiffies - ticks;
if (ticks) // when the first time the loops causing more then one jiffies,
//the corresponding loops_per_jiffy is a preliminary result, named 'A'.
break;
}
/*
* Do a binary approximation to get loops_per_jiffy set to
* equal one clock (up to lps_precision bits)
* start: A/2;
* first increment: A/4;
* next increment is half of the last one.("Binary Approximation");
* precision: lps_precision(the number of loop);
*/
loops_per_jiffy >>= 1;
loopbit = loops_per_jiffy;
while (lps_precision-- && (loopbit >>= 1)) {
loops_per_jiffy |= loopbit; // add the current increment to lpj.
ticks = jiffies;
while (ticks == jiffies)
/* nothing */;
ticks = jiffies;
__delay(loops_per_jiffy);
if (jiffies != ticks) /* longer than 1 tick */
loops_per_jiffy &= ~loopbit; // drop the current increment.
}
}
printk(KERN_CONT "%lu.%02lu BogoMIPS (lpj=%lu)\n",
loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ)) % 100, loops_per_jiffy);
}