[英]When is CLREX actually needed on ARM Cortex M7?
我在網上找到了幾個地方,其中指出每當進入中斷例程時“必須”調用 CLREX,我不明白。 CLREX狀態的文檔(添加編號以便於參考):
(1) 清除執行處理器的本地記錄,該記錄表明地址已請求獨占訪問。
(2) 使用
CLREX
指令將緊密耦合的獨占訪問監視器返回到其開放訪問狀態。 這消除了對內存的虛擬存儲的要求。(3)
CLREX
是否也清除執行處理器的全局記錄,即某個地址已請求獨占訪問,這是實現定義的。
我在這里幾乎什么都不懂。
MOV r1, #0x1 ; load the ‘lock taken’ value
try: <---\
LDREX r0, [LockAddr] ; load the lock value |
CMP r0, #0 ; is the lock free? |
STREXEQ r0, r1, [LockAddr] ; try and claim the lock |
CMPEQ r0, #0 ; did this succeed? |
BNE try ; no - try again ------------/
.... ; yes - we have the lock
為什么要清除“本地記錄”? 我認為LDREX
/ STREX
足以保證從多個中斷對地址進行原子訪問? 即 GCC for ARM 使用LDREX
/ STREX
編譯所有 C11 原子函數,我沒有看到CLREX
在任何地方被調用。
第二段指的是什么“對虛擬商店的要求”?
全局記錄和本地記錄有什么區別? 多核場景是否需要全局記錄?
分別回答(和解釋)你的三個問題:
1、為什么要清除訪問記錄?
當強制執行嚴格的代碼嵌套時,例如處理中斷時,通常不需要CLREX
。 但是,在某些情況下它很重要。 想象一下,您正在為搶占式操作系統內核編寫上下文切換,它可以異步掛起正在運行的任務並恢復另一個。 現在考慮以下病態情況,涉及使用LDREX
和STREX
操作相同共享資源的兩個相同優先級的任務(A 和 B):
Task A Task B
...
LDREX
-------------------- context switch
LDREX
STREX (succeeds)
...
LDREX
-------------------- context switch
STREX (succeeds, and should not)
...
因此,上下文切換必須發出CLREX
以避免這種情況。
2. 避免什么“對虛擬商店的要求”?
如果沒有CLREX
指令,則有必要使用STREX
來放棄獨占訪問標志,這涉及內存事務,因此如果您只想清除標志,則速度比所需的速度慢。
3. 是多核場景的“全球記錄”嗎?
是的,如果您使用的是單核機器,則只有一個記錄,因為只有一個 CPU。
其實CLREX
並不需要在M7異常/中斷,它似乎只包含兼容性的原因。 從文檔(版本 c) :
CLREX 支持與其他 ARM Cortex 處理器的兼容性,如果異常發生在同步操作中的加載獨占指令和匹配的存儲獨占指令之間,則這些處理器必須強制存儲獨占失敗。 在 Cortex-M 處理器中,本地獨占訪問監視器在異常邊界上自動清除,因此使用 CLREX 的異常處理程序是可選的。
因此,由於 Cortex-M 處理器在異常/中斷進入/退出時清除本地獨占訪問標志,這否定了CLREX
大多數(所有?)用例。
關於你的第三個問題,正如其他人所說,你認為全局記錄用於多核場景是正確的。 根據實現定義對本地/全局標志的影響,在多核處理器上可能仍然存在CLREX
用例。
我可以理解為什么對此存在混淆,因為 M7 文檔的初始版本不包含這些句子(更不用說 ARM 網站上更通用的文檔的各種其他版本)。 即使是現在,我什至無法鏈接到最新版本。 該頁面默認顯示“版本 a”,您必須通過下拉框手動更改版本(希望將來會更改)。
為了回應評論,提供了一個額外的文檔鏈接。 這是手冊的一部分,描述了特定說明文檔之外的這些說明的用法(並且自第一次修訂以來一直存在):
如果出現以下情況,處理器將刪除其獨占訪問標簽:
它執行 CLREX 指令。
無論寫入是否成功,它都會執行 STREX 指令。
發生異常。 這意味着處理器可以解決不同線程之間的信號量沖突。
在多處理器實現中:
執行 CLREX 指令只會刪除處理器的本地獨占訪問標記。
執行 STREX 指令或異常會刪除處理器的本地獨占訪問標記。
對共享內存區域執行 STREX 指令也可以去除系統中處理器的全局獨占訪問標簽。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.