clocksource就是一个固定频率(freq)的time counter,用来为时间系统提供时间计数,并为时间信息接口提供服务(timekeeping)。clocksource不是timer,他不提供中断。
clocksource devices
clocksource的实现,底层既可以是硬件,也可以是软件。实际上他就提供一个read接口,读取counter计数,通过counter/freq,就计算出了相对时间,然后为时间系统提供时间计算和计数。
jiffies是一个默认的clocksource,由于jiffies有固定频率,所以jiffies的值就可以作为这个counter值,用来转换时间。ARM arch timer的system counter,也是一个clocksource,这里只用了system counter,并不是每个core的timer。
以arm arch timer为例,system counter部分被实现为了clocksource,提供时间计数,为timekeeping服务,最终为上层提供出了各类时间获取接口。而processor timer部分,则实现为clockevent device,提供timer中断,最终提供出了tick device,为调度和timer服务。
clocksource rating
clocksource的频率越大,这个相对时间的精度就越高。比如一个10MHz时钟源,他的精度(rating)就是100ns。clocksource结构中有一个rating字段,代表着该时钟源的精度范围:
clocksource mult/shift
clocksource所表示的时间,可以通过下面算式计算:
t = cycle / freq
由于不能使用除法,所以使用mult/shift来代替除法计算
t = (cycle * mult) >> shift;
所以,clocksource需要根据freq计算出一组合适的mult, shift替代值,保存到结构体中。
clocksource watchdog
clocksource提供一个watchdog线程,来监控clocksource的精度,当他发现clocksource精度有问题时,就会把他的rating设置为0,表示精度极差,然后重新选择一个新的clocksource。
clocksource selection
clocksource会向上层timekeeping提供服务,只会有一个精度最高的clocksource被选择,用来提供服务(cur_clocksource)。
系统启动初始化阶段,会先使用jiffies作为默认clocksource,启动过程中,如果有新的clocksource注册进来,则会调用clocksource_select
,重新选择出高精度clocksource,然后调用timekeeping_notify
通知timekeeping系统更新clocksource。
timekeeping系统使用的clocksource中,除了cur_clocksource,还会有一个suspend_clocksource,这个clocksource可以在系统下电后继续运行,专门用于记录睡眠时间,
- include/linux/clocksource.h
- /kernel/time/clocksource.c
clocksource_list
全局clocksource注册链表,根据精度排序。
cur_clocksource
当前选中的clocksource
suspend_clocksource
用来记录suspend时间
clocksource_done_booting
Boot阶段默认clocksource初始化,使用jiffies作为默认clocksource
clocksource_default_clock
返回jiffies clocksource
clocksource_select
重新计算选择高精度的clocksource
clocksource_register_hz
注册clocksource
clocksource_register_khz
注册clocksource
__clocksource_register_scale
注册clocksource,会重新排序,执行clocksource select,并notify timekeeping。
__clocksource_update_freq_scale
通过freq计算更新clocksource的mult/shift
timekeeping_notify
通知timekeeping使用新的clocksource
/sys/devices/system/clocksources/<clocksource>
logs
Register a new clocksource
clocksource: arch_sys_counter: mask: 0x1ffffffffffffff max_cycles: 0x1cd42e208c, max_idle_ns: 881590405314 ns
(max_cycles:counter最大值,max_idle_ns:最大发生翻转的时间)
Switch to new clocksource:
clocksource: Switched to clocksource arch_sys_counter
https://www.cnblogs.com/arnoldlu/p/7078234.html
https://www.kernel.org/doc/Documentation/timers/timekeeping.txt