操作偽代碼cmpxchg如下(英特爾? 64 和 IA-32 架構軟體開發人員手冊,第 2A 卷:指令集參考,AM,2010):
IF accumulator = DEST
THEN
ZF ← 1;
DEST ← SRC;
ELSE
ZF ← 0;
accumulator ← DEST;
FI;
至少乍一看,累加器會在(且僅當)時 ZF = 0更改其值。那么,是安全還是完全忽略ZF,只觀察累加器值的變化來判斷操作是否成功?
換句話說,我可以安全地使用變體 #2 而不是 #1 嗎?
#1:
mov eax, r8d
lock cmpxchg [rdx], ecx
jz @success
#2:
mov eax, r8d
lock cmpxchg [rdx], ecx
cmp eax, r8d
jz @success
我的意思是,是否有一些非常特殊的情況,只尋找ZF才能真正顯示操作是否成功?這可能是一個微不足道的問題,但無鎖多任務處理幾乎不可能除錯,所以我必須 101% 確定。
uj5u.com熱心網友回復:
你的推理在我看來是正確的。
浪費指令來重新生成 ZF 不會導致正確性問題,如果 cmp 可以與 JCC 融合,只會消耗代碼大小。不過,這也會花費您一個額外的暫存器,而不是僅在 EAX 中使用舊值來替換。
這可能就是為什么 GNU C 的舊式__sync內建函式(被采用記憶體順序引數的內建函式廢棄__atomic)只提供__sync_val_compare_and_swap并__sync_bool_compare_and_swap回傳值或布爾成功結果,沒有一個內建函式可以同時回傳兩者的原因。
(較新__atomic_compare_exchange_n的 API 更像 C11/C 11 API,expected通過參考進行更新,并回傳一個bool. 這可能使 GCC 不會浪費帶有 . 的指令cmp。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/459724.html
上一篇:你怎么能告訴一臺計算機它正在添加而不在Assembly中添加addl
下一篇:什么是PSP(程式段前綴)?
