12

Linux内核中的原始代码是:

static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)
{
    local_irq_disable();
    preempt_disable();
    spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);
    LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}

我认为禁用本地 IRQ 后没有执行路径可以抢占当前路径。

因为所有常见的硬 IRQ 都被禁用,所以应该不会发生软中断,也不会出现启动调度轮的滴答声。我认为目前的道路是安全的。那么为什么会有一个preempt_disable()

4

2 回答 2

8

据我所知,preempt_disable()调用被添加到相当多的锁定原语中,包括spin_lock_irqDave Miller 在 2002 年 12 月 4 日,并在 2.5.51 中发布。提交消息没有帮助;它只是说“[SPINLOCK]:修复非 SMP nopping spin/rwlock 宏。”

我相信Proper Locking Under a Preemptible Kernel文档很好地解释了这一点。标题为“使用中断禁用防止抢占”的最后一节开始,

It is possible to prevent a preemption event using local_irq_disable and
local_irq_save.  Note, when doing so, you must be very careful ...
于 2012-11-07T06:10:52.343 回答
5

我浏览了 Sharp 提到的补丁,发现禁用 irq 可以隐式禁用抢占,但有风险。

但是,请记住,依赖 irq 被禁用是一项有风险的业务。任何将抢占计数减少到 0 的 spin_unlock() 都可以触发重新调度。即使是简单的 printk() 也可能触发这样的重新安排。因此,仅当您知道此类事情不会在您的代码路径中发生时,才依赖隐式抢占禁用。最好的策略是仅在短时间内且仅在您保留在自己的代码中时才依赖隐式抢占禁用。

于 2015-11-26T01:02:02.540 回答