通过上面的定时器初始化函数我们知道定时器软中断所对应的action是run_timer_softirq,也就是当时钟中断到来,软中断启动时,就会调用这个函数,因此我们来看这个函数:
这个函数功能很简单,它的最关键就是调用__run_timers,这个函数才是真正处理定时器的函数.
Java代码
static void run_timer_softirq(struct softirq_action *h) { struct tvec_base *base = __get_cpu_var(tvec_bases); ///这个函数应该是提供给2.6.31内核的新特性Performance Counters. perf_counter_do_pending(); ///处理hrt timer hrtimer_run_pending(); ///判断当前的jiffies是否大于等于最小的那个超时jiffies.是的话就进入定时器处理 if (time_after_eq(jiffies, base->timer_jiffies)) __run_timers(base); } static void run_timer_softirq(struct softirq_action *h) { struct tvec_base *base = __get_cpu_var(tvec_bases); ///这个函数应该是提供给2.6.31内核的新特性Performance Counters. perf_counter_do_pending(); ///处理hrt timer hrtimer_run_pending(); ///判断当前的jiffies是否大于等于最小的那个超时jiffies.是的话就进入定时器处理 if (time_after_eq(jiffies, base->timer_jiffies)) __run_timers(base); }__run_timers这个函数的主要功能是运行所有超时的定时器:
1
Java代码
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)) { ///这里的head和work_list其实表示的就是已经超时的定时器,也就是我们将要处理的定时器. struct list_head work_list; struct list_head *head = &work_list; ///从timer_jiffies得到所在index,其实也就是在tv1中的index int index = base->timer_jiffies & TVR_MASK; ///开始处理层叠定时器,这里的这个cascade是一个关键的函数,我们下面会分析,这里只需要知道这个函数其实也就是用来一层层的得到这个定时器处于哪个级别中. 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)); ///更新timer_jiffies. ++base->timer_jiffies; ///用work_list替换掉base->tv1.vec + index.这里因为上面的处理中,就算定时器不在base->tv1中,可是通过cascade的调节,会将base->tv2加入到base->tv1中,或者说base->tv3,以此类推. list_replace_init(base->tv1.vec + index, &work_list); ///如果这个值不为空说明有已经超时的定时器.这里head也就是work_list,也就是base->tv1 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); ///设置当前正在处理的定时器为timer(这个主要是针对smp的架构),因为我们是在软中断中进行的,因此要防止多个cpu的并发. set_running_timer(base, timer); ///删除这个定时器. detach_timer(timer, 1); spin_unlock_irq(&base->lock); { int preempt_count = preempt_count(); lock_map_acquire(&lockdep_map); ///执行定时器回调函数 fn(data); ............................................. } spin_lock_irq(&base->lock); } } ///修改base->running_timer为空 set_running_timer(base, NULL); spin_unlock_irq(&base->lock); }