时间子系统7_高分辨率定时器处理
// 高分辨率下的定时器软中断
// 当增加一个hrtimer到rbtree中后,会raise高分辨率定时器软中断
// 函数任务:
// 1.关中断下,运行所有hrtimer
// 注:
// 在hrtimers_init中,open_softirq(HRTIMER_SOFTIRQ, run_hrtimer_softirq);
1.1 static void run_hrtimer_softirq(struct softirq_action *h)
{
//遍历运行所有到期的hrtimer
hrtimer_peek_ahead_timers();
}
// 遍历运行hrtimer
// 函数任务:
// 1.关中断
// 2.运行hrtimer
// 调用路径:run_hrtimer_softirq->hrtimer_peek_ahead_timers
1.2 void hrtimer_peek_ahead_timers(void)
{
unsigned long flags;
//关中断
local_irq_save(flags);
hrtimer_interrupt(&__get_cpu_var(tick_cpu_device)->evtdev);
local_irq_restore(flags);
}
// 高分辨率tick device事件处理函数
// 遍历执行本cpu上的hrtimer
// 调用路径:
// 1.run_hrtimer_softirq->....->hrtimer_interrupt 软中断路径。
// 2.当激活高分辨率模式时,安装此函数作为tick device的事件处理函数。
// 函数任务:
// 1.遍历时钟基础
// 1.1 运行到期的hrtimer
// 2.如果处理完所有hrtimer,关闭时钟事件设备,退出
// 3.重复步骤1,最多遍历3次
// 4.更新统计信息
// 4.1 cpu_base->nr_hangs统计一次hrtimer未能处理完所有hrtimer的次数
// 4.2 cpu_base->hang_detected指示有hrtimer待处理
// 4.3 cpu_base->max_hang_time记录hrtimer_interrupt花费的最大时间,即hrtimer可能被延迟的最大时间
// 5.根据花费的时间计算时钟事件设备下一次到期的时间
// 5.1 如果处理hrtimer花费时间超过1ms,推迟下一次到期时间为1ms后
// 5.2 否则下一次到期时间为花费的时间
1.3 void hrtimer_interrupt(struct clock_event_device *dev)
{
struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
struct hrtimer_clock_base *base;
ktime_t expires_next, now, entry_time, delta;
int i, retries = 0;
cpu_base->nr_events++;
dev->next_event.tv64 = KTIME_MAX;
entry_time = now = ktime_get();
retry:
expires_next.tv64 = KTIME_MAX;
//防止此段时间内其他cpu的hrtimer迁移到本cpu时
raw_spin_lock(&cpu_base->lock);
cpu_base->expires_next.tv64 = KTIME_MAX;
base = cpu_base->clock_base;
//遍历所有时钟基础的hrtime
for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) {
ktime_t basenow;
struct rb_node *node;
//时钟基础的时间与实际时间可能有偏移,hrtimer的到期时间为实际时间的绝对值
basenow = ktime_add(now, base->offset);
while ((node = base->first)) {
struct hrtimer *timer;
timer = rb_entry(node, struct hrtimer, node);
//如果当前hrtimer还没有到期
if (basenow.tv64 < hrtimer_get_softexpires_tv64(timer)) {
ktime_t expires;
//更新时钟事件下一次到期时间
expires = ktime_sub(hrtimer_get_expires(timer),
base->offset);
if (expires.tv64 < expires_next.tv64)
expires_next = expires;
break;
}
//否则立即执行定时器
__run_hrtimer(timer, &basenow);
}
base++;
}
//更新时钟基础下一次到期时间
cpu_base->expires_next = expires_next;
raw_spin_unlock(&cpu_base->lock);
//没有要到期的hrtimer,关闭时间事件设备
if (expires_next.tv64 == KTIME_MAX ||
!tick_program_event(expires_next, 0)) {
cpu_base->hang_detected = 0;
return;
}
//防止一直处理hrtimer,最大遍历次数3
now = ktime_get();
cpu_base->nr_retries++;
if (++retries < 3)
goto retry;
//有挂起的hrtimer需要处理
cpu_base->nr_hangs++;
cpu_base->hang_detected = 1;
//计算hrtimer_interrupt处理hrtimer花费的时间
delta = ktime_sub(now, entry_time);
if (delta.tv64 > cpu_base->max_hang_time.tv64)
cpu_base->max_hang_time = delta;
//根据花费的时间计算时钟事件设备下一次到期的时间
// 如果处理hrtimer花费时间超过1ms,推迟下一次到期时间为1ms后
// 否则下一次到期时间为花费的时间
if (delta.tv64 > 100 * NSEC_PER_MSEC)
expires_next = ktime_add_ns(now, 100 * NSEC_PER_MSEC);
else
expires_next = ktime_add(now, delta);
tick_program_event(expires_next, 1);
}
// 运行hrtimer
// 调用路径:hrtimer_interrupt->__run_hrtimer
// 函数任务:
// 1.从红黑树中删除hrtimer
// 2.设置其为执行状态
// 3.执行hrtimer回调函数
// 3.1 如果hrtimer需要继续执行,重新建hrtimer加入到红黑树中
// 4.清除其正在执行标志
1.4 static void __run_hrtimer(struct hrtimer *timer, ktime_t *now)
{
struct hrtimer_clock_base *base = timer->base;
struct hrtimer_cpu_base *cpu_base = base->cpu_base;
enum hrtimer_restart (*fn)(struct hrtimer *);
int restart;
//从红黑树中删除hrtimer,设置其为执行状态
__remove_hrtimer(timer, base, HRTIMER_STATE_CALLBACK, 0);
fn = timer->function;
raw_spin_unlock(&cpu_base->lock);
//执行hrtimer回调函数
restart = fn(timer);
raw_spin_lock(&cpu_base->lock);
//将hrtimer重新入队
if (restart != HRTIMER_NORESTART) {
enqueue_hrtimer(timer, base);
}
//清除其正在执行标志
timer->state &= ~HRTIMER_STATE_CALLBACK;
}
// 运行高分辨率定时器
// 调用路径:
// update_process_times->run_local_timers->hrtimer_run_queues
// 当没有开启高分辨率模式时,高分辨率定时器由低分辨率时钟软中断调用,此函数在低分辨率中衔接高分辨率
// 函数任务:
// 1.检查高分辨率率定时器框架是否已经被激活
// 1.1 当高分辨率定时器框架被激活时,hrtimer已经通过hrtimer_interrupt被运行
// 2.获取当前时间
// 3.遍历时钟基础,如果hrtimer到期,运行其回调函数
// 注:
// 当高分辨率率定时器框架为激活时,高分辨率定时器通过时钟中断运行,频率为jiffiy。
2.1 void hrtimer_run_queues(void)
{
struct timerqueue_node *node;
struct hrtimer_cpu_base *cpu_base = &__get_cpu_var(hrtimer_bases);
struct hrtimer_clock_base *base;
int index, gettime = 1;
//如果高分辨率定时器框架已经激活,则hrtimer已经通过hrtimer_interrupt被运行,直接返回
if (hrtimer_hres_active())
return;
//遍历cpu的时钟基础,运行到期的hrtimer
for (index = 0; index < HRTIMER_MAX_CLOCK_BASES; index++) {
base = &cpu_base->clock_base[index];
//当前时钟基础已经没有active的hrtimer,则遍历下一个
if (!timerqueue_getnext(&base->active))
continue;
//获取当前时间
if (gettime) {
hrtimer_get_softirq_time(cpu_base);
gettime = 0;
}
raw_spin_lock(&cpu_base->lock);
//获取下一个active的hrtimer
while ((node = timerqueue_getnext(&base->active))) {
struct hrtimer *timer;
timer = container_of(node, struct hrtimer, node);
//如果hrtimer到期,则运行其回调函数
if (base->softirq_time.tv64 <=
hrtimer_get_expires_tv64(timer))
break;
__run_hrtimer(timer, &base->softirq_time);
}
raw_spin_unlock(&cpu_base->lock);
}
}
最后更新:2017-04-03 14:54:27