4

-functionlocal_bh_disable改变每个 cpu(在 x86 和最近的内核的情况下)__preempt_countcurrent_thread_info()->preempt_count其他。

无论如何,这给了我们一个宽限期,所以我们可以假设在rcu_read_lock()里面做是多余的local_bh_disable()。确实:在早期的内核中,我们可以看到local_bh_disable()用于 RCU,rcu_dereference()随后在例如dev_queue_xmit-function 内部被调用。后来local_bh_disable()被替换为rcu_read_lock_bh(),最终变得比调用更复杂一些local_bh_disable()。现在看起来像这样:

static inline void rcu_read_lock_bh(void)
{
   local_bh_disable();
   __acquire(RCU_BH);
   rcu_lock_acquire(&rcu_bh_lock_map);
   RCU_LOCKDEP_WARN(!rcu_is_watching(),"rcu_read_lock_bh() used illegally while idle");
}

还有足够多的文章描述 RCU API。在这里我们可以看到:

您是否需要将 NMI 处理程序、hardirq 处理程序和禁用抢占的代码段(无论是通过 preempt_disable()、local_irq_save()、local_bh_disable() 还是其他机制)视为显式 RCU 读取器?如果是这样,RCU-sched 是唯一适合您的选择。

这告诉我们在这种情况下使用RCU Sched API,所以rcu_dereference_sched()应该有所帮助。从这个综合表中我们可以意识到rcu_dereference()应该只在rcu_read_lock/ rcu_read_unlock-markers 内部使用。

但是,还不够清楚。我可以在/ -markersrcu_dereference()内部使用(在现代内核的情况下)而不担心会出现任何问题吗?local_bh_disablelocal_bh_enable

PS 在我的情况下,我无法更改local_bh_disable调用 eg的代码rcu_read_lock_bh,因此我的代码在 bh 已禁用的情况下运行。还使用了通常的 RCU API。因此,它充满了rcu_read_lock嵌套在local_bh_disable.

4

1 回答 1

3

您不应该混合搭配 API。如果需要使用 RCU-bh API,则需要使用rcu_dereference_bh.

您可以看到,如果您rcu_dereference_check在之后调用rcu_read_lock_bh,它会正确地推测它没有在 RCU 读取端临界区中调用lock_is_held(&rcu_lock_map)将调用与上面代码段中的调用进行对比rcu_lock_acquire(&rcu_bh_lock_map);

此处RCU 的内核文档(搜索“rcu_dereference()”部分)给出了正确使用的明确示例;只有在对应的函数完成rcu_dereference*后才能正确调用。rcu_read_lock*

于 2018-07-09T11:02:15.907 回答