- 论坛徽章:
- 6
|
本帖最后由 瀚海书香 于 2013-04-27 10:04 编辑
回复 6# uliux
目前x86计算机上的时钟振荡器有很高的精度,linux内核可以读振荡器中的计数器,通过比较上一次读的值与当前值,以确定中断是否丢失。如果发现中断丢失,则本次中断处理程序会给jiffies_64增加相应的计数。也就是说全局jiffies是可以弥补丢失的。那么每一个定时器如何弥补丢失的jiffies呢?
x86下时钟中断的处理函数:
中断触发---->irq0---->timer_interrupt---->global_clock_event->event_hander---->tick_handle_periodic
---->tick_periodic---->update_process_times---->run_local_timers---->raise_softirq(TIMER_SOFTIRQ)
对应的时钟软中断处理函数:
run_timer_softirq---->__run_timers- static inline void __run_timers(struct tvec_base *base)
- {
- struct timer_list *timer;
- spin_lock_irq(&base->lock);
- while (time_after_eq(jiffies, base->timer_jiffies)) {
- struct list_head work_list;
- struct list_head *head = &work_list;
- int index = base->timer_jiffies & TVR_MASK;
- /*
- * Cascade timers:
- */
- if (!index &&
- (!cascade(base, &base->tv2, INDEX(0))) &&
- (!cascade(base, &base->tv3, INDEX(1))) &&
- !cascade(base, &base->tv4, INDEX(2)))
- cascade(base, &base->tv5, INDEX(3));
- ++base->timer_jiffies;
- list_replace_init(base->tv1.vec + index, &work_list);
- while (!list_empty(head)) {
- void (*fn)(unsigned long);
- unsigned long data;
- timer = list_first_entry(head, struct timer_list,entry);
- fn = timer->function;
- data = timer->data;
- timer_stats_account_timer(timer);
- base->running_timer = timer;
- detach_timer(timer, 1);
- spin_unlock_irq(&base->lock);
- call_timer_fn(timer, fn, data);
- spin_lock_irq(&base->lock);
- }
- }
- base->running_timer = NULL;
- spin_unlock_irq(&base->lock);
- }
复制代码 这个函数是一个while循环,如果时钟中断信号丢失,那么全局(jiffies-base->timer_jiffies)> 1,这个函数就会一个一个的执行,直到处理完所有的定时器。
|
|