2015-04-28 109 views
5

根據這個https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html, 發佈的商店被實現爲MOV(進入內存)。MOV x86指令是否實現了C++ 11 memory_order_release原子存儲?

據他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如何告訴處理器完成以前的所有商店?

+1

你忘了提及「在x86上」 – Cubbi

+0

@cubbi:對,很重要,完成 – Krab

+0

因爲它是一個動態調度的ISA,所以芯片總是假定最壞的情況。 – user3528438

回答

3

但這似乎是映射,至少在與Intel編譯器,其中,I看到編譯的代碼:

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 ; 
} 

當前Intel architecture documents,第3卷(系統編程指南),對此做了很好的解釋。請參閱:在P6

8.2.2內存排序和最近的處理器系列

  • 讀取是不可能與其他讀取重新排序。
  • 寫入不會被舊的讀取重新排序。
  • 寫入內存不與其它寫入重新排序,但下列情況除外:......

完整的內存模型有解釋。我假設英特爾和C++標準人員已經共同合作詳細地確定了每個存儲器訂單操作的最佳映射,這符合第3卷中描述的存儲器模型,並且確定了存儲和負載。在這些情況下就足夠了。

請注意,僅僅因爲x86-64上的此有序存儲庫不需要特殊說明,並不表示這將是普遍適用的。對於powerpc,我希望看到像store和store一樣的lwsync指令,在hpux(ia64)上,編譯器應該使用st4.rel指令。

4

在運行時有一個內存排序(由CPU完成),並且在編譯時有內存排序。 memory_order_release可防止編譯器重新排序對數據的訪問。請閱讀this article(以及該博客上的其他許多優秀博客)以獲取更多信息。