[英]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_count
或current_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.