CMPXCHG–忽略ZF标志是否安全



cmpxchg的操作伪代码如下(英特尔®;64和IA-32体系结构软件开发人员手册,第2A卷:指令集参考,A-M,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%的把握。

您的推理在我看来是正确的。
浪费重新生成ZF的指令不会导致正确性问题,而且如果cmp可以与JCC融合,只会损失代码大小。不过,与只替换EAX中的旧值相比,还需要额外的寄存器。

这可能就是为什么GNU C的旧式__sync内建(被采用内存顺序参数的__atomic内建所淘汰(只提供返回值布尔成功结果的__sync_val_compare_and_swap__sync_bool_compare_and_swap是可以的,而没有一个内建同时返回这两个值。

(较新的__atomic_compare_exchange_n更类似于C11/C++11 API,通过引用更新expected,并返回bool。这可以允许GCC不浪费具有cmp的指令。(

相关内容

  • 没有找到相关文章

最新更新