5

次のように、32ビットの比較と交換のためにi686アーキテクチャでcmpxchg(比較と交換)を使用しています。

(編集者注: 元の 32 ビットの例にはバグがありましたが、問題はそれについてではありません。このバージョンは安全であり、おまけとして x86-64 でも正しくコンパイルされます。 また、インライン asm はそうではないことに注意してください。これには必要または推奨;または、 i486 および x86-64__atomic_compare_exchange_nの古い__sync_bool_compare_and_swap作業int32_tint64_t.しかし、この質問は、インライン asm でそれを行うことについてです.)

// note that this function doesn't return the updated oldVal
static int CAS(int *ptr, int oldVal, int newVal)
{
    unsigned char ret;
    __asm__ __volatile__ (
            "  lock\n"
            "  cmpxchgl %[newval], %[mem]\n"
            "  sete %0\n"
            : "=q" (ret), [mem] "+m" (*ptr), "+a" (oldVal)
            : [newval]"r" (newVal)
            : "memory");    // barrier for compiler reordering around this

    return ret;   // ZF result, 1 on success else 0
}

64ビットの比較とスワップのx86_64アーキテクチャに相当するものは何ですか?

static int CAS(long *ptr, long oldVal, long newVal)
{
    unsigned char ret;
    // ?
    return ret;
}
4

4 に答える 4

7

x86_64命令セットには、8 バイト (64 ビット) のコンペア アンド スワップ用の ( クワッドワードの ) 命令がありますcmpxchgqq

8 バイトの量で機能する命令もありcmpxchg8bますが、セットアップがより複雑で、より自然な 64 ビットではなく、edx:eax使用する必要があります。これが存在する理由は、ほぼ間違いなく、Intel が登場するずっと前に 64 ビットのコンペア アンド スワップ操作を必要としていたという事実に関係しています。64 ビット モードではまだ存在しますが、唯一のオプションではなくなりました。ecx:ebxraxx86_64

しかし、前述のように、cmpxchgqおそらく 64 ビット コードのほうが適切なオプションです。


16 バイト オブジェクトを cmpxchg する必要がある場合、64 ビット バージョンcmpxchg8bcmpxchg16b. 非常に初期の AMD64 CPU には存在しなかったため、 (gcc に対して)有効にしない限り、コンパイラは 16B オブジェクトのstd::atomic::compare_exchangeに対してそれを生成しません。-mcx16ただし、アセンブラはそれをアセンブルしますが、バイナリは初期の K8 CPU では実行できないことに注意してください。(これは にのみ適用され、 64 ビット モードの には適用されcmpxchg16bません)。cmpxchg8bcmpxchgq

于 2009-05-07T06:23:47.643 に答える
2

cmpxchg8b

__forceinline int64_t interlockedCompareExchange(volatile int64_t & v,int64_t exValue,int64_t cmpValue)
{
  __asm {
    mov         esi,v
    mov         ebx,dword ptr exValue
    mov         ecx,dword ptr exValue + 4
    mov         eax,dword ptr cmpValue
    mov         edx,dword ptr cmpValue + 4
    lock cmpxchg8b qword ptr [esi]
  }
}
于 2009-05-07T06:25:01.633 に答える
-1

AMD64 Architecture Programmer's Manual V3 の cmpxchg8B の使用法:

EDX:EAX レジスタを 64 ビットのメモリ位置と比較します。等しい場合は、ゼロ フラグ (ZF) を 1 に設定し、ECX:EBX レジスタをメモリ位置にコピーします。それ以外の場合は、メモリの場所を EDX:EAX にコピーし、ゼロ フラグをクリアします。

cmpxchg8B を使用して、単純なミューテックス ロック機能を x86-64 マシンに実装します。ここにコードがあります

.text
.align 8
.global mutex_lock
mutex_lock:
    pushq   %rbp
    movq    %rsp,   %rbp

    jmp .L1

.L1:
    movl    $0, %edx
    movl    $0, %eax
    movl    $0, %ecx
    movl    $1, %ebx
    lock    cmpxchg8B   (%rdi)
    jne .L1
    popq    %rbp
    ret
于 2013-12-01T06:12:07.437 に答える