Linux时间管理之hardware(1)(3)
ACPI_PM
这个是传说中的ACPI Power Management Time,这个其实我也知之不详,对这个感兴趣的可以去找下CU的彭东,这小子写OS,应该会经常和这种硬件纠缠不清。到了硬件驱动层,我水平基本温饱线以下。
- #define PMTMR_TICKS_PER_SEC 3579545
- 66 static struct clocksource clocksource_acpi_pm = {
- .name = "acpi_pm",
- .rating = 200,
- .read = acpi_pm_read,
- .mask = (cycle_t)ACPI_PM_MASK,
- .mult = 0, /*to be calculated*/
- .shift = 22,
- .flags = CLOCK_SOURCE_IS_CONTINUOUS,
- };
- fs_initcall(init_acpi_pm_clocksource)
我们看到了频率在3Mhz这个级别,rating是200,低于HPET。至于初始化在fs_initcall这一步做。
TSC
TSC是Time Stamp Counter。CPU 执行指令需要一个外部振荡器产生时钟信号,从 CLK 管脚输入。x86 提供了一个 TSC 寄存器,该寄存器的值在每次收到一个时钟信号时加一。比如 CPU 的主频为 1GHZ,则每一秒时间内,TSC 寄存器的值将增加 1G 次,或者说每一个纳秒加一次。x86 还提供了 rtdsc 指令来读取该值,因此 TSC 也可以作为时钟设备。TSC 提供了比 RTC 更高精度的时间,即纳秒级的时间精度。这个很牛X,看时钟频率是和CPU的频率一个水平线的。远远超过HPET,PIT这些小鱼小虾米。看下我的笔记本的TSC 频率:
- manu@manu:~/code/c/classical/linux-3.4.61$ dmesg |grep Detected
- [ 0.004000] Detected 2127.727 MHz processor.
- manu@manu:~$ cat /proc/cpuinfo
- processor : 0
- vendor_id : GenuineIntel
- cpu family : 6
- model : 37
- model name : Intel(R) Core(TM) i3 CPU M 330 @ 2.13GHz
- 。。。。。
看这时钟频率,相当的吓人,看下clocksource的rating:
- static struct clocksource clocksource_tsc = {
- .name = "tsc",
- .rating = 300,
- .read = read_tsc,
- .resume = resume_tsc,
- .mask = CLOCKSOURCE_MASK(64),
- .flags = CLOCK_SOURCE_IS_CONTINUOUS |
- CLOCK_SOURCE_MUST_VERIFY,
- #ifdef CONFIG_X86_64
- .archdata = { .vclock_mode = VCLOCK_TSC },
- #endif
- };
TSC的init和register分别在tsc_init和init_tsc_clocksource中进行
time_init
|________________x86_late_time_init |_________x86_init.timers.timer_init (arch/x86/kernel/x86_init.c) |________hpet_time_init |_____hpet_enable |____hpet_clocksource_register |_____set_default_time_irq |________________tsc_init |________x86_platform.calibrate_tsc (x86_init.c) |______native_calibrate_tsc |___quit_pit_calibrate |
- static int __init init_tsc_clocksource(void)
- {
- if (!cpu_has_tsc || tsc_disabled > 0 || !tsc_khz)
- return 0;
- if (tsc_clocksource_reliable)
- clocksource_tsc.flags &= ~CLOCK_SOURCE_MUST_VERIFY;
- /* lower the rating if we already know its unstable: */
- if (check_tsc_unstable()) {
- clocksource_tsc.rating = 0;
- clocksource_tsc.flags &= ~CLOCK_SOURCE_IS_CONTINUOUS;
- }
- /*
- * Trust the results of the earlier calibration on systems
- * exporting a reliable TSC.
- */
- if (boot_cpu_has(X86_FEATURE_TSC_RELIABLE)) {
- clocksource_register_khz(&clocksource_tsc, tsc_khz);
- return 0;
- }
- schedule_delayed_work(&tsc_irqwork, 0);
- return 0;
- }
- /*
- * We use device_initcall here, to ensure we run after the hpet
- * is fully initialized, which may occur at fs_initcall time.
- */
- device_initcall(init_tsc_clocksource);
所以,clocksource 的PK之战中,TSC技压群雄,完爆HPET/PIT/ACPI_PM,成为current_clocksource。clocksource之战如何进行,如何选择当前时钟源,新的时钟源注册会带来什么影响。Linux如何根据时钟源完成计时,这个就在下一篇clocksource中介绍。
评论暂时关闭