2

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

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

4

1 回答 1

1

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

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

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

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

于 2020-09-17T13:50:46.510 回答