gpt4 book ai didi

linux-kernel - 延迟工作的 CPU 处理

转载 作者:行者123 更新时间:2023-12-04 04:44:56 25 4
gpt4 key购买 nike

嘿,所以我正在查看 kernel source code 中的此功能.我试图弄清楚 Linux 如何处理无法在本地 CPU 上安排任务的情况。

/**
* queue_delayed_work - queue work on a workqueue after delay
* @wq: workqueue to use
* @dwork: delayable work to queue
* @delay: number of jiffies to wait before queueing
*
* Equivalent to queue_delayed_work_on() but tries to use the local CPU.
*/
static inline bool queue_delayed_work(struct workqueue_struct *wq,
struct delayed_work *dwork,
unsigned long delay)
{
return queue_delayed_work_on(WORK_CPU_UNBOUND, wq, dwork, delay);
}

这里是 queue_delayed_work_on :
bool queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
struct delayed_work *dwork, unsigned long delay)
{
struct work_struct *work = &dwork->work;
bool ret = false;
unsigned long flags;

/* read the comment in __queue_work() */
local_irq_save(flags);

if (!test_and_set_bit(WORK_STRUCT_PENDING_BIT, work_data_bits(work))) {
__queue_delayed_work(cpu, wq, dwork, delay);
ret = true;
}

local_irq_restore(flags);
return ret;
}

假设您有 4 个 CPU,但它无法在 CPU 1 上安排任务,它会选择哪一个,以及在源代码中的哪个位置处理?我已经找了一段时间了,找不到。即使你不明白它是如何工作的,我也会非常感谢一个链接到魔法发生的地方。

最佳答案

如您所见,queue_delayed_work将设置 cpu WORK_CPU_UNBOUND 的参数.该值被定义为大于内核支持的实际 CPU 数量。这个值被传递给 __queue_delayed_work如果 delay非零,将使用计时器(使用 add_timer 函数在指定时间后触发回调函数 delayed_work_timer_fn(此回调函数在工作队列初始化时定义)。此回调函数所做的只是调用 __queue_work ,仍然通过WORK_CPU_UNBOUND 作为 cpu 论点。所以整个“魔法”正在那里发生。

此函数将检查 cpu参数设置为 WORK_CPU_UNBOUND并选择 cpu 作为当前处理器:

if (req_cpu == WORK_CPU_UNBOUND)
cpu = raw_smp_processor_id()

所以工作将在处理之前设置的定时器中断的处理器上执行。现在我没有研究定时器代码,而是 LDD3 书中的 IIRC,定时器中断将由它们注册的 CPU 处理(当然,除非同时禁用这个 CPU,在这种情况下定时器 IRQ 将被移动到其他 CPU)但是那本书很旧,这可能不再是真的了。

内核代码中还有另一个提示可以证明我写的内容 - 请参阅 queue_work 的评论函数说:“我们将工作排队到提交它的 CPU,但如果 CPU 死了,它可以由另一个 CPU 处理”。此函数还使用 WORK_CPU_UNBOUND作为 cpu 参数。

计时器迁移详细信息

如前所述,如果某个处理器出现故障,它就无法再处理 IRQ,因此它无法处理它已注册的计时器。因此,当 CPU 离线时,内核会将所有挂起的计时器迁移到其他 CPU。此任务由 migrate_timers() 完成由 timer_cpu_notify 运行的函数这又是一个注册为 cpu_notifier 的回调。 .
migrate_timers当 cpu 状态更改为 CPU_DEAD 时运行或 CPU_DEAD_FROZEN .此状态设置在 _cpu_down 内部通过调用函数:
cpu_notify_nofail(CPU_DEAD | mod, hcpu);

它在 __cpu_die(cpu) 之后调用这确保了我们禁用的 CPU 不再工作,因此我们可以确保此代码在其他一些 CPU 上运行。 migrate_timers会将所有计时器重新分配给其运行的 CPU。

那么应该在哪里决定哪个 CPU 应该接管计时器呢?可以说它是由调度程序完成的:
  • 如果您调用cpu_down在与您要禁用的 CPU 不同的 CPU 上,那么这就是将接管的 CPU。
  • 如果您调用cpu_down在将被禁用的 CPU 上,它将在 __cpu_die 中自行调度然后其余代码将在其他 CPU 上重新调度。
  • 关于linux-kernel - 延迟工作的 CPU 处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31601216/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com