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



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

  1. 现在,当从ISR执行返回时,它会去处理软线程和微线程中的延迟工作。
  2. 现在这个延迟的工作可以在中断上下文中被处理,irq被启用,或者有ksoftirq线程可以在进程上下文中处理它。
  3. 相同的微线程将在同一个CPU上执行,因为ksoftirq线程是全CPU的。
  4. 我在很多书中看到,例如LDD, Robert Love的书,它声称同一个微线程不能同时在两个核心上执行?

如何?有人能帮我一下吗?如果真是这样,我还错过了什么?

这是真的。虽然微线程可以在任意数量的cpu上调度(即请求微线程执行),但它只会在一个cpu上执行。

我认为这样做的原因是为了简化开发模型:使它更容易实现本质上是中断处理程序,而无需担心由于在多个处理器上同时执行而导致的竞争——同时不禁用其他中断。(游戏邦注:显然,赛车手开发者还需要意识到许多其他的比赛机会,但这些都是最难解决的。)

如果你问的是实现,它实际上很简单。在tasklet_action中,称为tasklet_trylock。它使用保证原子函数test_and_set_bit来设置TASKLET_STATE_RUN位。这只能在一个处理器上成功。因此,所有其他处理器都被阻止执行微线程,直到该位被清除——这只有在微线程完成后设置它的处理器才会完成。

编辑:
澄清:在任意数量的CPU上调用tasklet_schedule(在执行之前)会导致微线程只执行一次:在发出调用的第一个 CPU上。同样的机制(test_and_set_bit)确保如果微线程已经在其他CPU上调度但尚未执行,它将被添加到后一个CPU上的微线程运行队列(因此根本不会在后一个CPU上执行)。

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

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

维护一个函数指针数组。当一个函数被注册时,一个有效的函数指针被写入相应的索引中。指数代表软队列个数,0为优先级最高的软队列。一个字被维护为挂起的软请求的掩码。

当前软电平的数目由单词的每个位表示,当软电平升高时,掩码中相应的位被设置。接下来,当内核想要运行挂起的软请求时,它使用掩码字来标识挂起的软请求,并使用数组调用适当的函数调用,该数组的第0个索引映射为掩码字的第0位。

微线程是通过softirqs实现的,数组的索引0和索引5分别包含处理高微线程和普通微线程的函数的指针。微线程是用一个结构体来标识的,这个结构体包含一个函数指针和一个状态标志。

每当创建微线程时,就会创建一个结构,用实现微线程的函数的地址填充函数指针。维护所有这类结构的链接列表。当微线程被调度时,它(内核)在链表的头部添加一个相应的结构,并提高微线程的softirq,即在掩码字中设置适当的位。

接下来,当处理微线程的函数被调用时,它检查链接列表中的所有元素,如果状态标志没有运行,则在结构中调用该函数,这表明它已经在处理器中运行。

因此内核确保没有两个相同的微线程运行在一个以上的处理器。

相关内容

  • 没有找到相关文章

最新更新