
[英]How does the x86 TSO memory consistency model work when some of the stores being observed come from store-forwarding?
[英]Why cannot the load part of the atomic RMW instruction pass the earlier store to unrelated location in TSO(x86) memory consistency model?
众所周知,由于使用了写缓冲区,x86 架构没有实现顺序一致性内存模型,因此可以进行 store->load 重新排序(可以提交稍后的加载,而较早的存储仍然驻留在写缓冲区中等待提交) L1缓存)。
在A Primer on Memory Consistency and Coherence 中,我们可以了解 Total Store Order(TSO) 内存一致性模型中的 Read-Modify-Write(RMW) 操作(应该与 x86 非常相似):
...我们将 RMW 视为紧随其后的负载。 由于 TSO 的排序规则,RMW 的负载部分无法通过较早的负载。 乍一看,RMW 的加载部分可能会传递写入缓冲区中较早的存储,但这是不合法的。 如果 RMW 的加载部分通过较早的存储,则 RMW 的存储部分也必须通过较早的存储,因为 RMW 是原子对。 但是由于TSO中不允许存储相互传递,因此RMW的负载部分也不能通过较早的存储。
好的,原子操作必须是原子的,即RMW访问的内存位置在RMW操作期间不能被其他线程/内核访问,但是如果较早的存储通过原子操作的加载部分,则与RMW 访问的内存位置? 假设我们有以下几条指令(伪代码):
store int32 value in 0x00000000 location
atomic increment int32 value in 0x10000000 location
第一个存储被添加到写缓冲区并等待轮到它。 同时,原子操作从另一个位置(甚至在另一个缓存行中)加载值,传递第一个存储,然后将存储添加到第一个之后的写入缓冲区中。 在全局内存顺序中,我们将看到以下顺序:
加载(原子的一部分)-> 存储(序数)-> 存储(原子的一部分)
是的,从性能的角度来看,这可能不是最好的解决方案,因为我们需要将原子操作的缓存行保持在读写状态,直到写入缓冲区中的所有先前存储都被提交,但是,抛开性能考虑,是是否存在违反 TSO 内存一致性模型的情况,我们是否允许 RMW 操作的加载部分将较早的存储传递到不相关的位置?
您可以针对不同地址的任何存储 + 加载对提出相同的问题:由于乱序执行,加载可能比旧存储更早在内部执行。 在 X86 中这是允许的,因为:
可以将旧商店重新排序到不同位置,但不能将旧商店重新排序到同一位置
(来源: 英特尔 64 位架构内存订购白皮书)
但是,在您的示例中,锁定前缀会阻止这种情况,因为(来自同一组规则):
锁定指令有一个总顺序
这意味着锁会强制一个内存屏障,就像一个 mfence(实际上一些编译器使用一个锁定的操作作为一个栅栏)。 这通常会使 CPU 停止执行加载,直到存储缓冲区耗尽,从而迫使存储首先执行。
因为我们需要将原子操作的缓存行保持在读写状态,直到提交缓冲区中的所有前面的存储,但是,抛开性能考虑
如果您在执行与 L 阻止的操作具有相同性质的操作 S 时持有锁 L,即存在可以被 L 阻塞(延迟)并且 S 可以被 L' 阻塞(延迟)的操作,那么你有死锁的秘诀,除非你被保证是唯一这样做的演员(这会使整个原子的事情变得毫无意义)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.