最近在看一些Linux内核空间代码,看到这个
uint64_t used;
uint64_t blocked;
used = atomic64_read(&g_variable->used); //#1
barrier(); //#2
blocked = atomic64_read(&g_variable->blocked); //#3
这个代码片段的语义是什么?它是否确保 #1 在 #3 之前由 #2 执行。但我有点困惑,因为
#A在 64 位平台,atomic64_read 宏扩展为
used = (&g_variable->used)->counter // where counter is volatile.
在 32 位平台中,它被转换为使用 lock cmpxchg8b。我假设这两个具有相同的语义,对于 64 位版本,我认为这意味着:
- all-or-nothing,我们可以排除地址未对齐且字长大于 CPU 原生字长的情况。
- 没有优化,强制 CPU 从内存位置读取。
atomic64_read 没有保留读取顺序的语义!!!看到这个
#B屏障宏定义为
/* Optimization barrier */
/* The "volatile" is due to gcc bugs */
#define barrier() __asm__ __volatile__("": : :"memory")
从wiki 这只是防止gcc 编译器重新排序读取和写入。
我很困惑的是它如何禁用 CPU 的重新排序优化?另外,我可以认为屏障宏是完整的围栏吗?