在X86处理器上是否可能进行原子加载和存储操作?

4
这能够以原子方式完成吗?
void load_and_store(int* dst, int* src) {
  int data = *src;
  *dst = data;
}

如果必须使用XCHG [addr], EAX进行原子存储,则必须先将数据加载到EAX中。然后,加载和存储就不是原子操作了。
gcc原子扩展具有void __atomic_store (type *ptr, type *val, int memmodel),看起来能够同时原子地执行加载和存储。

这与 *dst = *src; 有什么不同吗? - Mark B
*dst = *src 不是原子操作。 - woodings
@MarkB,也许我的问题有点令人困惑。我想知道是否有一种CPU指令,可以以原子方式执行C++函数中的相同操作。 - woodings
看过 CompareAndSwap() 吗? - brian beuning
1个回答

7
我不相信x86有任何一条指令可以同时对不同地址进行原子性的读取和存储。(我不确定其他架构是否有这样的指令,但我认为很少,甚至没有,因为这没有任何实用价值且代价高昂。)
x86 (和x86_64) 有许多指令可以执行原子读-修改-写操作,但只能针对单个内存位置。例如,BTS 可以执行测试并设置操作,XCHG 可以交换寄存器中的值和内存位置中的值,XADD 可以执行原子递增,CMPXCHG 可以执行比较和交换操作。这些指令默认情况下都不是原子性的,但可以通过在汇编指令前添加 LOCK 前缀使其成为原子性的。

gnu的__atomic_store(type *ptr, type *val, int memmodel)并不是你想象的那样。请参见http://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html。它的作用是将val加载到寄存器中(或者其他一些操作(实际上没有定义它对val进行了什么操作)),然后原子性地将值存储到由ptr给出的内存位置。

在x86上,对于32位及以下的值,对齐的加载和存储默认是原子性的。

但是除非必须使用gnu内置函数,否则不应该使用它们。而应该使用--std=c++11标志,然后使用C++ atomics


在x86-64上,“单个内存位置”可以有多大?是64位还是32位? - Jay
在x86-64中,对齐的8位、16位、32位和64位加载和存储是原子性的。 - Wandering Logic
未对齐的16位、32位和64位加载和存储可能不是原子操作。 - Wandering Logic
还有一个cmpxchg16b指令,可以处理128位对齐的比特。我不知道是否还有其他指令可以原子地处理超过64位的宽度。 - Wandering Logic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接