1

众所周知,在 INTEL X86 架构中访问对齐的基本数据类型是原子的。ARMV8怎么样?我尝试从Arm Architecture Reference Manual Armv8中得到结果,对于A-profile架构,我确实找到了一些与原子性有关的东西。ARMV8 是其他多拷贝原子的。它承诺多线程访问同一个 LOCATION 是原子的。但它说 LOCATION 是一个字节。我想知道如果线程 1 在没有锁定的情况下写入对齐的 uint64_t 内存,而线程 2 同时在没有锁定的情况下读取或写入它。它是原子的吗?(uint64_t 是 8 个字节,但 LOCATION 只有一个字节)

4

1 回答 1

0

这在 ARMv8 架构参考手册的 B2.2 中有说明。通常,最多 64 位的普通加载和存储(如果自然对齐)是单副本原子的。特别是,如果一个线程存储到一个地址而另一个线程加载相同的地址,则可以保证加载看到旧值或新值,而不会出现撕裂或其他未定义的行为。这大致类似于relaxedC 或 C++ 中的加载或存储。实际上,您可以看到编译器会为此类原子访问发出普通的加载和存储指令。https://godbolt.org/z/cWjaed9rM


让我们举个例子来证明这一点。为简单起见,让我们使用对齐的 2 字节半字 H,将其称为字节 H0 和 H1。假设在遥远的过去,H被存储指令Wi初始化为0x0000;对字节 H0 和 H1 的相应写入将表示为 Wi.0 和 Wi.1。现在让新的存储指令 Wn = {Wn.0,Wn.1} 存储值 0xFFFF,并让它与加载指令 R = {R.0,R.1} 竞争。根据B2.2.1,前两个项目符号,每个访问 Wi、Wn、R 都是单拷贝原子。我们希望证明 R.0、R.1 都返回 0x00,否则它们都返回 0xFF。

B2.3.2中,存在将每次读取与一些写入配对的读取关系。R.0 必须Wi.0 或 Wn.0 读取,因为这是对 H0 的仅有的两次写入,因此它必须返回 0x00 或 0xFF。同样,R.1 也必须返回 0x00 或 0xFF。如果它们都返回 0x00,我们就完成了,所以假设其中一个,比如 R.1,返回 0xFF,让我们证明 R.0 也返回 0xFF。

我们假设 R.1Wn.1 读取。根据B2.2.2 (2) ,在B2.3.2的意义上,在 R 生成的相应重叠读取之后,由 Wn 生成的重叠写入都不是连贯的。特别是,Wn.0在 R.0之后不是连贯的

请注意,Wn.0 是 Wi.0之后的一致性(一致性顺序是写入的总顺序,因此必须一个接一个,并且我们假设 Wi 发生在很久以前,两者之间有足够的排序或同步)。因此,如果 R.0Wi.0 中读取,则 Wn.0 在 R.0 之后是连贯的(coherence-after定义,第二句)。我们只是认为情况并非如此,因此 R.0 不会Wi.0 读取;它必须Wn.0 读取,因此返回 0xFF。∎</p>


请注意,在 x86 上,普通的加载和存储分别隐式地带有获取和释放顺序,而在 ARM64 上并非如此。你必须使用ldar / stlr它。

于 2021-12-12T18:31:33.853 回答