在英特尔,CMPXCHG的参数必须与高速缓存行对齐(因为英特尔使用MESI来实现CAS)。
在ARM上,ldrex和strex运行独家预订granuales。
要明确的是,这是否意味着在ARM上运行的数据不必是高速缓存行对齐的?
答案 0 :(得分:2)
独家访问限制
以下限制适用于独占访问:
•具有给定ID的独占写入的大小和长度必须与 具有相同ID的前一次独占读取的大小和长度。
•独占访问的地址必须与总字节数对齐 在交易中。
•独占读取和独占写入的地址必须相同。
•独占访问的读取部分的ARID字段必须与AWID匹配 写部分。
•独占访问的读写部分的控制信号必须是 相同。
•独占访问突发中要传输的字节数必须是电源 2,即1,2,4,8,16,32,64或128字节。
•独占突发中可以传输的最大字节数是 128。
•必须保证ARCACHE [3:0]或AWCACHE [3:0]信号的值 监视独占访问的从属设备会看到该事务。对于 例如,由从属设备监控的独占访问不得具有 ARCACHE [3:0]或AWCACHE [3:0]值表示事务是 缓存。
未遵守这些限制会导致不可预测的行为。
以上内容来自AMBA / AXI规范。您会发现某些供应商忽略了AWLOCK / ARLOCK(意味着ldrex / strex不会在核心之外工作)。我有一些代码可以证明这一点,或者至少会找到一个不支持独占访问的系统。
https://github.com/dwelch67/raspberrypi/tree/master/extest
根据任务和您想要的可移植性,您可能需要提供由ifdefs包围的swp和ldrex / strex解决方案和/或使用过多的可用寄存器(运行时)来告诉您哪些指令是否受支持通过你正在运行的核心。 (你可能会发现至少有一个案例既不支持swp也不支持ldrex / strex。)
答案 1 :(得分:1)
它在ARM体系结构参考手册A.3.2.1“未对齐的数据访问”中说得很对。 LDREX
和STREX
需要字对齐。这是有道理的,因为未对齐的数据访问可以跨越独占的预留颗粒。
答案 2 :(得分:1)
在Intel上,CMPXCHG的参数不需要缓存对齐。尝试一下,你会发现它有效。
但是,你是对的:在可缓存的内存中,英特尔确实使用缓存协议来实现CMPXCHG。因此,如果不将两个独立的高使用率同步变量放在同一个缓存行中,您会很聪明 - 因为如果两个处理器使用这些不同的变量进行同步,则缓存行可能会来回颠簸。但这与任何数据完全相同:您没有不同的处理器同时写入同一个高速缓存行。虚假分享。
但你当然不能缓存行对齐锁:
struct Foo {
int data;
Lock lock;
int data_after;
};
您可以在同一个缓存行中放置不同的锁:
struct Foo {
int data;
Lock read_lock;
int data_between;
Lock write_lock;
int data_after;
};
由于读写往往是相互排斥的,因此可能没有损失;
您可以在同一个缓存行中放置不同的锁:
struct Foo {
int data;
Lock read_lock;
int data_between;
Lock write_lock;
int data_after;
};
顺便说一句,在未缓存的内存中,英特尔不会将缓存侦听协议用于像CMPXCHG这样的原子操作。因此,缓存行对齐同步变量的理由较少。但是你仍然可能想要:许多内存子系统按照缓存行大小进行交错,即使在未缓存时也是如此。
至于ARM:它几乎是一样的。
在窥探总线上或未缓存的情况下,您可能不需要过多担心缓存行对齐。
但是在群集缓存层次结构中,您遇到与x86完全相同的问题。事实上,众所周知,如何“导出”像CMPXCHG这样的操作,而不是ARM ldrexd / strexd。