- 論壇徽章:
- 0
|
本帖最后由 blake326 于 2014-06-29 22:25 編輯
好吧沒人回,我自己理解下,關(guān)鍵的一點:
“ 狀態(tài)為S時,數(shù)據(jù)將直接寫入到Cache中,并將狀態(tài)改為M,同時其他CPU保存該數(shù)據(jù)副本的Cache行狀態(tài)將從S或者O遷移到I(Probe Write Hit)。”這個是否原子?
這個操作看起來有很多小步組成的,寫數(shù)據(jù)到cache,修改m,同時發(fā)送inval request到其他cpu,可能還要處理其他cpu回來的inval replay。所以,當然不是原子的了,要不然肯 定很影響性能的。
但是,更關(guān)鍵的一點,mesi會保證整個一套動作是安全的,之前的例子,cpu0,cpu1同時寫s的cache line,那么對于這同一個cache line,mesi應(yīng)該會有一個同步機制(類似 mutex)之類的保證同時只有一個cpu操作了addr響應(yīng)的cache line.比如,cpu0,cpu1同時開始寫,首先,mesi會仲裁選擇一個cpu進行對cache line進行操作,另外一個cpu只能等 待,待的就是之前說的一些列操作:狀態(tài)為S時,數(shù)據(jù)將直接寫入到Cache中,并將狀態(tài)改為M,同時其他CPU保存該數(shù)據(jù)副本的Cache行狀態(tài)將從S或者O遷移到I)。因此,我這個帖子 的結(jié)果就是,最終cache line的值是0, 1, 2, 3, 4, 5, 6, 7. arm-linux-gcc同志是正確的。
重新整理一下cache一致性的狀態(tài)切換:
假設(shè)有cpu0, cpu1。一個虛擬地址addr。
則cpu0, cpu1都有一個addr對應(yīng)的cache line, 狀態(tài)有四種:有效E, 修改M,共享S, 無效I。I實際上就是說該addr在cache中沒有緩存的意思。根據(jù)這四種狀態(tài),組合分析一下 。
cpu0,cpu1的cache狀態(tài)一樣:
都是I狀態(tài):
cpu0讀的話,首先會像mesi申請cache line使用權(quán),然后開始分配一個cache line并且從ddr把addr的值讀取過來,狀態(tài)變成E。
cpu0寫的話,首先會像mesi申請cache line使用權(quán),然后開始分配一個cache line并且從寫addr,狀態(tài)變成E。
都是S狀態(tài):
cpu0讀的話,首先會像mesi申請cache line使用權(quán),如果其他cpu已經(jīng)獲取了cache line的使用權(quán)的話,則這里要等待。獲得cache line使用權(quán)之后,直接把cache line的值讀出來 就好了。
cpu0寫的話,首先會像mesi申請cache line使用權(quán),cpu0寫addr,修改本地cache,狀態(tài)變成M,且發(fā)送一個inv消息給cpu1通知cpu1失效響應(yīng)的cache line,當然cpu1應(yīng)該會發(fā)送一 個inval replay回來。
都是E,M的狀態(tài)是不存在的。因為,E/M狀態(tài)的核心一點就是表示cache line只在本地cpu中存在,不存在競爭關(guān)系。
cpu0,cpu1的cache狀態(tài)不一樣:
cpu0 I, cpu1 E:
cpu0 讀addr,首先會像mesi申請cache line使用權(quán),發(fā)現(xiàn)cpu1有對應(yīng)的E cache,新建一個本地的cache line將cpu1的cache line拷貝過來,并且設(shè)置大家的狀態(tài)為S。
cpu0 寫addr,首先會像mesi申請cache line使用權(quán),發(fā)現(xiàn)cpu1有對應(yīng)的E cache,發(fā)送一個inv消息告訴cpu1,并且等待其inval replay返回,然后本地新建一個cache line將ddr 讀進來,之后修改本地cache line,并且設(shè)置狀態(tài)M。
cpu1 讀addr,因為E狀態(tài),無需向mes申請cache line使用權(quán),直接讀cache。
cpu1 寫addr,因為E狀態(tài),無需向mes申請cache line使用權(quán),直接寫cache,設(shè)置狀態(tài)為M。
cpu0 I, cpu1 M:
cpu0 讀addr,首先會像mesi申請cache line使用權(quán),發(fā)現(xiàn)cpu1有對應(yīng)的M cache,發(fā)送一個flush消息告訴cpu1并且等待cpu1刷新cache到ddr,然后新建一個本地cache line將ddr 從內(nèi)存讀進來,并且設(shè)置狀態(tài)為E。
cpu0 寫addr,首先會像mesi申請cache line使用權(quán),發(fā)現(xiàn)cpu1有對應(yīng)的M cache,發(fā)送一個flush消息告訴cpu1并且等待cpu1刷新cache到ddr,然后新建一個本地cache line將ddr 從內(nèi)存讀進來并且寫,并且設(shè)置狀態(tài)為M。
cpu1 讀addr,因為M狀態(tài),無需向mes申請cache line使用權(quán),直接讀。
cpu1 寫addr,因為M狀態(tài),無需向mes申請cache line使用權(quán),直接寫。
cpu亂序模型:
http://www.72891.cn/thread-3593865-1-1.html
cpu亂序,cache一致性,和內(nèi)存屏障。
內(nèi)存屏障mb() 是和cpu亂序,chache一致性相關(guān)的。下面的老例子:
cpu0
a = 1;
wmb();
b = 2;
cpu1
讀 b;
rmb();
讀 a;
cpu亂序模型會讓a=1,a=2執(zhí)行順序顛倒。 讀b,讀a順序顛倒。
wmb() 會使 a=1先執(zhí)行,然后再執(zhí)行 b=1, 說的再細一點同cache一致性就有關(guān)系了,因為a=1,之前說了是一個很多小步驟組成的過程,獲取cache使用權(quán),寫cache,發(fā)送inval a ,修改m狀態(tài)。wmb實際上就是保證,在wmb之前所有的inval request已經(jīng)發(fā)了出去。就是說保證先發(fā)inval a, 然后再發(fā)inval b.
rmb() 會先執(zhí)行讀b,然后再執(zhí)行讀a,仔細一點,實際上就是說在rmb之前所有的inval request完成了。那么,我們剛才已經(jīng)知道了cpu1先收到的inval a然后是inval b,假設(shè)在 rmb()時,inval b已經(jīng)執(zhí)行了,那么這個時候會處理掉所有的inval request,確保inval a也應(yīng)執(zhí)行了。就是說cpu1假設(shè)讀到了b=2,那么rmb()之后,a肯定是1.
cache alias:
http://www.72891.cn/forum.php?mod=viewthread&tid=1972593
cache一般有幾種類型:
pipt
vivt
vipt noalias
vipt alias
實際上armv7 的dcache是vipt noalias的。icache是vipt alias的。
為什么會有cache alias問題呢,為什么amv7 dcache又沒有呢。
一個cache由 cache line size * num set * way 組成。
一般是 32 * 256 * 4 = 32KB.
如果line size * num set = 8KB大于page size的話那么就有可能有alias問題。
假設(shè)0xf000 0000和0xf000 1000兩段地址都是映射同一個page的話,那么訪問0xf000 0000和0xf000 1000時,他們在cache中的num是不同的,就是有各自的cache line,但是映射的物理地址是一樣的。如果硬件不能自動處理的話,軟件一定要處理好。
現(xiàn)在假設(shè)dcache是vipt alias的話,文件系統(tǒng)寫一個page cache時,會調(diào)用flush_dcache_page()來解決這個alias問題。
最終會調(diào)用到flush_pfn_alias(),好久不看相關(guān)的東西,看不懂這個鳥玩意了,請高手幫忙分析下。
|
|