繁体   English   中英

rcu_read_lock和x86-64内存顺序

[英]rcu_read_lock and x86-64 memory ordering

在可抢占式SMP内核上, rcu_read_lock编译以下内容:

current->rcu_read_lock_nesting++;
barrier();

barrier是一个编译器指令,可编译为空。

因此,根据英特尔的X86-64内存订购白皮书:

可能会将旧商店的货物重新排序到其他位置

为什么实施实际上可以?

请考虑以下情况:

rcu_read_lock();
read_non_atomic_stuff();
rcu_read_unlock();

是什么阻止read_non_atomic_stuff从“ rcu_read_lock ”向前“泄漏”,导致它与在另一个线程中运行的回收代码同时运行?

对于其他CPU上的观察者,没有什么可以阻止这一点。 没错, ++商店部分的StoreLoad重新排序可以使它在某些加载后在全局可见。

因此,我们可以得出结论,只有当前在此内核上运行的代码才会观察到current->rcu_read_lock_nesting或者通过在此处调度而远程触发了该内核上的内存屏障,或者使用了一种专用机制来使所有内核在该内核中执行屏障。处理器间中断(IPI)的处理程序。 例如,类似于membarrier()用户空间系统调用。


如果此核心开始运行另一个任务,则可以确保该任务按程序顺序查看此任务的操作。 (因为它在同一个内核上,并且一个内核总是按顺序查看其自身的操作。)而且,上下文切换可能涉及完整的内存屏障,因此可以在不破坏单线程逻辑的情况下在另一个内核上恢复任务。 (这可以使任何内核在此任务/线程不在任何地方运行时安全地查看rcu_read_lock_nesting 。)

请注意,内核在您的计算机的每个内核上启动一个RCU任务 例如, ps输出在我的4c8t四核上显示[rcuc/0][rcuc/1] ,..., [rcu/7] 大概它们是该设计的重要组成部分,它使读者可以毫无障碍地等待。

我还没有研究RCU的全部细节,但是https://www.kernel.org/doc/Documentation/RCU/whatisRCU.txt中的“玩具”示例之一是实现了synchronize_rcu() “经典RCU” for_each_possible_cpu(cpu) run_on(cpu); ,以使回收器在可能已执行RCU操作的每个内核(即每个内核)上执行。 完成此操作后,我们知道在切换过程中某个地方一定已经发生了内存不足的情况。

因此,是的,RCU并没有遵循经典的方法,在这种方法中,您需要一个完整的内存屏障(包括StoreLoad)来使核心等待直到第一个存储区可见之后才能进行任何读取。 RCU避免了读取路径中完整内存屏障的开销。 除了避免争用外,这是它的主要吸引力之一。

暂无
暂无

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

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