【问题标题】:why spin_lock_irqsave needs to disable preemption on multiprocessor为什么 spin_lock_irqsave 需要在多处理器上禁用抢占
【发布时间】:2014-11-30 05:22:22
【问题描述】:

只是好奇为什么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_);
    ...
}

只有在启用中断的情况下才能进行抢占,因此无需担心禁用中断后的抢占。

【问题讨论】:

  • 来自 Documentation/preempt-locking.txt:但请记住,“irqs disabled”是一种从根本上不安全的禁用抢占方式 - 任何将抢占计数减少到 0 的 spin_unlock() 都可能触发重新调度。一个简单的 printk() 可能会触发重新安排。因此,仅当您知道受影响的代码路径不执行任何此操作时,才使用此隐式抢占禁用属性。最好的策略是仅将其用于您编写且不调用复杂函数的小型原子代码。

标签: kernel spinlock preemption


【解决方案1】:

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

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

它检查是否启用了抢占并调用调度程序。这个函数是从内核中的许多地方调用的,可能会意外触发其中一个,从而破坏您的自旋锁保护的临界区。

此外,中断禁用自旋锁意味着可以从中断处理程序访问您的临界区。如果你不小心使用 cond_resched() 触发了抢占,一旦你的进程被安排回来,中断将被重新启用。如果发生试图获取锁的中断,就会出现死锁。

【讨论】:

    猜你喜欢
    • 2016-08-07
    • 1970-01-01
    • 2014-01-13
    • 2016-02-25
    • 2010-10-23
    • 2013-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多