【问题标题】:why same TASKLET can't execute on two core simultaneously?为什么相同的任务不能同时在两个核心上执行?
【发布时间】:2015-10-14 14:01:55
【问题描述】:

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

  1. 现在,当从 ISR 执行返回时,它会处理 softirq 和 tasklet 中的延迟工作。
  2. 现在可以在启用了 IRQ 的中断上下文中处理此延迟工作,或者有可以在进程上下文中处理它的 ksoftirq 线程。
  3. 相同的 tasklet 将在与 ksoftirq 线程是 percpu 相同的 CPU 上执行。
  4. 我在很多书中都看到了这一点,例如LDD,Robert Love 的书,声称同一个 tasklet 不能同时在两个内核上执行?

怎么样?有人可以帮我解决这个问题...如果是这样,我错过了什么?

【问题讨论】:

    标签: linux-kernel kernel interrupt tasklet softirq


    【解决方案1】:

    这是真的。虽然可以在任意数量的 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 上调度但尚未执行,它将不会添加到 tasklet-to-run 队列中更高版本的 CPU(因此根本不会在更高版本的 CPU 上执行)。

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

    【讨论】:

    • 感谢您的回复,我明白这一点,但我的意思是,我已经创建了一个 tasklet 并将其添加到我的 ISR 所在的 CPU 的 hi_vec 中,现在它将由 percpu 线程 ksoftirq 提供服务,所以肯定它只会在每次被调度时在同一个 CPU 上执行,现在如果对于其他 CPU 上的相同 ISR,我们使用该内核的 HI_VEC 列表引发相同的小任务。那么同一个小任务将在两个内核上执行。在两个的上下文中per-cpu 线程 ksoftirq/x 和 ksoftirqx1 ,现在据称一个小任务不能同时在两个核心上执行。这个说法是错误的,你建议什么?
    【解决方案2】:

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

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-23
      • 2021-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多