我需要一個執行緒保存 idx 和 idx-- 操作。禁用中斷,即使用臨界區,是一回事,但我想了解為什么我的操作不是原子的,正如我所期望的?這是顯示行內匯編代碼的 C 代碼,使用 segger 臭氧:(另請注意,變數的地址顯示 32 位變數在記憶體中是 32 位對齊的,而 8 位和 16 位變數都是 16 位對齊的)
volatile static U8 dbgIdx8 = 1000U;
volatile static U16 dbgIdx16 = 1000U;
volatile static U32 dbgIdx32 = 1000U;
dbgIdx8 ;
080058BE LDR R3, [PC, #48]
080058C0 LDRB R3, [R3]
080058C2 UXTB R3, R3
080058C4 ADDS R3, #1
080058C6 UXTB R2, R3
080058C8 LDR R3, [PC, #36]
080058CA STRB R2, [R3]
dbgIdx16 ;
080058CC LDR R3, [PC, #36]
080058CE LDRH R3, [R3]
080058D0 UXTH R3, R3
080058D2 ADDS R3, #1
080058D4 UXTH R2, R3
080058D6 LDR R3, [PC, #28]
080058D8 STRH R2, [R3]
dbgIdx32 ;
080058DA LDR R3, [PC, #28]
080058DC LDR R3, [R3]
080058DE ADDS R3, #1
080058E0 LDR R2, [PC, #20]
080058E2 STR R3, [R2]
uj5u.com熱心網友回復:
不能保證 和--是原子的。如果您需要保證原子性,則必須找到其他方法。
正如@StaceyGirl 在評論中指出的那樣,您也許可以使用<stdatomic.h>的設施。例如,我看到atomic_fetch_add定義了一個原子函式,它的作用類似于 您正在爭取的后綴。還有一個atomic_fetch_sub。
或者,您可能有一些編譯器內在函式可用于以某種特定于處理器的方式執行原子增量。
uj5u.com熱心網友回復:
- ARM 皮質內核不修改記憶體。所有記憶體修改都作為 RMW(讀-修改-寫)操作執行,默認情況下不是原子操作。
但是 Cortex M33 有特殊的指令來鎖定對記憶體位置的訪問。LDREX 和 STREX。https://developer.arm.com/documentation/100235/0004/the-cortex-m33-instruction-set/memory-access-instructions/ldaex-and-stlex
您可以直接在 C 代碼中使用它們,而無需使用內部函式來接觸程式集。
- 不要在任何性能(您希望鎖定盡可能短的時間)敏感程式中使用非 32 位資料型別。大多數較短的資料型別操作都會添加一些額外的代碼。
uj5u.com熱心網友回復:
變數被標記為volatile告訴編譯器假設它可以以未知方式使用或修改。因此處理器會將值加載到暫存器,執行所需的操作,并將結果存盤回記憶體位置。Cortex-M3 中沒有“記憶體中”演算法。
但是,洗掉關鍵字volatile可能會,也可能不會使操作原子化。這取決于增量前后所做的操作。沒有保證。
uj5u.com熱心網友回復:
后綴遞增運算子 indbgIdx8 ;不是原子的,因為 C 編譯器確實保存了當前值,dbgIdx8然后對其進行任何操作(在這種情況下沒有任何操作),然后進行遞增。
要實作原子操作,請使用前綴增量運算子,例如 dbgIdx8;
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/335629.html
下一篇:洗掉出現的“The”和“the”
