次の方法で共有


_InterlockedCompareExchange128 組み込み関数

Microsoft 固有の仕様

128 ビットのインタロックされた比較と交換を実行します。

構文

unsigned char _InterlockedCompareExchange128(
   __int64 volatile * Destination,
   __int64 ExchangeHigh,
   __int64 ExchangeLow,
   __int64 * ComparandResult
);
unsigned char _InterlockedCompareExchange128_acq(
   __int64 volatile * Destination,
   __int64 ExchangeHigh,
   __int64 ExchangeLow,
   __int64 * ComparandResult
);
unsigned char _InterlockedCompareExchange128_nf(
   __int64 volatile * Destination,
   __int64 ExchangeHigh,
   __int64 ExchangeLow,
   __int64 * ComparandResult
);
unsigned char _InterlockedCompareExchange128_np(
   __int64 volatile * Destination,
   __int64 ExchangeHigh,
   __int64 ExchangeLow,
   __int64 * ComparandResult
);
unsigned char _InterlockedCompareExchange128_rel(
   __int64 volatile * Destination,
   __int64 ExchangeHigh,
   __int64 ExchangeLow,
   __int64 * ComparandResult
);

パラメーター

宛先
[in、out] 2 つの 64 ビット整数の配列 (128 ビット フィールドと見なされます) である宛先を指すポインター。 一般保護違反を回避するには、宛先データが 16 バイトにアラインされている必要があります。

ExchangeHigh
[in] 宛先の上位部分と交換できる 64 ビット整数。

ExchangeLow
[in] 宛先の下位部分と交換できる 64 ビット整数。

ComparandResult
[in、out] 宛先と比較する、2 つの 64 ビット整数の配列 (128 ビット フィールドと見なされます) を指すポインター。 出力時、この配列は宛先の元の値で上書きされます。

戻り値

128 ビットの比較対照値が宛先の元の値と等しい場合は 1。 ExchangeHigh および ExchangeLow では 128 ビットの宛先が上書きされます。

比較対照値が宛先の元の値と等しくない場合は 0。 宛先の値は変更されず、比較対象値は宛先の値で上書きされます。

要件

Intrinsic Architecture
_InterlockedCompareExchange128 x64、ARM64
ARM64
_InterlockedCompareExchange128_np x64

ヘッダー ファイル<intrin.h>

解説

_InterlockedCompareExchange128 組み込みでは、128 ビットのロックされた比較および交換を実行する (lock プレフィックスの付いた) cmpxchg16b 命令が生成されます。 AMD 64 ビット ハードウェアの初期バージョンでは、この命令はサポートされていません。 cmpxchg16b 命令のハードウェア サポートを確認するには、InfoType=0x00000001 (standard function 1)__cpuid 組み込みを呼び出します。 命令がサポートされている場合、CPUInfo[2] (ECX) のビット 13 は 1 になります。

Note

ComparandResult の値は常に上書きされます。 lock 命令の後、この組み込みでは、Destination の初期値が即座に ComparandResult にコピーされます。 そのため、予期しない動作を回避するために、ComparandResultDestination は別々のメモリ位置を指す必要があります。

_InterlockedCompareExchange128 は低レベルのスレッド同期に使用できますが、代わりにより小さな同期関数 (他の _InterlockedCompareExchange 組み込みなど) を使用できる場合は 128 ビットを超えて同期する必要がありません。 _InterlockedCompareExchange128 は、メモリ内の 128 ビット値にアトミック アクセスする場合に使用してください。

組み込みが使用されているコードを cmpxchg16b 命令がサポートされないハードウェアで実行すると、結果は予測できません。

ARM プラットフォームでは、クリティカル セクションの最初と最後などでの取得と解放のセマンティクスのために、_acq および _rel サフィックスの付いた組み込みを使用します。 ARM の組込み関数で _nf ("no fence") のサフィックスを持つものは、メモリ バリアとして機能しません。

組み込みに _np ("プリフェッチなし") サフィックスが付いていると、コンパイラによってプリフェッチ操作が挿入される可能性がなくなります。

このルーチンは、組み込みとしてのみ使用できます。

この例では、_InterlockedCompareExchange128 を使用して、2 つの 64 ビット整数の配列の上位ワードをその上位ワードと下位ワードの合計に置き換え、下位ワードをインクリメントします。 BigInt.Int 配列へのアクセスはアトミックですが、この例では単一のスレッドを使用し、わかりやすくするためにロックを無視しています。

// cmpxchg16b.c
// processor: x64
// compile with: /EHsc /O2
#include <stdio.h>
#include <intrin.h>

typedef struct _LARGE_INTEGER_128 {
    __int64 Int[2];
} LARGE_INTEGER_128, *PLARGE_INTEGER_128;

volatile LARGE_INTEGER_128 BigInt;

// This AtomicOp() function atomically performs:
//   BigInt.Int[1] += BigInt.Int[0]
//   BigInt.Int[0] += 1
void AtomicOp ()
{
    LARGE_INTEGER_128 Comparand;
    Comparand.Int[0] = BigInt.Int[0];
    Comparand.Int[1] = BigInt.Int[1];
    do {
        ; // nothing
    } while (_InterlockedCompareExchange128(BigInt.Int,
                                            Comparand.Int[0] + Comparand.Int[1],
                                            Comparand.Int[0] + 1,
                                            Comparand.Int) == 0);
}

// In a real application, several threads contend for the value
// of BigInt.
// Here we focus on the compare and exchange for simplicity.
int main(void)
{
   BigInt.Int[1] = 23;
   BigInt.Int[0] = 11;
   AtomicOp();
   printf("BigInt.Int[1] = %d, BigInt.Int[0] = %d\n",
      BigInt.Int[1],BigInt.Int[0]);
}
BigInt.Int[1] = 34, BigInt.Int[0] = 12

Microsoft 固有の仕様はここまで

関連項目

コンパイラの組み込み
_InterlockedCompareExchange 組み込み関数
x86 コンパイラとの競合