Chinaunix
标题:
同一个tasklet不能同时运行在不同CPU上,why?
[打印本页]
作者:
Huntsmen
时间:
2014-03-04 00:15
标题:
同一个tasklet不能同时运行在不同CPU上,why?
在看中断下半部时,大部分资料讲软中断softirq和tasklet的区别时:
softirq必须是重入的,可以同时运行在不同的CPU上;
而同一个tasklet不能同时运行在不同的CPU上,不同的tasklet可以同时运行在不同的CPU上;
目前是知其然而不知其所以然,有大牛帮忙讲解一下为什么可以,为什么又不可以吗?最好能拿着例子讲解一下,多谢多谢
作者:
tempname2
时间:
2014-03-04 00:42
就是这么设计的,参见LKD软中断一章。
老版的BH接口完全串行化,只要有一个CPU在执行下半部,其它CPU都不能执行下半部。编码简单,只可能跟中断race,效率低,扩展性不好。
后来改成了softirq,完全并行化,扩展性好,但要写代码时要考虑中断race和所有softirq间的race。
Tasklet是折衷的设计,同类型串行,不同类型并行,需要考虑中断race以及不同类型softirq间的race,不用考虑同类型softirq间的race。适用于大多数驱动。
作者:
humjb_1983
时间:
2014-03-04 08:40
完全同意
作者:
asuka2001
时间:
2014-03-04 09:05
回复
1#
Huntsmen
以前也回答过这个问题,顺手粘贴过来:)
static inline void tasklet_schedule(struct tasklet_struct *t)
{
if (!
test_and_set_bit(TASKLET_STATE_SCHED, &t->state)
)
__tasklet_schedule(t);
}
static void tasklet_action(struct softirq_action *a)
{
struct tasklet_struct *list;
local_irq_disable();
list = __this_cpu_read(tasklet_vec.head);
__this_cpu_write(tasklet_vec.head, NULL);
__this_cpu_write(tasklet_vec.tail, &__get_cpu_var(tasklet_vec).head);
local_irq_enable();
while (list) {
struct tasklet_struct *t = list;
list = list->next;
if (
tasklet_trylock(t)
) {
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);
}
local_irq_disable();
t->next = NULL;
*__this_cpu_read(tasklet_vec.tail) = t;
__this_cpu_write(tasklet_vec.tail, &(t->next));
__raise_softirq_irqoff(TASKLET_SOFTIRQ);
local_irq_enable();
}
}
1. 从tasklet_schedule()红色代码那里可以看到,一旦
同一个
tasklet被schedule,直到tasklet_action()蓝色部分清除TASKLET_STATE_SCHED之前,tasklet不允许再次schedule
2. 从橘黄色tasklet_trylock()开始到绿色tasklet_unlock(t)期间,
同一个
tasklet不允许再次运行!
3. 从蓝色到绿色部分,同一个tasklet允许schedule,但是不允许运行!
欢迎光临 Chinaunix (http://bbs.chinaunix.net/)
Powered by Discuz! X3.2