比較してどのような
static int CAS(int *ptr, int oldVal, int newVal)
{
unsigned char ret;
__asm__ __volatile__ (
" lock\n"
" cmpxchgl %2,%1\n"
" sete %0\n"
: "=q" (ret), "=m" (*ptr)
: "r" (newVal), "m" (*ptr), "a" (oldVal)
: "memory");
//above assembly returns 0 in case of failure
if (ret) return 0;
}
スワップ。
あり、8バイトの量に動作しますcmpxchg8b
命令もありますが、それはむしろ、より自然な64ビットrax
よりedx:eax
とecx:ebx
を使用するためにあなたを必要とし、設定するには、より複雑です。この理由が存在する理由は、Intelがx86_64
が登場するずっと前に、64ビットの比較とスワップ操作が必要だったこととほぼ関係があります。それは64ビットモードではまだ存在しますが、もはや唯一のオプションではありません。
しかし、前述したように、おそらく、cmpxchgq
が64ビットコードのためのより良いオプションです。
あなたは16バイトのオブジェクトをCMPXCHGする必要がある場合は、cmpxchg8b
の64ビット版はcmpxchg16b
です。最初のAMD64 CPUから欠けていたので、-mcx16
(gcc用)を有効にしない限り、コンパイラは16Bオブジェクトのstd::atomic::compare_exchangeのために生成しません。アセンブラはそれを組み立てますが、あなたのバイナリが最古のK8 CPUで動作しないように注意してください。 (これは、cmpxchg16b
にのみ適用され、64ビットモードではcmpxchg8b
には適用されず、cmpxchgq
に適用されます)。
IIRCは、CMPXCHG8Bが戻って最初のi486プロセッサへのすべての道をさかのぼるので、互換性はcpxchgqよりも問題が少ないことになるだろう。 –
@Brian、私はあまりにもOPがx86_64用であると明示していたので、ここでは互換性が問題であると確信していません。私が考えているのは、より自然な(私にとって) 'rax'ではなく、edx:eax/ecx:ebxを使うために必要な" asm体操 "です。また、あなたの呼び出し規約が、許可されているレジスタの破棄によって、それらのレジスタへの書き込みが許可されていることを確認してください。さもなければ、それらを保護するためにプッシュとポップが必要です。 – paxdiablo