【发布时间】:2018-05-20 18:35:23
【问题描述】:
鉴于 ARMv8 CPU 上的类似情况(尽管这可能也适用于许多其他人):
class abcxzy
{
// Pragma align to cacheline to ensure they exist on same line.
unit32_t atomic_data;
uint32_t data;
void foo()
{
volatile asm (
" ldr w0, [address of data]\n"
"# Do stuff with data in w0..."
" str w0, [address of data]\n"
"1: ldaxr w0, [address of atomic_data]\n"
" add w1, w0, #0x1\n"
" stxr w2,w1, [address of atomic_data]\n"
" cbnz w2, 1b\n"
);
}
}
在 Asm inline 上设置适当的 clobbers 等,以便 C 和 Asm 可以在彩虹小马和阳光的世界中愉快地共存。
在多 CPU 的情况下,同时运行这段代码,存储到 data 是否会导致原子加载/存储到 atomic_data 失败?根据我的阅读,ARM atomic 的东西在缓存行的基础上工作,但不清楚非原子存储是否会影响原子。我希望它不会(并假设它会......),但我希望看看是否有其他人可以证实这一点。
【问题讨论】:
-
原子和非原子操作都在缓存行的基础上工作。 C++ 内存模型允许同时修改不同地址的变量,即使它们在同一个缓存行中(这无论如何都很难说)。
-
@LWimsey 当使用
asm时,C++ 内存模型就消失了。例如,C++ 编译器可能会进行各种优化(例如,在一次 64 位访问中访问atomic_data和data或不使用“不必要的”原子指令)仍然导致它生成的代码符合 C++ 内存模型,但是在使用这个 asm 语句时会中断(或打破这个 asm 语句所做的假设)。 -
老实说,更担心
stxr是否会在此处返回1,因为硬件检测到有人修改了原子变量的缓存行,而不是实际的原子变量,因此导致虚假故障。如果是这样,那么在原子行上有许多其他变量的情况下,它可能会导致原子由于缓存行干预而永远无法“完成”的情况,因此导致永久锁试图以原子方式递增变量. -
如果 C++ 编译器还生成独占访问指令,这些指令访问同一高速缓存行并同时在其他 CPU 上并行运行,那么肯定会出现误报问题。由于这种争用,您似乎不太可能遇到一个线程永远无法获得锁或其他任何情况的情况,但最终由您来确保这一点。
-
您是在询问从不同 CPU 存储到
data是否会导致atomic_data的原子RMW 失败,或者关于从data >相同的 CPU?在第一种情况下,答案是肯定的,另一个线程写入同一个缓存行绝对会导致 RMW 失败。
标签: c++ multithreading assembly arm atomic