x86/x86_64 實現
x86 平臺上,使用 LOCK XADD
指令來實現原子自增:
#include <iostream>inline int atomic_increment_x86(int* value) {int result;__asm__ __volatile__("lock xaddl %1, %0": "+m"(*value), "=r"(result): "1"(1): "memory");return result + 1;
}
說明
lock xaddl
指令用于原子地將寄存器的值加到內存變量上,并返回原值。+m(*value)
:+m
表示被修改的內存操作數。"1"(1)
: 約束 1 號操作數使用寄存器,并初始化為1
。memory
作為 clobber 說明該指令會修改內存。
ARM(ARMv7)實現
在 ARM(32 位)上,使用 ldrex
和 strex
指令實現原子操作:
#include <iostream>inline int atomic_increment_arm(int* value) {int result, tmp;__asm__ __volatile__("1: ldrex %0, [%2]\n"" add %0, %0, #1\n"" strex %1, %0, [%2]\n"" teq %1, #0\n"" bne 1b\n": "=&r"(result), "=&r"(tmp): "r"(value): "memory", "cc");return result;
}
說明
ldrex
加載值到result
,并設置獨占標志。add
執行加 1 操作。strex
試圖存回新值到value
,并檢查是否成功(如果strex
失敗,則循環重試)。teq %1, #0
檢測strex
失敗標志,不為 0 時回到1:
處重試。
ARM64(AArch64)實現
在 ARM64(64 位)上,可以使用 ldxr
和 stxr
進行原子操作:
#include <iostream>inline int atomic_increment_arm64(int* value) {int result, tmp;__asm__ __volatile__("1: ldxr %w0, [%2]\n"" add %w0, %w0, #1\n"" stxr %w1, %w0, [%2]\n"" cbnz %w1, 1b\n": "=&r"(result), "=&r"(tmp): "r"(value): "memory");return result;
}
說明
ldxr
(load exclusive register)加載value
,并建立獨占訪問。stxr
(store exclusive register)存儲value
,如果失敗,則重新加載并重試。cbnz
指令檢查stxr
失敗標志,不為 0 時回到1:
處重試。
c++封裝
#include <iostream>inline int atomic_increment(int* value) {
#if defined(__x86_64__) || defined(__i386__)return atomic_increment_x86(value);
#elif defined(__aarch64__)return atomic_increment_arm64(value);
#elif defined(__arm__)return atomic_increment_arm(value);
#else#error "Unsupported architecture"
#endif
}int main() {int counter = 0;std::cout << "Before: " << counter << std::endl;std::cout << "After: " << atomic_increment(&counter) << std::endl;return 0;
}