与低精度timer不同,hrtimer实现了timer的精准到期控制。
hrtimer定义了8组timer base,hrtimer添加时可以使用不同时间类型做定时。
hrtimer在注册时使用的ktime可以选择使用ABS绝对时间,也可以使用基于now的REL相对时间做定时。
hrtimer提供了两种timer执行上下文:hard irq、soft irq
与低精度timer使用的哈希链表不同,hrtimer内部使用红黑树(timerqueue)来管理timer队列,hrtimer机制用自己的tick中断回调替换了原有的perioidic tick,原有的tick被实现为一个hrtimer(sched timer)注册到hrtimer队列,这样hrtimer实现了timer的精准到期控制,同时将tick纳入到了自己的timer loop中。
hrtimer的使能需要系统满足一些条件,正常情况下,在arch timer初始化结束后,会从low res切换到hres,同时替换tick中断处理函数,由hres完全接管tick。原来的tick功能由一个新的hrtimer(sched timer)来实现。
hrtimer也实现了debug object,可以对用户申请释放过程做预防监控。
tick_switch_to_oneshot
- /include/linux/hrtimer.h # interface
- /kernel/time/hrtimer.c # implementation
- /include/linux/timerqueue.h # timer rb-tree
struct hrtimer
hrtimer基本结构体,一个hrtimer,就是一个timer
主要定义回调函数、到期ktime、所使用的clock base、ktime是否为相对时间、硬timer还是软timer
struct hrtimer_cpu_base
per cpu hrtimer base,里面主要包括了一个clock base的合集。
struct hrtimer_clock_base
一个clock base,主要包括了这个clock base的get_time接口,timerqueue(所有使用这个clock base的timer队列)
struct timerqueue...
管理hrtimer的红黑树,用于降低hrtimer“队列”的插入和查找复杂度。
所以,综上:
hrtimer_bases
per cpu hrtimer_cpu_base
hrtimer_init
初始化一个hrtimer
clock:CLOCK_REALTIME / CLOCK_MONOTONIC,会最终对应到对应的timer base上。
mode:HRTIMER_ABS / HRTIMER_REL设置ktime时间所表示的是wall time还是基于now的相对时间。
hrtimer_start
启动timer
hrtimer_forward
置后一个timer
hrtimer_cancel
取消一个timer,死等
hrtimer_try_to_cancel
取消一个timer,不死等
hrtimer_restart
取消的timer可以重新restart
hrtimer_get_remaining
获取timer剩余到期时间
rtimer_active
获取timer是否active
hrtimer_interrupt
hrtimers_init
在start_kernel中初始化hrtimer机制,使能hrtimer softirq。
hrtimer_run_softirq
hrtimer软中断回调函数,用于运行HRTIMER_ACTIVE_SOFT类型的timer
hrtimer_run_softirq
# 运行所有到期softirq timer(HRTIMER_ACTIVE_SOFT)
__hrtimer_run_queues
# 重新更新timerqueue,更新下次到期时间
hrtimer_update_softirq_timer
# 调用tick_program_event更新下次tick时间
__hrtimer_reprogram
hrtimer_run_queues
hrtimer硬中断回调函数,用于运行HRTIMER_ACTIVE_HARD类型的timer
hres切换前,在tick device的tick中断回调中运行(run_local_timers)
hres切换后,HRTIMER_ACTIVE_HARD类型的timer在hrtimer机制自己的interrupt handler hrtimer_interrupt
中调用。
low res => hres
这个函数在legacy tick中还有个作用,就是不断判断是否能切换hres,在arch timer初始化结束后,切换条件满足,从legacy切换到hres。
tick_handle_periodic->
run_local_timers
hrtimer_run_queues
hrtimer_switch_to_hres
tick_init_highres
- tick_switch_to_oneshot(hrtimer_interrupt)
- tick_setup_sched_timer # add sched_timer
切换后,会用tick_setup_sched_timer创建新的tick timer(tick_sched_timer),替换原来的periodic_handler tick中断回调。后面jiffies也是在这个timer中更新
tick_sched_timer # new sched tick handler
tick_sched_do_timer
tick_do_update_jiffies64 # update jiffies
who legacy timer working after hres
切换hres后,低精度timer raise timer softirq的动作在tick_sched_timer中触发,timer softirq在中断下半部被处理。
hrtimer_interrupt
hrtimer提供的tick device handler,切换到hres后,替换掉原来的tick_handle_periodic回调。
会从timerqueue中取出timer运行,运行后根据timer到期时间设置下次tick时间。
https://lwn.net/Articles/167897/
https://blog.csdn.net/wangquan1992/article/details/122997220