_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] 指向目标的指针,它是两个 64 位整数的数组,被视为 128 位字段。 目标数据必须对齐 16 字节,以避免出现常规保护错误。

ExchangeHigh
[in] 可与目标高部分交换的 64 位整数。

ExchangeLow
[in] 可与目标低部分交换的 64 位整数。

ComparandResult
[in,out] 指向两个 64 位整数(被视为 128 位字段)的数组的指针,用于跟目标比较。 在输出中,此数组被目标的原始值覆盖。

返回值

如果 128 位比较数与目标的原始值相等,则为 1。 ExchangeHighExchangeLow 覆盖 128 位目标。

如果比较数不等于目标的原始值,则为 0。 目标的值不变,比较数的值将被目标的值覆盖。

要求

Intrinsic 体系结构
_InterlockedCompareExchange128 x64、ARM64
_InterlockedCompareExchange128_acq, _InterlockedCompareExchange128_nf, _InterlockedCompareExchange128_rel ARM64
_InterlockedCompareExchange128_np x64

头文件<intrin.h>

备注

_InterlockedCompareExchange128 内部函数生成前缀为 lockcmpxchg16b 指令,以执行 128 位锁定比较和交换。 AMD 64 位硬件的早期版本不支持此指令。 若要检查 cmpxchg16b 指令的硬件支持,请使用 InfoType=0x00000001 (standard function 1) 调用 __cpuid 内部函数。 如果支持指令,则 13 位 CPUInfo[2] (ECX) 为 1。

注意

ComparandResult 始终被覆盖。 指令 lock 后,此内部函数会立即将初始值 Destination 复制到 ComparandResult。 因此,ComparandResultDestination 应指向单独的内存位置以避免意外行为。

尽管 _InterlockedCompareExchange128 可用于低级线程同步,但如果可以使用较小的同步函数(比如另一个 _InterlockedCompareExchange 内部函数),则无需同步超过 128 位。 如果要在内存中对 128 位值进行原子访问,请使用 _InterlockedCompareExchange128

如果在不支持 cmpxchg16b 指令的硬件上运行使用内部函数的代码,则结果是不可预测的。

在 ARM 平台上,可以使用带 _acq_rel 后缀的内部函数获取和发布语义,例如在临界区的起始位置。 带 _nf(“无围墙”)后缀的 ARM 内部函数不能充当内存屏障。

_np(“无预取”)后缀的函数可以阻止编译器插入可能的预取操作。

此例程仅可用作内部函数。

示例

此示例使用 _InterlockedCompareExchange128 将两个 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 编译器冲突