簡體   English   中英

記憶障礙如何運作?

[英]How does memory barrier work?

在Windows下,有三個編譯器內部函數來實現內存屏障:

1. _ReadBarrier;

2. _WriteBarrier;

3. _ReadWriteBarrier;

但是,我發現了一個奇怪的問題:_ReadBarrier似乎是一個無效的虛函數! 以下是VC ++ 2012生成的匯編代碼。

我的問題是:如何在匯編指令中實現內存屏障功能?

int main()
{   
013EEE10  push        ebp  
013EEE11  mov         ebp,esp  
013EEE13  sub         esp,0CCh  
013EEE19  push        ebx  
013EEE1A  push        esi  
013EEE1B  push        edi  
013EEE1C  lea         edi,[ebp-0CCh]  
013EEE22  mov         ecx,33h  
013EEE27  mov         eax,0CCCCCCCCh  
013EEE2C  rep stos    dword ptr es:[edi]  
    int n = 0;
013EEE2E  mov         dword ptr [n],0  
    n = n + 1;
013EEE35  mov         eax,dword ptr [n]  
013EEE38  add         eax,1  
013EEE3B  mov         dword ptr [n],eax  
    _ReadBarrier();
    n = n + 1;
013EEE3E  mov         eax,dword ptr [n]  
013EEE41  add         eax,1  
013EEE44  mov         dword ptr [n],eax 
}
013EEE56  xor         eax,eax  
013EEE58  pop         edi  
013EEE59  pop         esi  
013EEE5A  pop         ebx  
013EEE5B  add         esp,0CCh  
013EEE61  cmp         ebp,esp  
013EEE63  call        __RTC_CheckEsp (013EC3B0h)  
013EEE68  mov         esp,ebp  
013EEE6A  pop         ebp  
013EEE6B  ret 

_ReadBarrier_WriteBarrier_ReadWriteBarrier影響編譯器重新排序代碼的內在函數 ; 它們與CPU內存屏障完全無關,僅對特定類型的內存有效(請參閱此處的 “受影響的內存”)。

MemoryBarrier()是用於強制CPU內存屏障的內在函數。 但是,Microsoft的建議是使用std::atomic<T>繼續使用VC ++。

現代處理器能夠在實際“完成”指令之前執行相當長的指令,因此在涉及某些類型的存儲器操作時,使用內存屏障來阻止它運行到很遠的地方,其中嚴格的排序是必需 - 對於大多數事情,如果你在變量b之前寫入變量a,或者在a之前寫入b,則實際上並不重要。 但有時它確實如此。

x86指令集有lfencesfencefence ,它們分別是“fence in”加載,存儲和所有內存操作。 關於“柵欄”或“屏障”指令的要點是確保屏障指令之前的所有指令在屏障可以繼續之后的下一指令之前完成了它們的加載,存儲或兩者。

例如,如果要實現信號量,互斥量或類似指令,這一點很重要,因為在繼續讀取其他數據之前,存儲值“我已鎖定信號量”非常重要。 換句話說,事情可能會出錯。

請注意,除非您真的知道自己在處理內存障礙方面做了什么,否則最好不要使用它們 - 並且依賴已經解決相同問題的現有代碼 - std::atomic是一個資助此類代碼的地方。 我寫了很多“棘手的”代碼,但只有一兩次我的代碼中需要一個內存屏障。

有好幾次,我需要讓編譯器不要傳播代碼,你可以用“無操作函數”來做,顯然現在甚至還有特殊的內部函數來做。

有幾個要點需要考慮。 也許第一個障礙只是在多線程代碼中產生影響,並且大多數編譯器需要一個特殊選項來生成多線程代碼。 _ReadBarrier這樣的東西幾乎肯定是編譯器內置_ReadBarrier ,除非你給出了多線程代碼的選項,否則它什么都不做。

第二,即使在多線程環境中,硬件所需的內容也各不相同。 在我工作的大多數機器上(大約四十年),機器從不需要任何東西; 只有當機器具有復雜的讀寫流水線時,障礙才會變得相關。 (大多數早期的機器甚至沒有圍欄或屏障指令,因此生成的代碼必須為空。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM