线程 A 和 B 同时执行。哪些 ARMv8-A 内存屏障类型(如 DMB、DSB)足以满足后置条件,为什么?
Initially x1 = 0, x2 = 0
Thread A | Thread B
----------------------------------
x1 = 1 | x2 = 1
barrier | barrier
y1 = x2 | y2 = x1
Postcondition: (y1 == 1) || (y2 == 1)
我查看了 DMB 和 DSB 的 ARMv8-A 架构参考手册内存模型定义,但无法推断出为什么即使有 DSB 内存屏障,后置条件也会成立。我认为架构参考手册中的关键定义是:
DMB 指令确保执行 DMB 的 PE 在 DMB 之前按程序顺序显示的所有受影响的内存访问,以及那些源自不同 PE 的内存访问,这些访问在执行 DMB 之前由 PE 观察到,在 DMB 之后按程序顺序显示的任何受影响的内存访问之前,每个 PE 都会观察到该 PE
。
和
由 PE 执行的 DSB 在以下所有条件适用时完成:
对于
所需可共享性域中的观察器集,在 DSB 之前按程序顺序显示的所需访问类型的所有显式内存访问都是完整的。
[...]
和
此外,在DSB指令之后按程序顺序显示的任何指令都不能更改系统的任何状态或执行其功能的任何部分,直到DSB完成,而不是[...]
Unix蓝精灵写了一系列关于ARM内存障碍的文章。DSB
是DMB
的超集,换句话说,DSB
更具限制性。 该DMB
足以确保在使用普通内存更新y1
或y2
之前完成对x1
和x2
的写入。 也就是说,在大多数 ARM 系统上,它足以替代您示例中的屏障,DSB
也可以正常工作。
操作系统可以在 MMU 表中使用不同的属性,这可能会影响结果。 例如,使用图形RAM或某些网络设备缓冲区作为x1
,x2
的后备存储可能不需要发出dmb
,或者dmb
可能需要不同的参数,因为这些类型的内存可能放在不同的域中。
事实上,操作系统可能完全颠覆这些机制。 对于大多数用例来说,这不是一个因素,我只是说它是完整的。 也可能有 AMP(非对称多处理器)系统,这不起作用。 例如,如果您的系统带有ARMv8和Cortex-M。
参考:
- 在 ARM CPU 上 dsb、dmb 和 isb 的真实用例
- ARM屏障石蕊测试和食谱