[英]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)上實現為MOV
(進入內存)。
根據他的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("%d\n", 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指令。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.