完美搞清LINUX TIMER问题!
时间:2007-05-24 来源:fineamy
代码实现:
完美搞清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中的图片说明一下, 500)this.width=500;" border=0>
如图,比如连接到图中的TV2双链中。
那么这里有两个问题
- timer挂起为什么可以通过
QUOTE: return timer->entry.next != NULL;
来判断,是不是TIMER在过期后执行前首先要从双链中解除下来。所以上面的判断可以这样进行。 -
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); }
相关阅读 更多 +
排行榜 更多 +