Linux内核定时器的实现(5)

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();    }  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwpfxw.html