2017-03-09 65 views
0

我看了下面的文檔:ARM的Barrier_Litmus_Tests_and_CookbookARM Cortex-M4互斥鎖。 DMB指令

7.2節顯示了獲取互斥鎖/信號量的代碼。

Loop 
    LDREX R5, [R1] ; read lock 
    CMP R5, #0 ; check if 0 
    STREXEQ R5, R0, [R1] ; attempt to store new value 
    CMPEQ R5, #0 ; test if store suceeded 
    BNE Loop ; retry if not 
    DMB 

LDREX指令請求對存儲器地址進行獨佔訪問。如果處理器具有獨佔訪問權限,用STREX寫入操作纔會成功。 它們使用DMB指令來確保獨佔寫入與所有處理器同步。

我有一個小問題。假定處理器具有對內存地址的獨佔訪問權並將其鎖定。一旦STREX指令完成,獨佔訪問被刪除。其他處理器可以從現在開始訪問這個內存。但是,在DMB完成之前,寫入仍處於處理器的高速緩存中。如果另一個處理器在第一個處理器已經鎖定它但尚未同步到RAM時嘗試獲取鎖的訪問權限,會發生什麼情況。內存地址不是專門鎖定到第一個處理器,但寫入沒有完成。

任何人都可以解釋,爲什麼這個工作並且是安全的。我有我的問題。

+0

'DMB'通過使內存訪問直到內存層次結構中的各個點(即緩存)來指令內存訪問。高速緩存一致性機制對於允許處理器偵聽另一個高速緩存是必需的,否則您假設的情況可能會發生。 ARM緩存是一致的。沒有選項的'DMB'會進行全系統同步,我不知道它是什麼意思,但我可以寫一個內存。 –

+3

對於讀取 - 修改 - 寫入的原子性而言,'DMB'不是必需的。 'DMB'確保*其他*內存操作按照RMW操作進行排序。 – EOF

+0

的DMB是推動負載和存儲出去,讓他們完成這樣其他看到它... ...「確保鎖的成功要求由所有觀察者觀察到他們所觀察到的任何後續加載或存儲之前。」就像您使用其他內存障礙,刷寫寫入緩衝區和緩存等一樣。 –

回答

2

我認爲你已經過分複雜化了。看看amba/axi規範(以及你在哪裏找到了多核cortex-m4?)。 ldrex/strex用於在多處理器芯片中的處理器之間共享資源。一段時間以來,它們被錯誤地用於其他事物。不幸的是,ARM做了一個非常糟糕的工作,正確記錄了所有這些。

ldr的獨佔部分是processorid和地址(範圍)保存在表中。當strex發生時,會檢查該地址(範圍)的processorid是否與EXOKAY匹配,如果不是OKAY則不進行存儲。 Strex沒有清除任何東西,他們有趣的是有這個clrex指令,我假設它將processorid設置爲某些不會觸及的值,或者取決於他們如何構建表格,它們釋放了一個表格條目。

我可以寫這之後,試試這個,但你可以很容易地LDREX然後STREX然後STREX,相當肯定我做了INT在全尺寸的武器,將嘗試在一個皮質-M4 LDREX,STREX,STREX,CLREX, strex,看看會發生什麼。

在單處理器系統中,LDREX/STREX預計在ARM的邏輯工作,但不是必需的芯片供應商,以支持它,並且可以簡單地返回OKAY(代替EXOKAY)。除了你進入芯片供應商之外,L1當然也可能是L2邏輯邏輯。 (cortex-ms是否有l2?)。通常情況下,您不必擔心觸及芯片供應商代碼,如果不是無限期地運行很長時間,您可能會停留在其中一個緩存中,但不知道這些情況。例如,在Linux中禁用這兩個緩存就是一個皇家PITA,它們可能會使它看起來像是編譯時選項,但可以深入瞭解現實。只有一個處理器,你如何獲得不同的處理器ID?

在多處理器芯片中,芯片供應商應該在緩存之外正確支持它,如果您甚至可以通過獨佔訪問達到目的,如何正常使用ldrex/strex,最有可能在您的L1並且永遠不會暴露於芯片供應商提供的內容,但是如果您在兩者之間中斷並且很可能由L2保存,則可能會發生這種情況。在這種情況下,芯片中有多個processorid是有道理的,因爲有多個處理器。

