434
王者荣耀
时间子系统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