为什么spin_lock_irqsave需要禁用多处理器上的抢占

时间:2014-11-30 05:22:23

标签: kernel spinlock preemption

只是好奇为什么spin_lock_irqsave在禁用本地中断后需要禁用抢占。

static inline unsigned long __raw_spin_lock_irqsave(raw_spinlock_t *lock)
{
    unsigned long flags;

    local_irq_save(flags);
    preempt_disable(); ===> can preemption happen with interrupt disabled?
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    ...
}

只有启用中断才能进行抢占,因此在禁用中断后不必担心抢占。

1 个答案:

答案 0 :(得分:0)

因为存在一些导致抢占的函数,除非显式禁用了抢占,而无论中断状态如何。假设是如果不允许抢占,它将被明确禁用,并且该功能也不会抢占。使用中断来禁止抢占会违反该假设。

一个这样的函数是cond_resched(),它在core.c(https://elixir.bootlin.com/linux/v5.9-rc5/source/kernel/sched/core.c#L6116)中调用_cond_resched()

它检查是否启用了抢占并调用调度程序。在内核中的许多地方都可以调用此函数,并且有可能意外触发其中之一,从而破坏了自旋锁保护的关键部分。

此外,禁用中断自旋锁意味着可以从中断处理程序访问关键部分。如果您不小心使用cond_resched()触发了抢占,一旦您的进程得到调度,将重新启用后向中断。如果发生试图获取锁的中断,则将导致死锁。