为什么同一个TASKLET不能同时在两个核心上执行?

时间:2015-10-14 14:01:55

标签: linux-kernel kernel interrupt tasklet softirq

在ARM平台的linux内核实现中,tasklet中的延迟工作被添加到percpu vec | vec_hi列表中。

  1. 现在从ISR执行返回时,它将在softirq和tasklet中解决延迟工作。
  2. 现在可以在启用了IRQ的中断上下文中处理这个延迟的工作,或者有ksoftirq线程可以在进程上下文中处理它。
  3. 同一个tasklet将在同一个CPU上执行,因为ksoftirq thread是percpu。
  4. 我在很多书中都看到过,例如LDD,Robert Love的书,声称同一个tasklet不能同时在两个核心上执行?
  5. 如何?有人可以帮我这个......如果是这样的话,我错过了什么?

2 个答案:

答案 0 :(得分:2)

这是真的。虽然可以在任意数量的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)确保如果已经在某个其他CPU上调度了tasklet但尚未执行,则将被添加到tasklets-to-run队列中在后来的CPU上(因此根本不会在后来的CPU上执行)。

另一方面,如果它已经开始在第一个CPU上执行,TASKLET_STATE_SCHEDULE位将被清除(因此可能再次设置),因此另一个tasklet_schedule调用确保tasklet最终将在后来的CPU上重新执行,但直到它在第一个CPU上运行完成后才会重新执行。

答案 1 :(得分:1)

softirqs是下半部分中断处理,基于一个基于索引的函数调用机制,其中该函数实现softirq的功能。

维护一个函数指针数组。注册softirq时,有效的函数指针被写入适当的索引。该指数代表了 softirq的编号,0是最高优先级的softirq。保留一个单词作为挂起的softirq的掩码。

当前9的softirq数由一个字的每个位表示,当sofirqs被提升时,掩码中的相应位被设置。接下来,当内核想要运行挂起的softirq时,它使用屏蔽的字来识别挂起的softirqs ,并使用数组调用适当的函数调用,其第0个索引与掩码字的第0位映射。

Tasklet在softirqs上实现,索引0和数组的索引5包含指向分别处理高和正常tasklet的函数的指针。 Tasklet由一个结构标识,该结构包含一个函数指针和一个状态标志以及其他成员。

每当创建tasklet时,都会创建一个结构,使用实现tasklet的函数的地址填充函数指针。保留所有此类结构的链接列表。 当调度tasklet时,它(内核)将相应的结构添加到链接列表的头部并提高tasklet的softirq,即设置掩码字中的相应位。

接下来,当调用处理tasklet的函数时,它检查了链接列表的所有元素,并在状态标志未运行时调用结构中的函数,这表明它已经在处理器中运行。

因此内核确保在多个处理器中没有运行2个相同的tasklet。