锁定 Per CPU 变量
Locking on Per CPU variable
我正在阅读 Robert Love 的 Linux 内核开发,并试图了解内核同步机制。我试图理解书中提到的与锁定机制相关的一些要点如下-
"有些情况不需要自旋锁,但确实需要内核抢占 disabled.The 这些情况中最常见的是每个处理器的数据。如果每个处理器的数据都是唯一的,则可能不需要用锁来保护它,因为只有那个处理器可以访问数据。如果没有持有自旋锁,内核是抢先的,新调度的任务可能会访问这个相同的变量。
因此,即使这是一台单处理器计算机,该变量也可以被多个进程伪并发访问。通常,这个变量需要一个自旋锁(以防止多处理机器上的真正并发)。但是,如果这是每个处理器变量,它可能不需要 lock.To 解决这个问题,可以通过 preempt_disable()"
禁用内核抢占
所以在这里考虑多处理器系统 -
我知道虽然当前进程正在操作 per-cpu 变量,但由于 SMP 可能会安排另一个进程并尝试操作相同的 per-cpu 变量因此需要禁用抢占书中有解释。但是我无法理解的一点是,如果我们只禁用内核抢占并且当前进程正在尝试操作 per-cpu 数据并且同时在当前处理器上发生中断并且由于中断没有被禁用,CPU 停止当前任务并开始执行中断处理程序,现在这个处理程序也想操作相同的 per-cpu 变量。那么在这种情况下,变量可能最终包含不一致的数据?
那么这是否意味着如果还从中断处理程序访问 per-cpu 变量,则还需要在当前处理器上禁用中断?
平台:Linux x86
So considering a multiprocessor system here - I understand that while
per-cpu variable is being manipulated by the current process, another
process may be scheduled due to SMP and try to manipulate the same
per-cpu variable hence the preemption needs to be disabled as
explained in the book.
我认为 SMP 在这里没有发挥任何作用,因为变量是每个 cpu(不在处理器之间共享)。另一个进程可能会被调度,因为调度程序中断会来,这与 SMP 无关,也可能发生在单处理器系统上。为了避免这种抢占禁用。对于 CONFIG_PREEMPT_ENABLE linux kernel says spinlock/unlock = preemp disable/enable
的单处理器系统
So does that mean that the interrupt also needs to be disabled on the
current processor if the per-cpu variable is also accessed from
interrupt handler ?
是的!对于单处理器系统也是如此。在这种情况下,您应该使用 irqsave API(或等效项):
spin_lock_irqsave(&xxx_lock, flags);
... critical section here ..
spin_unlock_irqrestore(&xxx_lock, flags);
对于单处理器内核,此自旋锁将变成本地 irq enable/disabling。在 SMP 系统中,自旋锁是通过 cmpxchg + irq disabling/enabling.
实现的实际自旋锁
对于多处理器系统和保护每个cpu变量,我们可以只禁用抢占并执行local_irq_save。这样我们就避免了使用自旋锁。自旋锁需要跨多个 CPU 的原子性。对于每个 cpu 个变量,不需要它。
local_irq_save(flags);
preempt_disable();
-- Modify the percpu variable
preempt_enable();
local_irq_restore(flags);
使用此代码,其他 CPU 可以并行工作。 None 次 CPU 次旋转。
如果我们采用自旋锁,那么我们修改一个原子变量,其他 CPU 出现,那么它必须 wait/spin 如果获得自旋锁。
我正在阅读 Robert Love 的 Linux 内核开发,并试图了解内核同步机制。我试图理解书中提到的与锁定机制相关的一些要点如下-
"有些情况不需要自旋锁,但确实需要内核抢占 disabled.The 这些情况中最常见的是每个处理器的数据。如果每个处理器的数据都是唯一的,则可能不需要用锁来保护它,因为只有那个处理器可以访问数据。如果没有持有自旋锁,内核是抢先的,新调度的任务可能会访问这个相同的变量。
因此,即使这是一台单处理器计算机,该变量也可以被多个进程伪并发访问。通常,这个变量需要一个自旋锁(以防止多处理机器上的真正并发)。但是,如果这是每个处理器变量,它可能不需要 lock.To 解决这个问题,可以通过 preempt_disable()"
禁用内核抢占所以在这里考虑多处理器系统 - 我知道虽然当前进程正在操作 per-cpu 变量,但由于 SMP 可能会安排另一个进程并尝试操作相同的 per-cpu 变量因此需要禁用抢占书中有解释。但是我无法理解的一点是,如果我们只禁用内核抢占并且当前进程正在尝试操作 per-cpu 数据并且同时在当前处理器上发生中断并且由于中断没有被禁用,CPU 停止当前任务并开始执行中断处理程序,现在这个处理程序也想操作相同的 per-cpu 变量。那么在这种情况下,变量可能最终包含不一致的数据?
那么这是否意味着如果还从中断处理程序访问 per-cpu 变量,则还需要在当前处理器上禁用中断?
平台:Linux x86
So considering a multiprocessor system here - I understand that while per-cpu variable is being manipulated by the current process, another process may be scheduled due to SMP and try to manipulate the same per-cpu variable hence the preemption needs to be disabled as explained in the book.
我认为 SMP 在这里没有发挥任何作用,因为变量是每个 cpu(不在处理器之间共享)。另一个进程可能会被调度,因为调度程序中断会来,这与 SMP 无关,也可能发生在单处理器系统上。为了避免这种抢占禁用。对于 CONFIG_PREEMPT_ENABLE linux kernel says spinlock/unlock = preemp disable/enable
的单处理器系统So does that mean that the interrupt also needs to be disabled on the current processor if the per-cpu variable is also accessed from interrupt handler ?
是的!对于单处理器系统也是如此。在这种情况下,您应该使用 irqsave API(或等效项):
spin_lock_irqsave(&xxx_lock, flags);
... critical section here ..
spin_unlock_irqrestore(&xxx_lock, flags);
对于单处理器内核,此自旋锁将变成本地 irq enable/disabling。在 SMP 系统中,自旋锁是通过 cmpxchg + irq disabling/enabling.
实现的实际自旋锁对于多处理器系统和保护每个cpu变量,我们可以只禁用抢占并执行local_irq_save。这样我们就避免了使用自旋锁。自旋锁需要跨多个 CPU 的原子性。对于每个 cpu 个变量,不需要它。
local_irq_save(flags);
preempt_disable();
-- Modify the percpu variable
preempt_enable();
local_irq_restore(flags);
使用此代码,其他 CPU 可以并行工作。 None 次 CPU 次旋转。
如果我们采用自旋锁,那么我们修改一个原子变量,其他 CPU 出现,那么它必须 wait/spin 如果获得自旋锁。