为什么同一个TASKLET不能同时在两个内核上执行?
在ARM平台的Linux内核实现中,将tasklet中的延迟工作添加到percpu vec | vec_hi列表中。
怎么样? 有人可以帮助我...如果是这样,我错过了什么?
这是真的。 虽然可以在任意数量的CPU上调度tasklet(即请求tasklet执行),但它只能在一个CPU上执行。
原因是我相信简化开发模型:使其更容易实现本质上是中断处理程序的内容,而无需担心由于在多个处理器上同时执行而导致的竞争 - 并且不会禁用其他中断。 (很明显,驾驶员开发人员需要了解的其他比赛机会还很多,但这些都是最难解决的问题。)
如果你问的是实现,其实很简单。 在tasklet_action
,调用tasklet_trylock
。 它使用保证原子函数test_and_set_bit
来设置TASKLET_STATE_RUN
位。 这只能在一个处理器上成功。 因此,所有其他处理器都会被禁止执行该tasklet,直到该位被清除 - 这只能由在tasklet完成后设置它的处理器完成。
编辑:
说明:在任意数量的CPU上调用tasklet_schedule
(在执行之前)会导致tasklet执行一次:在第一个进行调用的CPU上。 同样的机制( test_and_set_bit
)确保如果tasklet已经在其他某个CPU上被调度过但尚未执行,它将不会被添加到后面的CPU上的tasklets-to-run队列中(因此不会被在后面的CPU上执行)。
另一方面,如果它已经开始在第一个CPU上执行,则TASKLET_STATE_SCHEDULE
位将被清除(因此可能会被重新设置),所以对tasklet_schedule
另一个调用将确保最终将重新执行tasklet以后的CPU,但是直到它在第一个CPU上运行完成后。
softirqs是下半部中断处理,它基于一个基于索引的函数调用机制,其中函数实现了softirq的功能。
一个函数指针数组被维护。 当softirq被注册时,一个有效的函数指针被写入适当的索引。 索引代表softirq的编号,0是最高优先级softirq。 一个字作为未决softirq的掩码来维护。
当sofirqs被提升时,掩码中的相应位被设置,当前9个softirqs的数量由一个字的每一位表示。接下来,当内核想要运行待处理的softirqs时,它使用掩码字来标识待处理的softirqs,函数调用是使用数组的第0个索引映射到掩码字的第0位来调用的。
Tasklet通过softirqs实现,数组的索引0和索引5包含指向分别处理高和正常小任务的函数的指针。 Tasklet使用包含函数指针和其他成员中的状态标志的结构来标识。
无论何时创建tasklet,都会创建一个结构,并使用实现该tasklet的函数的地址填充函数指针。 维护所有这些结构的链接列表。 当tasklet被调度时,它(内核)将相应的结构添加到链接列表的头部并提升tasklet的softirq,即在掩码字中设置相应的位。
接下来,当调用处理tasklet的函数时,它会检查链接列表的所有元素,并在状态标志未运行时调用该结构中的函数,这表明它已经在处理器中运行。
因此,内核确保没有2个相同的tasklet在多个处理器中运行。
链接地址: http://www.djcxy.com/p/84803.html上一篇: why same TASKLET can't execute on two core simultaneously?