免费注册 查看新帖 |

Chinaunix

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

对tasklet的疑问 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-06-12 10:06 |只看该作者 |倒序浏览
代码如下, 疑问一:tasklet_schedule判断该tasklet是否已经被SCHE,如果没有则执行 __tasklet_schedule(),并且只加入当前的CPU队列,而不是每个CPU队列,
  所以说每个tasklet只是被schedule一次?但ULK3上说可能是多次。

疑问二:tasklet_action()中,
       if (tasklet_trylock(t)) 首先判断是否已经在其他CPU上执行,如果只被在当前CPU上schedule一次,这个似乎没有必要?

疑问三: tasklet如果被schedule多次,怎么保证它只被执行一次,而不是在各个CPU上各执行一次?

以上假设在SMP环境下。高手请指点。HELP!


void fastcall __tasklet_schedule(struct tasklet_struct *t)
{
    unsigned long flags;

    local_irq_save(flags);
    t->next = __get_cpu_var(tasklet_vec).list;
    __get_cpu_var(tasklet_vec).list= t;  /* 只是当前CPU ? */
    raise_softirq_irqoff(TASKLET_SOFTIRQ);
    local_irq_restore(flags);
}

static inline void tasklet_schedule(struct tasklet_struct *t)
{
    if(!test_and_set_bit(TASKLET_STATE_SCHED,&t->state))
/*判断是否被SCHED,如果是,则什么也不做,这不是只调度一次吗? */


        __tasklet_schedule(t);
}



static void tasklet_action(struct softirq_action *a)
{
    struct tasklet_struct *list;

    local_irq_disable();
    list = __get_cpu_var(tasklet_vec).list;
    __get_cpu_var(tasklet_vec).list = NULL;
    local_irq_enable();

    while (list) {
        struct tasklet_struct *t = list;

        list = list->next;

      
       if (tasklet_trylock(t)) {
             /*判断是否在其他CPU上执行 */
            if (!atomic_read(&t->count)) {
                if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
                    BUG();
                t->func(t->data);
                tasklet_unlock(t);
                continue;
            }
            tasklet_unlock(t);
        }

        /*已经在其他CPU上执行了,为什么还要再次加入当前的CPU队列? */
        local_irq_disable();
        t->next = __get_cpu_var(tasklet_vec).list;
        __get_cpu_var(tasklet_vec).list = t;
        __raise_softirq_irqoff(TASKLET_SOFTIRQ);
        local_irq_enable();
    }
}



[ 本帖最后由 rwen2012 于 2008-6-12 10:10 编辑 ]

论坛徽章:
0
2 [报告]
发表于 2008-06-12 10:10 |只看该作者
为2.6.23, 较早的版本也差不多

论坛徽章:
0
3 [报告]
发表于 2008-06-12 10:27 |只看该作者

回复 #2 rwen2012 的帖子

if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))

SCHED被清除了, 中断上半部使该tasklet可以再一次被调用,但是不能不同时执行。

算是看明白了。


tasklet的特性也再次,可以多次被调用,但是不能同时被执行,这样使用时不用显式加锁,较softirq更方便

[ 本帖最后由 rwen2012 于 2008-6-12 10:32 编辑 ]

论坛徽章:
0
4 [报告]
发表于 2008-06-12 10:33 |只看该作者
根源在于你对tasklet的理解有问题,tasklet不保证函数只运行一次,而是不同时运行,不像别的softirq,它可能同时在多CPU运行,tasklet不会,这把这种同步的负担由驱动程序作者移动到内核,就像中断处理机制一样

论坛徽章:
0
5 [报告]
发表于 2008-06-12 10:38 |只看该作者

回复 #4 flw2 的帖子

谢谢,是理解有问题,

但它能保证“每次调度只运行一次“,是吗?谢谢

论坛徽章:
0
6 [报告]
发表于 2008-06-12 10:43 |只看该作者

回复 #5 rwen2012 的帖子

“每次调度只运行一次“ 怎么理解?

论坛徽章:
0
7 [报告]
发表于 2008-06-12 10:50 |只看该作者

回复 #6 flw2 的帖子

每次tasklet_schedule(tasklet)只会使tasklet->func()运行一次

论坛徽章:
0
8 [报告]
发表于 2008-06-12 10:59 |只看该作者
如果真的调度了,就运行一次了,就像中断一样,来了10次可能也被看成是一次,但是它一次会处理完该处理的事情,原则是保证不会丢失通知

if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))
                    BUG();
                t->func(t->data);
所以上面这段代码的顺序不能换,否则可能丢失了,在回来就是BUG了

论坛徽章:
0
9 [报告]
发表于 2008-06-12 11:17 |只看该作者
好, 还是你理解得透彻, 谢谢指点
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP