本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn:
[email protected]
来源: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,而不是到该函数中去删除。