【发布时间】:2021-01-07 18:40:15
【问题描述】:
ARM 提供 LDREX/STREX 来自动加载/存储值,但我觉得我在这仍然是一个原子操作方面遗漏了一些东西。以下通常是如何增加一。但是,是什么阻止了某些东西在 ADD 指令期间抢占,从而使 r2 不再匹配存储在 [r0] 中的内容?
(Assuming r0 is valid and r1 = 1)
ADD
LDREX r2, [r0]
ADDS r2, r2, #1
STREXNE r2, r1, [r0] @ Store 1 if the original [r0] was not -1
CMPNE r2, #1
BEQ ADD
【问题讨论】:
-
当操作被抢占时,代码表现得好像从未发生过一样,
r2设置为 0 表示这种情况。然后代码可以重试。 -
fuz:或者至少,就好像商店从未发生过一样。 AFAIK,中间的其他指令不会回滚。
-
应该是
ADDS而不是ADD,这样你就只在[r0]中的值以前是-1时才进行存储?否则我不清楚条件应该完成什么。正如代码所示,您无条件存储1,而不是[r0]的增量值;STREXNE的操作数可能会颠倒,在这种情况下,CMPNE可能希望使用r1而不是r2。 -
@Maxthecat:我明白了。正如 old_timer 指出的那样,在这种情况下发生的情况是原始线程根本 不 存储。
STREX指令检测到其他人同时写入了该地址,而不是执行存储它返回失败,导致循环重复并加载新值 101。这正是*EX指令提供的额外功能超过常规加载/存储。 -
@Nate:我认为中断处理程序还必须清除“监视器”(CLREX 或虚拟 strex,除非在某些 Cortex-M CPU 上会在中断时自动发生),否则如果您上下文从一个线程中的 LDREX 切换到另一个线程中的 STREX,在不按地址监视的 CPU 上可能会出现误报(“成功的”strex)。见When is CLREX actually needed on ARM Cortex M7?。但是对于表现良好的操作系统,是的,Atomic operations in ARM 适用:STREX 确保跨线程的排他性。
标签: assembly arm atomic cpu-architecture load-link-store-conditional