读书人

2.6中当心用del_timer_sync

发布时间: 2012-07-20 10:38:30 作者: rapoo

2.6中小心用del_timer_sync
本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn: yfydz_no1@hotmail.com
来源:http://yfydz.cublog.cn

1. 前言del_timer_sync()是del_timer()的同步版,主要是在多处理器情况下使用,如果编译内核时不支持SMP,则是和del_timer()等价。不过2.6下的del_timer_sync()和2.4相比有了较大改变,不小心就会造成内核死锁。 2. 函数实现该函数在 kernel/timer.c 中实现。2.1 2.4.26中的实现/* * SMP specific function to delete periodic timer. * Caller must disable by some means restarting the timer * for new. Upon exit the timer is not queued and handler is not running * on any CPU. It returns number of times, which timer was deleted * (for reference counting). */int del_timer_sync(struct timer_list * timer){ int ret = 0; for (;;) {  unsigned long flags;  int running;  spin_lock_irqsave(&timerlist_lock, flags);  ret += detach_timer(timer);  timer->list.next = timer->list.prev = 0;  running = timer_is_running(timer);  spin_unlock_irqrestore(&timerlist_lock, flags);  if (!running)   break;  timer_synchronize(timer); } return ret;}函数体中主要调用detach_timer()函数和宏timer_is_running(),这两个处理都不是循环的,因此不会出现死循环情况,所以在哪调用这个函数都是安全的。2.2 2.6.17中的实现/*** * del_timer_sync - deactivate a timer and wait for the handler to finish. * @timer: the timer to be deactivated * * This function only differs from del_timer() on SMP: besides deactivating * the timer it also makes sure the handler has finished executing on other * CPUs. * * Synchronization rules: callers must prevent restarting of the timer, * otherwise this function is meaningless. It must not be called from * interrupt contexts. The caller must not hold locks which would prevent * completion of the timer's handler. The timer's handler must not call * add_timer_on(). Upon exit the timer is not queued and the handler is * not running on any CPU. * * The function returns whether it has deactivated a pending timer or not. */int del_timer_sync(struct timer_list *timer){ for (;;) {  int ret = try_to_del_timer_sync(timer);  if (ret >= 0)   return ret; }}2.6中的实现已经明确说明了该函数不能在中断上下文中调用:“It must not be called from interrupt contexts”,这里的中断上下文也就是定时器的处理函数timer.function,因为执行这个函数是在时钟中断中。可看到该实现中就是循环调用try_to_del_timer_sync(),就是这个函数使得不能在中断上下文中使用:/* * This function tries to deactivate a timer. Upon successful (ret >= 0) * exit the timer is not queued and the handler is not running on any CPU. * * It must not be called from interrupt contexts. */int try_to_del_timer_sync(struct timer_list *timer){ tvec_base_t *base; unsigned long flags; int ret = -1;// 取得timer的base base = lock_timer_base(timer, &flags);// 如果base中正在运行的timer就是该timer的话,返回-1// 返回-1后,del_timer_sync()会一直循环// 所以如果在中断上下文中再次调用del_timer_sync(),内核将死锁 if (base->running_timer == timer)  goto out; ret = 0; if (timer_pending(timer)) {  detach_timer(timer, 1);  ret = 1; }out: spin_unlock_irqrestore(&base->lock, flags); return ret;}3. 结论 2.6中的del_timer_sync()的实现和2.4相比已经作了较大改变,绝对不能在定时处理函数中调用,而2.4中实际还是可以调用的,只是返回失败而已。所以一般情况都不要直接去调用定时函数,而是让时钟中断去处理它,可以通过改变中断时间的方法提前调用;如果非要调用,则必须在调用前就删除timer,而不是到该函数中去删除。

读书人网 >互联网

热点推荐