Chinaunix首页 | 论坛 | 博客
  • 博客访问: 47986
  • 博文数量: 37
  • 博客积分: 1800
  • 博客等级: 上尉
  • 技术积分: 451
  • 用 户 组: 普通用户
  • 注册时间: 2010-11-29 19:56
文章存档

2011年(9)

2010年(28)

我的朋友

分类: LINUX

2011-01-06 18:04:42

解密tasklet_schedule背后的故事

本帖最后由 Dolphin 于 2010-9-18 13:45 编辑

Linux的中断处理框架大体为:入口点-->driver安装的中断处理函数-->退出点
通常说Linux下的中断处理分为top和bottom两部分,top部分中断是关闭的,因此一般在这里的代码都会以迅雷不及掩耳盗铃之势做完该做的事,然后打开中断以防止可能的中断丢失。因为要迅雷不及掩耳盗铃,所以大部分耗时的任务交给了bottom部分去处理。bottom阶段中断是打开的,所以有可能被其他中断到来时所打断。
bottom的延后处理,其中之一遍是由tasklet来完成,相对于workqueue这种任务延后机制,tasklet实际上是处在中断上下文中,因为处在空灵世界(不属于任一进程),所以在tasklet中休眠是绝对应该禁止的。
其他的一些bottom方法:
/* PLEASE, avoid to allocate new softirqs, if you need not _really_ high
   frequency threaded job scheduling. For almost all the purposes
   tasklets are more than enough. F.e. all serial device BHs et
   al. should be converted to tasklets, not to softirqs.
*/

enum
{
        HI_SOFTIRQ=0,
        TIMER_SOFTIRQ,
        NET_TX_SOFTIRQ,
        NET_RX_SOFTIRQ,
        BLOCK_SOFTIRQ,
        TASKLET_SOFTIRQ,       
        SCHED_SOFTIRQ,
        HRTIMER_SOFTIRQ,
        RCU_SOFTIRQ,        /* Preferable RCU should always be the last softirq */

        NR_SOFTIRQS
};
  1. static inline void tasklet_schedule(struct tasklet_struct *t)
  2. {
  3.         if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))
  4.                 __tasklet_schedule(t);
  5. }
复制代码
  1. void __tasklet_schedule(struct tasklet_struct *t)
  2. {
  3.         unsigned long flags;

  4.         local_irq_save(flags);
  5.         t->next = NULL;
  6.         *__get_cpu_var(tasklet_vec).tail = t;
  7.         __get_cpu_var(tasklet_vec).tail = &(t->next);
  8.         raise_softirq_irqoff(TASKLET_SOFTIRQ);
  9.         local_irq_restore(flags);
  10. }
复制代码

上诉代码依然处在top阶段,不过做了个标记,留待bottom阶段到来时去检查

转自:

阅读(947) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2011-03-08 14:36:31

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com