2016-07-21 68 views
0

我編譯和分析組件輸出:原子商店。結構

struct S{ 
public: 
    int a,b,c,d,e,f,g,h,i,j,k; 
}; 

int main() { 
    S s; 
    std::atomic<S> as; 
    as.store(s); 
    return 0; 
} 

我想看看怎麼做是它實際上執行atomic store。當對齊「小」操作數時很容易。但是,現在我們有更廣泛的操作數,所以這是一個更復雜的情況。

在我的其他問題(Atomicity on x86)@Peter柯德斯說:

對於較寬操作數,像原子寫入新的數據分成多個struct的 條目,你需要用一個鎖來保護它,所有 訪問它的尊重。 (您可以使用86鎖定cmpxchg16b 與重試循環做一個原子16B店。請注意,有沒有辦法 效仿無鎖)。

好,但它是什麼意思完全相同?這意味着什麼鎖定? 特別是,我知道lock是確保「前綴」指令的原子性的前綴。特別是,@Peter柯德斯說:

您可以使用86鎖定cmpxchg16b 與重試循環做一個原子16B店

我不明白它是如何能夠保持它的原子?好吧,我可以想象,16B的內存塊可以以原子方式存儲嗎?但接下來的迭代呢?

我希望我的疑惑是可以理解的,因爲我有一個問題來表達它。


我正在調試上面的程序,並在我眼中,魔術背後atomic_store。 我想這個函數會執行@Peter Cordes所說的。如果有人想,我可以粘貼在這裏拆卸__atomic_store

+4

你說你已經分析了生成的機器碼。那麼,你*可以告訴我們*這是如何實現的! –

+0

是的,繼續並粘貼__atomic_store的反彙編。 gcc只是通過引用傳入的數據來生成一個調用。 –

+0

我在這裏錯過了這個問題嗎? –

回答

3

您可以使用x86的鎖cmpxchg16b與重試循環做一個原子16B店

難道我真的說16B代替16B?哎呀。我將把它作爲更大編輯的一部分來解決。

它可以讓你做一個 16B原子存儲,但它做爲一個讀 - 修改 - 重寫,不斷重試,直到比較部分成功。你不能用它來自動存儲16B以上的數據。


是什麼意思鎖定?特別是,我知道鎖是一個確保「前綴」指令的原子性的前綴。

鎖定在自旋鎖/互斥體中,而不是lock前綴。 lock前綴只適用於讀取 - 修改 - 寫入指令;沒有lock mov [mem], eax做一個原子未對齊的商店或東西。如英特爾在文檔cmpxchg中記錄的那樣,總是讀取 - 修改 - 寫入總線週期爲lock。因此,一個lock mov存儲也會生成一個負載,如果您在內存映射I/O上使用該負載,則該負載具有不同的語義。 (閱讀可以引發副作用)。


我編譯和分析...

爲什麼你把這些代碼在main(),並從s初始化垃圾存儲到as裝配輸出?除此之外,main在幾個方面是特殊的。總是寫一個需要arg(或者隻影響全局)的函數總是更好。而atomic<s>需要是全球性的,而不是局部可能部分優化的地方,如果你想確保你看到gcc「真正」做什麼。

#include <atomic> 
struct S{ int a,b,c,d,e,f,g,h,i,j,k; }; // or int a[11] 
std::atomic<S> as; 
void atomic_struct_store_zero() { 
    S s = { 0 };  // initializes all members to zero 
    as.store(s); 
} 

compiles to一個函數調用__atomic_store,路過的src和dest的指針和大小。據推測,它在某處使用鎖,但該鎖不屬於as。 (sizeof(as) == sizeof(S) == 44)。