Memory Barriers

        這回該進入主題了。
        上一文最後提到了 Memory Barriers ,即內存屏障。因爲對一個 CPU 而言,a = 1; b = 1. 因爲在中間加了內存屏障,在 X86 架構下,就是 mfence 指令,此時在上一文中執行時。狀況就變成這樣了,當 CPU0 發
出 "read invalidate" 消息後,就會開始運行 mfence 指令,該指令把 Store Buffer 中的項都標記一下。而後開始運行 b = 1,此時儘管 cache hint (cache 命中),但是由於 Store Buffer 中存在被標記的項,因此
b 的新值不會直接應用到 cache 中,它也會被記錄到 Store Buffer 中,並會等待被 Store Buffer 中被標記的項被應用,CPU0 也會繼續運行其餘指令。
        這樣 CPU1 將會看到正確的 a 的值。看似完美的結局。事實上還差那麼一點點。
        依舊是上一文的小樣例。

a 和 b 初始化都爲 0。 a 在 CPU1 的 cache 中, b 在 CPU0 的 cache 中。
        CPU 0 運行如下的代碼:
        a = 1;
mfence;
        b = 1;
        CPU1 運行如下的代碼:
        while (b != 1);
        assert (a == 1);
        斷言必定能成功嗎? 讓咱們若是如下的狀況發生:
        1. CPU0 運行 a = 1, 但是發現 a 不在 cache 中。它就發出 "read invalidate" 消息,並且把 a 的值存在 store buffer 中;
        2。安全

CPU1 運行 b != 1 的比較,讀取 b 的值,結果不在 cache 中,因爲它不想改寫,因此僅僅發一個 "read" 消息出去。
        3. CPU0 運行 mfence, 將 Store Buffer 中的項全部標記,而後運行 b = 1, 結果發現 Store Buffer 中有標記的項,因此就把 b 的值也記錄在 Store Buffer,這些項是未標記的。
        4. CPU1 收到 "read invalidate" 消息,它把這個消息存入 Invalidate Queue 中。並做出迴應;
        5. CPU0 收到迴應,把 a 的值寫入 Cache line, 把 b 的值也寫入 cache line; 
        6. CPU0 收到 "read" 消息,並用出迴應;
        7. CPU1 收到迴應,退出循環,此時讀取 a 的值,由於 Invalidate 消息還在隊列中。此時它會以爲 Cache line 中 a 的值有效,但事實上爲舊值,因此斷言錯誤。
        很是明顯。兵敗在了 Invalidate Queue 上。那可不可以向 Store Buffer 同樣。弄一個屏障在讀取 Cache line 時做一下檢查呢?
        假設你能想到這裏,說明遇上了設計 CPU 的那些傢伙。對,這裏也可以用一個 mfence.
        代碼就成了這個樣子
        while (b != 1);
        mfence;
        assert(a == 1);
        這樣當 while (b != 1) 退出循環以後,遇到了 mfence, 它就必須停下來把 Message Queue 中的因此消息應用到 Cache line 中,此時就會發現 a 的 cache line 失效。當再進行讀取 a 時,就會發消息給
CPU0 。進而獲得正確的結果。架構


        事實上 X86 提供細粒度的指令 lfence (讀屏障), sfence (寫屏障)。 mfence(讀寫屏障)。spa


        lfence: 該指令把當前invalidate queue 裏的全部項標記。當 load 動做發生時,假設隊列中有標記項。那麼 CPU 必須把 Message Queue 中存在的消息全部應用以後,纔會運行後面的指令。設計

這樣讀取就變得安全;
        sfence: 該指令把標記 Store Buffer 中因此已存在的寫入記錄項。當下次再有寫入操做時,即便命中也不會直接應用到 cache 中。而是記錄到 Store Buffer 中。
        mfence: 兼備以上兩條指令的做用。
        另外一些其餘指令具有這種做用,通常如帶 lock 前綴的指令等。隊列

因此普通狀況下內存屏障需要成對使用。
        最終快要完了。 內存

相關文章
相關標籤/搜索