Linux 时钟管理
DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = { .clock_base = { { .index = CLOCK_REALTIME, .get_time = &ktime_get_real, .resolution = KTIME_LOW_RES, }, { .index = CLOCK_MONOTONIC, .get_time = &ktime_get, .resolution = KTIME_LOW_RES, }, } }; 图 4 展示了 hrtimer 如何通过 hrtimer_bases 来管理 timer。 图 3. hrtimer 的时钟管理 每个 hrtimer_bases 都包含两个 clock_base,一个是 CLOCK_REALTIME 类型的,另一个是 CLOCK_MONOTONIC 类型的。hrtimer 可以选择其中之一来设置 timer 的 expire time, 可以是实际的时间 , 也可以是相对系统运行的时间。 在 hrtimer_run_queues 的处理中,首先要通过 hrtimer_bases 找到正在执行当前中断的 CPU 相关联的 clock_base,然后逐个检查每个 clock_base 上挂的 timer 是否超时。由于 timer 在添加到 clock_base 上时使用了红黑树,最早超时的 timer 被放到树的最左侧,因此寻找超时 timer 的过程非常迅速,找到的所有超时 timer 会被逐一处理。超时的 timer 根据其类型分为 softIRQ / per-CPU / unlocked 几种。如果一个 timer 是 softIRQ 类型的,这个超时的 timer 需要被转移到 hrtimer_bases 的 cb_pending 的 list 上,待 IRQ0 的软中断被激活后,通过 run_hrtimer_pending 执行,另外两类则必须在 hardIRQ 中通过 __run_hrtimer 直接执行。不过在较新的 kernel(> 2.6.29)中,cb_pending 被取消,这样所有的超时 timers 都必须在 hardIRQ 的 context 中执行。这样修改的目的,一是为了简化代码逻辑,二是为了减少 2 次 context 的切换:一次从 hardIRQ 到 softIRQ,另一次从 softIRQ 到被超时 timer 唤醒的进程。 在 update_process_times 中,除了处理处于低精度模式的 hrtimer 外,还要唤醒 IRQ0 的 softIRQ(TIMER_SOFTIRQ(run_timer_softirq))以便执行 timer wheel 的代码。由于 hrtimer 子系统的加入,在 IRQ0 的 softIRQ 中,还需要通过 hrtimer_run_pending 检查是否可以将 hrtimer 切换到高精度模式,如清单 5 所示: 清单 5. hrtimer 进行精度切换的处理函数
|
- stm8s开发(五) TIMER的使用:定时!(09-18)
- STM8S Timer2_OC1_PWM1输出模式(12-03)
- TimerA流水灯问题分析(12-02)
- LPC2103之timer0 ang timer1(11-29)
- MSP430F5529 (六)定时器Timer_A-1(11-28)
- MSP430F5529 (六)定时器Timer_A-2(11-28)