MOV x86指令是否实现C++11 memory_order_release原子存储
Does the MOV x86 instruction implement a C++11 memory_order_release atomic store?
根据https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html,释放的存储被实现为x86(包括x86-64)上的CCD_ 1(进入存储器)。
根据他的http://en.cppreference.com/w/cpp/atomic/memory_order
memory_order_release:
具有此内存顺序的存储操作执行释放操作:当前线程中没有内存访问可以重新排序在这家商店之后。这样可以确保当前线程中的所有写入在获取或相同原子变量的其他线程中可见并将依赖项写入原子变量在使用相同原子的其他线程中可见。
我知道,当使用memory_order_release时,之前完成的所有内存存储都应该在此之前完成。
int a;
a = 10;
std::atomic<int> b;
b.store(50, std::memory_order_release); // i can be sure that 'a' is already 10, so processor can't reorder the stores to 'a' and 'b'
问题:裸MOV
指令(没有显式内存围栏)怎么可能足以满足这种行为?MOV
如何告诉处理器完成之前的所有存储?
运行时有内存重新排序(由CPU完成),编译时也有内存重新排列。请阅读Jeff Preshing关于编译时重新排序的文章(以及该博客上的许多其他好文章)以了解更多信息。
memory_order_release
防止编译器重新排序对数据的访问,以及发出任何必要的围栏或特殊指令。在x86 asm中,普通的加载和存储已经具有获取/释放语义,因此阻塞编译时重新排序对于acq_rel是足够的,但对于seq_cst则不足够。
这似乎是映射,至少在使用英特尔编译器编译的代码中是这样,我看到:
0000000000401100 <_Z5storeRSt6atomicIiE>:
401100: 48 89 fa mov %rdi,%rdx
401103: b8 32 00 00 00 mov $0x32,%eax
401108: 89 02 mov %eax,(%rdx)
40110a: c3 retq
40110b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
0000000000401110 <_Z4loadRSt6atomicIiE>:
401110: 48 89 f8 mov %rdi,%rax
401113: 8b 00 mov (%rax),%eax
401115: c3 retq
401116: 0f 1f 00 nopl (%rax)
401119: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
对于代码:
#include <atomic>
#include <stdio.h>
void store( std::atomic<int> & b ) ;
int load( std::atomic<int> & b ) ;
int main()
{
std::atomic<int> b ;
store( b ) ;
printf("%dn", load( b ) ) ;
return 0 ;
}
void store( std::atomic<int> & b )
{
b.store(50, std::memory_order_release ) ;
}
int load( std::atomic<int> & b )
{
int v = b.load( std::memory_order_acquire ) ;
return v ;
}
当前的英特尔体系结构文档第3卷(系统编程指南)很好地解释了这一点。参见:
8.2.2 P6和最近的处理器系列中的内存排序
- 读取不会与其他读取一起重新排序
- 写入不会与旧的读取一起重新排序
- 对内存的写入不会与其他写入一起重新排序,但以下情况除外:
这里解释了全内存模型。我认为英特尔和C++标准人员已经详细合作,为每一个可能的内存顺序操作确定了最佳映射,该映射符合第3卷中描述的内存模型,在这些情况下,普通存储和加载已经被确定为足够了。
请注意,仅仅因为x86-64上的这个有序存储不需要特殊说明,并不意味着这将是普遍正确的。对于powerpc,我希望看到类似lwsync指令和存储的东西,而在hpux(ia64)上,编译器应该使用st4.rel指令。
- ISearchJob->Release() 卡住
- Ascending order c++
- 调用 Napi::ThreadSafeFunction::Release() 会导致 ELIFECYCLE 322122
- LLVM 编译:目标的配方 '../lib/IR/Release+Asserts/Intrinsics.gen.tmp' failed
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- Release() 和析构函数之间的区别?
- 指向数组unique_ptr在调用 release() 后会自动释放动态内存,这是真的吗?
- 在Visual Studio代码中定义DEBUG和RELEASE符号
- Visual Studio 2017中使用ifstream时,Release和Debug的输出不同
- 从 Qt(release) 生成的文件执行.EXE文件时出错
- 为什么'acquire/release'不能保证 c++11 中的顺序一致性?
- "static initialization order fiasco"是 constexpr 变量的问题吗?
- 在使用 In Order 遍历成员函数时引发异常(堆栈溢出)时出现问题
- 为什么 std::make_unique<std::thread>(somefun()) 会在我没有调用 release() 时生成崩溃,并且在调用时会生成崩溃?
- 为什么在与静态库链接时强制执行 order(例如 source.cxx -lstatic)
- Qt在"debug"模式下正确渲染此SVG,但在"release"
- "The order of evaluation of expressions is left to right."是什么意思
- Qt5 嘈杂的调试消息"XI2 mouse release ... source MouseEventNotSynthesized"
- 为什么我的代码没有完成 Sound::release() 调用?
- 从动态库中加载FORTRAN函数:Debug vs Release