0

我正在研究内核代码(版本 3.10.1)的自旋锁代码,但没有理解一件事。

当通过该函数获取自旋锁时spin_lock_bh(),它会继续调用preempt_disable(). 这与用于获取的其他自旋锁函数相同,例如spin_lock()spin_lock_irq()

但是当通过 释放锁时spin_unlock_bh(),它会调用preempt_enable_no_resched(),它会跳过调用调度程序来抢占。对于其他相应的释放函数(如spin_unlock()spin_unlock_irq()),情况并非如此。他们调用调用的常规preempt_enable()函数__schedule()​​。

4

1 回答 1

2

local_bh_disable()将 counter增加preempt_count一个特定值,也preempt_disable()将其增加1. 就是__raw_spin_lock_bh()这样。

preempt_enable()函数(从__raw_spin_unlock()和调用__raw_spin_unlock_irq()调用preempt_check_resched()。但是,当抢占仍然被禁用时,无需尝试安排。它将_local_bh_enable_ip()在函数退出时在内部完成。

查看源代码可以看到真正的“BH”自旋锁调用序列是:

spin_release(&lock->dep_map, 1, _RET_IP_);
do_raw_spin_unlock(lock);
preempt_enable_no_resched();
    \____barrier();
    \____dec_preempt_count(); // <--- decrease counter, but we can't schedule here
local_bh_enable_ip();
    \____sub_preempt_count() // <--- real disabling preemption
    \____preempt_check_resched(); // <--- schedule

但是fe “IRQ”自旋锁调用序列:

spin_release(&lock->dep_map, 1, _RET_IP_);
do_raw_spin_unlock(lock);
local_irq_enable();
preempt_enable();
    \____barrier();
    \____dec_preempt_count(); // <--- real disabling preemption
    \____barrier();
    \____preempt_check_resched(); // <--- schedule

总结一下:在 BH-spinlock 的情况下,它只是绕过它,preempt_check_resched()因为它不是必需的。

于 2019-10-09T13:36:20.567 回答