spin_unlock_bh函数为什么不用调用调度器就可以抢占
Why does spin_unlock_bh function enables preemption without calling the scheduler
我正在查看内核代码(版本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()
)并非如此。他们调用调用 __schedule()
.
的常规 preempt_enable()
函数
local_bh_disable()
将 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()
内完成。
查看 source code you can see that the real "BH" spinlock 调用顺序是:
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
但是f.e。 "IRQ" spinlock调用顺序:
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()
因为它不需要。
我正在查看内核代码(版本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()
)并非如此。他们调用调用 __schedule()
.
preempt_enable()
函数
local_bh_disable()
将 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()
内完成。
查看 source code you can see that the real "BH" spinlock 调用顺序是:
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
但是f.e。 "IRQ" spinlock调用顺序:
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()
因为它不需要。