rps程序使用spinlock with local_irq_disable的原因

The reasons why rps procedure use spinlock with local_irq_disable

这几天在研究内核内网代码,尤其是RPS代码。你知道,有很多关于它的功能。但我关注的是一些关于 SMP 队列处理 的功能,例如 enqueue_to_backlogprocess_backlog

我想知道通过使用两个函数 -enqueue_to_backlogprocess_backlog-.

来同步两个内核(或单核)

在那个函数中,A core(A) 拥有另一个 core(B) 的 spin_lock,用于将数据包排队到 input_pkt_queue 并调度 core(B) 的 napi )。而A Core(B)还持有一个spin_lock,用于拼接input_pkt_queueprocess_queue的core(B),并自行去除napi schedule。我知道应该保持 spin_lock 以防止两个核心在处理队列时互相访问同一个队列。

但是我不明白为什么用local_irq_disable(或local_irq_save)调用spin_lock。我认为当中断(TH)抢占当前上下文(softirq,BH)时,中断上下文(TH)无法访问核心(B)的队列或rps_lock - 当然, TH 可以访问 napi 结构来调度 napi,但它会禁用 irq 直到排队数据包 - 所以我想知道为什么 spin_lock 被调用时带有 irq 禁用。

我觉得不可能被tasklet等其他BH抢占当前context(napi, softirq)。是真的吗?我想知道 local_irq_disable disable all cores irq or just current core's irq literally? 实际上,我读了一本关于内核开发的书,但我认为我对抢占的理解不够。

能否解释为什么rps程序使用spin_locklocal_irq_disable的原因?

禁用中断会影响当前核心(仅)。因此,当禁用时,同一核心 上的其他代码 将无法干扰对数据结构的更新。自旋锁的要点是将 "lock-out" 扩展到其他内核(尽管它是协作的,而不是硬件强制执行的)。

在内核中取自旋锁而不禁用中断是dangerous/irresponsible,因为当中断发生时,当前代码将被挂起,现在你正在阻止其他核心取得进展,而一些 无关 中断处理程序是 运行 (即使原始核心上的另一个用户进程或微任务将无法抢占)。其他内核本身可能处于中断或 BH 上下文中,现在您正在延迟整个系统。自旋锁应该保持很短的时间以对共享数据结构进行关键更新。

这也是产生死锁的好办法。考虑上面的场景是否在另一个子系统中复制(或者可能是同一子系统中的另一个设备,但我将描述前者)。

这里,内核 A 在子系统 1 中获取了一个自旋锁,没有禁用中断。同时,内核 B 在子系统 2 中也获取了一个自旋锁,而没有禁用中断。现在,如果与子系统 2 相关的中断发生在核心 A 上,并且在执行子系统 2 中断处理程序时,核心 A 需要更新受核心 B 中的自旋锁保护的结构。但大约在同一时间,子系统 1中断发生在核心 B 上,它需要更新该子系统中的数据结构。现在两个核心都在忙于等待另一个核心持有的自旋锁,并且整个系统被冻结,直到您进行硬重置。