当前位置: 首页 >> 开源操作系统 >> 彻底搞清Linux timer问题
 

彻底搞清Linux timer问题

作者:      来源:fineamy.cublog.cn     发表时间:2007-06-12     浏览次数:      字号:    

代码实现:

完美搞清LINUX TIMER问题!
QUOTE: /***
* timer_pending - is a timer pending?
* @timer: the timer in question
*
* timer_pending will tell whether a given timer is currently pending,
* or not. Callers must ensure serialization wrt. other operations done
* to this timer, eg. interrupt contexts, or other CPUs on SMP.
*
* return value: 1 if the timer is pending, 0 if not.
*/
static inline int timer_pending(const struct timer_list * timer) {
        return timer->entry.next != NULL;
}
QUOTE: struct timer_list {
        struct list_head entry;
        unsigned long expires;
        void (*function)(unsigned long);
        unsigned long data;
        struct timer_base_s *base;
};
上面TIMER中entry字段用于将该TIMER连接到相应的TIMER队列。借用ULK3中的图片说明一下,
 

如图,比如连接到图中的TV2双链中。

那么这里有两个问题

  1. timer挂起为什么可以通过
    QUOTE: return timer->entry.next != NULL;
    
    来判断,是不是TIMER在过期后执行前首先要从双链中解除下来。所以上面的判断可以这样进行。
  2. QUOTE: typedef struct tvec_t_base_s {
            spinlock_t lock;
            unsigned long timer_jiffies;
            struct timer_list *running_timer;
            tvec_root_t tv1;
            tvec_t tv2;
            tvec_t tv3;
            tvec_t tv4;
            tvec_t tv5;
        } tvec_base_t;
    
    中timer_jiffies如何更新. 该字段是用于从
    QUOTE: unsigned long idx = expires - base->timer_jiffies;
    
    算式中得出idx ,利用该idx 将TIMER插入相应的双链表。即

    QUOTE: tvec_root_t tv1;
            tvec_t tv2;
            tvec_t tv3;
            tvec_t tv4;
            tvec_t tv5;
    
    中的一个。

qtdszws (异次元空间)发表于 2007-5-17 15:12

»1.timer挂起为什么可以通过return timer->entry.next != NULL; 来判断,是不是TIMER在过期后执行前首先要从双链中解除下来。所以上面的判断可以这样进行。

»2.timer_jiffies如何更新

在run_timer_list中更新

[Copy to clipboard]CODE: v2.4.0 static inline void
run_timer_list(void) {
        spin_lock_irq(&timerlist_lock);
        while ((long)(jiffies - timer_jiffies) >= 0) {//定时器到时,可能还错过了几个jiffies,补上
                struct list_head *head, *curr;
                if (!tv1.index) {// 最近要执行的定时器队列已被遍历一遍
                        int n = 1;
                        do {
                                cascade_timers(tvecs[n]);
                        } while (tvecs[n]->index == 1 && ++n < NOOF_TVECS);
                }
repeat:
                head = tv1.vec + tv1.index;
                curr = head->next;
                if (curr != head) {
                        struct timer_list *timer;
                        void (*fn)(unsigned long);
                        unsigned long data;
                        timer = list_entry(curr, struct timer_list, list);
                        fn = timer->function;
                        data= timer->data;
                        detach_timer(timer);
                        timer->list.next = timer->list.prev = NULL;
                        //一次只运行一个定时器,run_timer_list是在timer_bh中运行的,
                        //所以一次只有一个CPU执行run_timer_list
                        timer_enter(timer);
                        spin_unlock_irq(&timerlist_lock);
                        fn(data);//执行定时任务
                        spin_lock_irq(&timerlist_lock);
                        timer_exit();
                        goto repeat;
                }
                ++timer_jiffies; //更新
                tv1.index = (tv1.index + 1) & TVR_MASK;
        }
        spin_unlock_irq(&timerlist_lock);
}

责任编辑 webmaster

 
 
 
 
 
评论更多>>
 
 
 
发表
 
姓名: QQ:
性别: MSN:
E-mail: 主页:
评分: 1 2 3 4 5
评论内容:
验证码:
  
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •