对于其他 CPU 上的观察者,没有什么能阻止这一点。你是对的, StoreLoad 的 store 部分的重新排序++
可以使它在你的一些加载后全局可见。
因此,我们可以得出结论,current->rcu_read_lock_nesting
只有在此内核上运行的代码才能观察到,或者通过在此处调度远程触发了此内核上的内存屏障,或者使用专用机制让所有内核在处理程序中执行屏障处理器间中断(IPI)。例如,类似于membarrier()
用户空间系统调用。
如果此内核开始运行另一个任务,则保证该任务按程序顺序查看此任务的操作。(因为它在同一个核心上,并且一个核心总是按顺序看到自己的操作。)此外,上下文切换可能涉及完整的内存屏障,因此可以在另一个核心上恢复任务而不会破坏单线程逻辑。(这将使任何核心在rcu_read_lock_nesting
此任务/线程未在任何地方运行时都可以安全地查看。)
请注意,内核会为您机器的每个内核启动一个 RCU 任务;例如,在我的 4c8t 四核上ps
输出显示[rcuc/0]
, [rcuc/1]
, ...。[rcu/7]
据推测,它们是这种设计的重要组成部分,让读者可以毫无障碍地等待。
我没有研究 RCU 的全部细节,但
https://www.kernel.org/doc/Documentation/RCU/whatisRCU.txtsynchronize_rcu()
中的“玩具”示例之一是实现 为的“经典 RCU” for_each_possible_cpu(cpu) run_on(cpu);
,以获取回收器在可能已经完成 RCU 操作的每个核心(即每个核心)上执行。一旦完成,我们就知道作为切换的一部分,那里一定发生了一个完整的内存屏障。
所以是的,RCU 不遵循经典方法,您需要一个完整的内存屏障(包括 StoreLoad)来使核心等到第一个存储可见后再进行任何读取。 RCU 避免了读取路径中的完整内存屏障的开销。 除了避免争用之外,这是它的主要吸引力之一。