這是很好

了Cortex-M4處理器實現本地監控獨家。處理器內的本地監視器已被構建,以使其 不包含任何物理地址,而是將任何訪問視爲與先前LDREX的地址匹配的 。這意味着 實施的獨佔預留顆粒是整個內存 地址範圍。

m7 trm說同樣的事情。

沒有多核心怎麼會/會產生一個不同的ID? 該文檔使用術語processorid來指示正在使用哪個處理器。 cortex-m中有多少處理器?也許它在其他地方使用不同的字符串/名稱進行記錄,但此時我不知道cortex-m中的processorid是如何生成的,並且單處理器是否存在多個?我沒有獲得核心知道肯定。

所以即使邏輯不支持每個地址的獨佔訪問,他們並沒有說他們沒有檢查processorid,他們只是考慮所有標記爲共享的內存的strex訪問與最後一個獨立於ldrex的processorid進行檢查的地址。

編輯

PUT32(0x01000600,0x600); 
PUT32(0x01000700,0x700); 
PUT32(0x01000800,0x800); 
CLREX(); 
hexstring(STREX(0x20000600,0x12345678)); 
hexstring(STREX(0x20000700,0x12345678)); 
hexstring(STREX(0x20000800,0x12345678)); 
hexstring(LDREX(0x20000600)); 
hexstring(STREX(0x20000600,0x6666)); 
hexstring(STREX(0x20000700,0x12345678)); 
hexstring(STREX(0x20000800,0x12345678)); 
hexstring(LDREX(0x20000600)); 
hexstring(STREX(0x20000700,0x7777)); 
hexstring(STREX(0x20000800,0x12345678)); 
hexstring(GET32(0x20000600)); 
hexstring(GET32(0x20000700)); 
hexstring(GET32(0x20000800)); 
CLREX(); 
hexstring(0xAABBCCDD); 
hexstring(LDREX(0x20000600)); 
CLREX(); 
hexstring(STREX(0x20000600,0x2222)); 
hexstring(GET32(0x20000600)); 

生產

00000001 
00000001 
00000001 
00000600 <-- ldrex 
00000000 <-- strex pass 
00000001 <-- strex fail 
00000001 
00006666 
00000000 
00000001 
00006666 
00007777 
00000800 
AABBCCDD 
00006666 
00000001 
00006666 

所以看起來他們在這裏做什麼是下一個STREX LDREX通過獨立的地址後。因此,使用你的條款strex「清除鎖定」。

請注意,在ldrex和strex之間加入clre會導致strex失敗。

不打相同的地址事項的一個LDREX一個STREX

hexstring(LDREX(0x20000900)); 
hexstring(STREX(0x20000900,0x2222)); 
hexstring(STREX(0x20000900,0x2222)); 

3EEDCC1B 
00000000 
00000001 

開啓數據高速緩存上didnt並沒有改變結果。

測試功能:

.thumb_func 
.globl LDREX 
LDREX: 
    ldrex r0,[r0] 
    bx lr 

.thumb_func 
.globl CLREX 
CLREX: 
    clrex 
    bx lr 

.thumb_func 
.globl STREX 
STREX: 
    strex r0,r1,[r0] 
    bx lr 

不像大哥哥懷裏:

CLREX(); 
hexstring(STREX(0x20000600,0x12345678)); 
hexstring(LDREX(0x20000600)); 
hexstring(STREX(0x20000600,0x6666)); 
hexstring(LDREX(0x20000600)); 
PUT32(0x20000600,0x11); 
hexstring(STREX(0x20000600,0x6666)); 

00000001 
00000600 
00000000 
00006666 
00000000 

的STREX生存的,之間至少基於文檔您發佈非獨佔店非獨佔訪問應該破壞先前的ldrex(在armv7-a上)。

注意上面是一個皮質-M4 r0p1 CPUID 0x410FC241

0

它是安全的,因爲芯片設計使得它的安全。操作系統將使用指令Test_and_Set的全部指令來執行semaphone和mutex命令。在多核/多處理器環境中,除了內置彙編命令外,沒有其他方法可以準確實現此功能。