【问题标题】:Program counter, fences and processor re-ordering程序计数器、栅栏和处理器重新排序
【发布时间】:2021-09-15 09:59:14
【问题描述】:

我了解,除了编译器之外,处理器还可以对指令重新排序。

我有几个想不通的问题。

假设我们有三个指令:

节目顺序

S1 S2 S3

在处理器重新排序后,顺序变为(无论出于何种原因):

S3 S2 S1

  • 那么当处理器执行 S1(按程序顺序)时,程序计数器的值是多少?
  • 如果是 windows(或其他操作系统),上下文切换线程并将其调度到另一个处理器中,另一个处理器如何知道接下来要执行哪条指令? (是否保证重新订购相同的产品?)
  • 一个处理器上的内存栅栏(例如,由原子比较和交换指令创建的完整栅栏)在线程被调度到另一个线程后是否有效?

对此的任何想法都非常感谢。

【问题讨论】:

    标签: windows assembly x86-64 cpu-architecture memory-barriers


    【解决方案1】:

    与静态编译时排序不同,乱序 exec 保留了按照程序顺序运行指令的错觉。包括中断处理程序看到的情况。当前的 CPU 不会重命名特权级别,因此它们通常会回滚到一致状态作为处理异常或中断的一部分,而不是保持未执行的指令处于运行状态。 When an interrupt occurs, what happens to instructions in the pipeline?


    这也意味着中断是严格在指令之间传递的,而不是在一条指令的中间。 Interrupting an assembly instruction while it is operating(除了“可中断”指令,如 rep movsb 在逻辑上作为多条指令工作,或 vpgatherdd 在其中一个收集操作数中记录了页面错误的语义。)

    其他内核观察到的内存顺序是另一回事,即使在有序 CPU 上也可能与程序顺序不同。 (Can a speculatively executed CPU branch contain opcodes that access RAM?)

    上下文切换的内核代码需要包含足够强的屏障,以便线程在另一个内核上恢复时按程序顺序查看它自己的存储。通常只需发布/获取同步就足够了(并且您已经需要其他内核上的内核来恢复寄存器值)。也许还有一个sfence 以使其适用于 x86 上的 NT 商店。

    【讨论】:

      【解决方案2】:
      1. 每条指令都有一个指令指针。

      2. 虽然指令可能会乱序执行,但它们总是按顺序完成。当发生中断或故障时,保存的 IP 地址之前的所有指令都已完成。任何后续指令的结果都将被丢弃。继续执行时,会从保存的地址开始。

      3. 操作系统在另一个处理器上调度线程所采取的步骤包括两个处理器上的隔离操作,因此当线程在新处理器上恢复时,所有先前的操作都被完全隔离(无论代码中是否存在任何明确的隔离)线程)。

      【讨论】:

        猜你喜欢
        • 2017-12-13
        • 2016-10-10
        • 2012-11-06
        • 1970-01-01
        • 2017-06-25
        • 2021-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多