简体   繁体   English

在local_bh_disable()/ local_bh_enable()中使用rcu_dereference()是否安全?

[英]Is it safe to use rcu_dereference() inside local_bh_disable()/local_bh_enable()?

The local_bh_disable -function changes per-cpu (in case of x86 and recent kernels) __preempt_count or current_thread_info()->preempt_count otherwise. local_bh_disable -function更改per-cpu(如果是x86和最近的内核) __preempt_countcurrent_thread_info()->preempt_count否则。

Anyway that gives us a grace period, so we can assume that it will be redundant to do rcu_read_lock() inside local_bh_disable() . 无论如何,这给了我们宽限期,所以我们可以假设在local_bh_disable()执行rcu_read_lock()是多余的。 Indeed: in earlier kernels we can see that local_bh_disable() is used for RCU and rcu_dereference() is called subsequently inside eg the dev_queue_xmit -function. 确实: 在早期的内核中,我们可以看到 local_bh_disable()用于RCU, rcu_dereference()随后在例如dev_queue_xmit rcu_dereference()中被dev_queue_xmit Later local_bh_disable() was replaced with rcu_read_lock_bh() , which eventually became a little more complicated than just calling local_bh_disable() . 后来local_bh_disable()被替换为rcu_read_lock_bh() ,最终变得比调用local_bh_disable()更复杂一些。 Now it looks like this: 现在它看起来像这样:

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");
}

Also there are enough articles describing the RCU APIs. 此外,还有足够的文章描述了RCU API。 Here we can see: 在这里我们可以看到:

Do you need to treat NMI handlers, hardirq handlers, and code segments with preemption disabled (whether via preempt_disable(), local_irq_save(), local_bh_disable(), or some other mechanism) as if they were explicit RCU readers? 您是否需要处理NMI处理程序,hardirq处理程序和禁用抢占的代码段(无论是通过preempt_disable(),local_irq_save(),local_bh_disable()还是其他一些机制),就像它们是显式RCU读取器一样? If so, RCU-sched is the only choice that will work for you. 如果是这样,RCU-sched是唯一适合您的选择。

This tells us to use the RCU Sched API in such cases, so rcu_dereference_sched() should help. 这告诉我们在这种情况下使用RCU Sched API ,因此rcu_dereference_sched()应该有所帮助。 From this comprehensive table we can realise that rcu_dereference() should be used only inside rcu_read_lock / rcu_read_unlock -markers. 这个全面的表中我们可以发现rcu_dereference()只能在rcu_read_lock / rcu_read_unlock -markers中使用。

However, it is not sufficiently clear. 但是,它还不够清楚。 Can I use (in case of modern kernels) rcu_dereference() inside local_bh_disable / local_bh_enable -markers without misgiving of anything going wrong? 我可以在local_bh_disable / local_bh_enable -markers中使用(在现代内核的情况下) rcu_dereference()而不会出现任何错误吗?

PS In my case, I can't change the code calling local_bh_disable to call eg rcu_read_lock_bh , so my code is runnung with bh already disabled. PS在我的情况下,我无法更改调用local_bh_disable的代码来调用例如rcu_read_lock_bh ,所以我的代码运行已经禁用了bh。 Also the usual RCU API is used. 还使用通常的RCU API。 Thus, it is fraught with rcu_read_lock nested in local_bh_disable . 因此,它充满了嵌套在local_bh_disable rcu_read_lock

You are not supposed to mix-and-match APIs. 您不应该混合使用API​​。 If you need to use the RCU-bh API, you need to use rcu_dereference_bh . 如果需要使用RCU-bh API,则需要使用rcu_dereference_bh

You can see that if you called rcu_dereference_check after rcu_read_lock_bh , it would correctly surmise it is not called in a RCU read-side critical section ; 你可以看到,如果你在rcu_read_lock_bh之后调用了rcu_dereference_check ,它会正确推测它不会在RCU读取端关键部分调用 ; contrast the call to lock_is_held(&rcu_lock_map) with rcu_lock_acquire(&rcu_bh_lock_map); lock_is_held(&rcu_lock_map)的调用与lock_is_held(&rcu_lock_map)进行rcu_lock_acquire(&rcu_bh_lock_map); in your snippet above. 在上面的代码段中。

The kernel documentation for RCU here (search for the section on "rcu_dereference()") gives an explicit example of correct usage; 对于RCU内核文件在这里 (搜索的“rcu_dereference()”一节)给出了正确用法的一个明显的例子; rcu_dereference* can only be called correctly after the corresponding rcu_read_lock* function has completed. rcu_dereference*只能在相应的rcu_read_lock*函数完成后才能正确调用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM