【问题标题】:Why is LOCK a full barrier on x86?为什么 LOCK 在 x86 上是一个完整的障碍?
【发布时间】:2020-06-05 12:37:02
【问题描述】:

为什么LOCK 前缀会在 x86 上造成完全障碍? (因此它会耗尽存储缓冲区并具有顺序一致性)

对于LOCK/read-modify-write 操作,不需要完整的屏障,对缓存行的独占访问似乎就足够了。是设计选择还是有其他限制?

【问题讨论】:

  • 简短回答:它既是加载又是存储(它们必须在全局操作顺序中原子地保持在一起),因此它不能在任一方向上重新排序。所以它最终拥有成为一个完整的障碍。
  • @PeterCordes 我虽然谈到了这一点,但它是一种先加载后存储,而且 x86 内存模型已经禁止 LoadStore 重新排序。还不够吗?
  • 是的,但请考虑一些示例,例如RMW 然后一个负载。 RMW 是否可以像普通商店一样延迟并在加载后出现?不,因为它会带来负载,那就是 LoadLoad 重新排序。
  • @PeterCordes 嗯,我明白了,所以在这种情况下,是为了防止其他负载在 RMW 负载和存储之间“潜行”吗? (会失去原子性)
  • 差不多。 AFAICT,acq_rel RMW 和 seq_cst RMW ISO C++ 之间的唯一区别是 acq_rel 不禁止 IRIW 重新排序(当加载部分观察到来自另一个核心的纯存储时),但 x86 的总存储顺序不允许这样做。虽然见 cmets:How do memory_order_seq_cst and memory_order_acq_rel differ?

标签: x86 cpu-architecture memory-barriers


【解决方案1】:

很久以前,在 Intel 80486 之前,Intel 处理器没有片上缓存或写入缓冲区。因此,根据设计,所有写入都立即按顺序在全球范围内可见,您不必从任何地方耗尽存储。通过完全锁定整个地址空间的总线来执行锁定事务。

在 486 和 Pentium 处理器中,已在片上添加写入缓冲区,并且某些型号还具有片上缓存。首先考虑没有片上缓存的模型。所有写操作都暂时保存在片上写缓冲区中,直到可用时将它们写到总线上或发生序列化事件。请记住,原子 RMW 事务用于获取对软件结构或硬件资源的独占访问权。因此,如果一个处理器执行了一个锁定的事务,它不应该发生处理器认为它获得了资源的所有权,但是另一个处理器也以某种方式最终也获得了所有权。如果锁定事务的写入部分在写入缓冲区中缓冲,然后释放总线锁,则没有什么可以阻止其他代理同时获取对资源的访问权限。本质上,写入部分必须对所有其他代理可见,而做到这一点的方法是不缓冲它。但是 x86 内存模型要求所有写入按顺序全局可见(这些处理器上没有弱排序)。因此,为了使锁定事务的写入部分全局可观察,所有缓冲的写入也必须以相同的顺序全局可观察。

部分 486 型号和所有奔腾处理器都具有片上缓存。但是在这些处理器上,不支持缓存锁。这就是为什么锁定的事务不能在这些处理器上缓存的原因,因为保证原子性的唯一方法是绕过缓存并锁定总线。获取总线锁后,根据目标内存区域的对齐方式和大小执行一次或多次写入。在释放总线锁之前,写缓冲区仍然必须被清空。

Pentium Pro 引入了一些重大变化,包括弱排序写入、写入组合缓冲区和缓存锁定。所谓的“写入缓冲区”通常在更现代的微架构上称为存储缓冲区。锁定的事务在这些处理器上使用缓存锁定,但是在将锁定的存储从存储缓冲区提交到缓存之前,无法释放缓存锁,这使得存储全局可观察,这必然需要使所有早期存储全局可观察。这些事件必须按此顺序发生。也就是说,我认为锁定事务不必序列化弱序写入,但英特尔已决定采用这种方式。可能是因为英特尔想要一个方便的指令,在没有专用存储栅栏的情况下耗尽 PPro 上的 WC 缓冲区。

【讨论】:

    猜你喜欢
    • 2011-05-13
    • 1970-01-01
    • 2015-03-06
    • 2013-01-17
    • 2015-02-13
    • 2017-08-20
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多