9

我在网上找到了几个地方,它们声明只要输入中断例程,就“必须”调用 CLREX,我不明白。CLREX状态的文档(添加编号以便于参考):

(1) 清除地址已请求独占访问的执行处理器的本地记录。

(2) 使用该CLREX指令将紧密耦合的独占访问监视器返回到其开放访问状态。这消除了对内存的虚拟存储的要求。

(3) 是否CLREX还清除执行处理器的全局记录,即某个地址已请求独占访问,这是实现定义的。

我在这里几乎什么都不懂。

我的印象是,按照文档中的示例编写一些内容足以保证原子性:

    MOV r1, #0x1                ; load the ‘lock taken’ value
try:                                                       <---\
    LDREX r0, [LockAddr]        ; load the lock value          |
    CMP r0, #0                  ; is the lock free?            |
    STREXEQ r0, r1, [LockAddr]  ; try and claim the lock       |
    CMPEQ r0, #0                ; did this succeed?            |
    BNE try                     ; no - try again   ------------/
    ....                        ; yes - we have the lock
  1. 为什么要清除“本地记录”?我认为LDREX/STREX足以保证从几个中断对地址的原子访问?即 ARM 的 GCC 使用LDREX/编译所有 C11 原子函数STREX,我看不到CLREX在任何地方被调用。

  2. 第二段指的是什么“虚拟商店的要求”?

  3. 全局记录和本地记录有什么区别?多核场景需要全局记录吗?

4

2 回答 2

11

分别提出(和解释)你的三个问题:

1. 为什么要清除访问记录?

当强制执行严格的代码嵌套时,例如在处理中断时,CLREX通常不需要。但是,在某些情况下它很重要。想象一下,您正在为抢占式操作系统内核编写上下文切换,它可以异步挂起正在运行的任务并恢复另一个任务。现在考虑以下病理情况,涉及两个具有相同优先级的任务(A 和 B)使用LDREX和操作相同的共享资源STREX

Task A      Task B
  ...
 LDREX
-------------------- context switch
             LDREX
             STREX   (succeeds)
              ...
             LDREX
-------------------- context switch
 STREX               (succeeds, and should not)
  ...

因此上下文切换必须发出 aCLREX来避免这种情况。

2. 避免了哪些“虚拟商店要求”?

如果没有CLREX指令,则有必要使用 aSTREX来放弃独占访问标志,这涉及内存事务,因此比您想要做的只是清除标志所需的速度要慢。

3. 是多核场景的“全球纪录”吗?

是的,如果您使用的是单核机器,那么只有一个记录,因为只有一个 CPU。

于 2018-07-04T08:59:05.870 回答
4

实际上,M7 上的异常/中断CLREX 不需要它,它似乎只是出于兼容性原因才包含在内。来自文档(版本 c)

如果异常发生在同步操作中的加载独占指令和匹配的存储独占指令之间,CLREX 可以与其他必须强制存储独占失败的 ARM Cortex 处理器兼容。在 Cortex-M 处理器中,本地独占访问监视器会在异常边界上自动清除,因此使用 CLREX 的异常处理程序是可选的。

因此,由于 Cortex-M 处理器在异常/中断进入/退出时清除了本地独占访问标志,这否定了CLREX.

关于你的第三个问题,正如其他人提到的,你认为全局记录用于多核场景是正确的。CLREX根据实现定义对本地/全局标志的影响,多核处理器上可能仍有用例。

我可以理解为什么会出现混淆,因为 M7 文档的初始版本不包含这些句子(更不用说 ARM 网站上更通用文档的各种其他版本)。即使是现在,我什至无法链接到最新版本。该页面默认显示“版本 a”,您必须通过下拉框手动更改版本(希望将来会更改)。

更新

作为对评论的回应,为此提供了一个额外的文档链接。这是手册的一部分,描述了这些说明在特定说明文档之外的用法(自第一次修订以来也一直存在):

如果出现以下情况,处理器将删除其独占访问标签:

  • 它执行 CLREX 指令。

  • 无论写入是否成功,它都会执行一条 STREX 指令。

  • 发生异常。这意味着处理器可以解决不同线程之间的信号量冲突。

在多处理器实现中:

  • 执行 CLREX 指令只会删除处理器的本地独占访问标记。

  • 执行 STREX 指令或异常会删除处理器的本地独占访问标记。

  • 对可共享内存区域执行 STREX 指令还可以删除系统中处理器的全局独占访问标签。

于 2019-01-21T16:52:02.907 回答