免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 735 | 回复: 0
打印 上一主题 下一主题

2.6中小心用del_timer_sync [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-11-27 08:54 |只看该作者 |倒序浏览
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,而不是到该函数中去删除。

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/12313/showart_206539.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP