ok我们接下来来看下定时器超时的机制,关键在这段代码:
Java代码
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)); 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));index为0就说明当前要处理的定时器不在base->tv1 中.因此我们需要cascade来进行调解.
Java代码
///得到在N级(也就是tv2,tv3...)的定时器表中的slot.这里可以对照我们前面的internal_add_timer加入定时器的情况. #define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK) static int cascade(struct tvec_base *base, struct tvec *tv, int index) { /* cascade all the timers from tv up one level */ struct timer_list *timer, *tmp; struct list_head tv_list; ///这里实例化tv_list为我们将要处理的链表.并将老的list重新初始化为空. list_replace_init(tv->vec + index, &tv_list); /* * We are removing _all_ timers from the list, so we * don't have to detach them individually. */ list_for_each_entry_safe(timer, tmp, &tv_list, entry) { BUG_ON(tbase_get_base(timer->base) != base); ///重新加入定时器,也就是加入到自己对应的位置 internal_add_timer(base, timer); } ///然后返回index,这里可以看到如果index为空则说明这个级别的定时器也已经都处理过了,因此我们需要再处理下一个级别. return index; } ///得到在N级(也就是tv2,tv3...)的定时器表中的slot.这里可以对照我们前面的internal_add_timer加入定时器的情况. #define INDEX(N) ((base->timer_jiffies >> (TVR_BITS + (N) * TVN_BITS)) & TVN_MASK) static int cascade(struct tvec_base *base, struct tvec *tv, int index) { /* cascade all the timers from tv up one level */ struct timer_list *timer, *tmp; struct list_head tv_list; ///这里实例化tv_list为我们将要处理的链表.并将老的list重新初始化为空. list_replace_init(tv->vec + index, &tv_list); /* * We are removing _all_ timers from the list, so we * don't have to detach them individually. */ list_for_each_entry_safe(timer, tmp, &tv_list, entry) { BUG_ON(tbase_get_base(timer->base) != base); ///重新加入定时器,也就是加入到自己对应的位置 internal_add_timer(base, timer); } ///然后返回index,这里可以看到如果index为空则说明这个级别的定时器也已经都处理过了,因此我们需要再处理下一个级别. return index; }可以看到定时器处理始终都是在处理tv1,如果tv1已经处理完了,则将tv2添加到tv1,以此类推.
而定时器软中断如何触发呢,是用update_process_times来触发的,这个函数比较简单,主要是调用run_local_timers来触发软中断:
Java代码
void run_local_timers(void) { hrtimer_run_queues(); ///触发软中断. raise_softirq(TIMER_SOFTIRQ); softlockup_tick(); }