_InterlockedCompareExchange128

Microsoft Specific

Performs a 128-bit interlocked compare and exchange.

unsigned char _InterlockedCompareExchange128(
      __int64 volatile * Destination,
      __int64 ExchangeHigh,
      __int64 ExchangeLow,
      __int64 * ComparandResult
);

Parameters

  • [in, out] Destination
    Pointer to the destination, which is an array of two 64-bit integers considered as a 128-bit field.

  • [in] ExchangeHigh
    A 64-bit integer that may be exchanged with the high part of the destination.

  • [in] ExchangeLow
    A 64-bit integer that may be exchanged with the low part of the destination.

  • [in, out] ComparandResult
    Pointer to an array of two 64-bit integers (considered as a 128-bit field) to compare with the destination. On output, this is overwritten with the original value of the destination.

Return Value

1 if the 128-bit comparand equals the original value of the destination. The ExchangeHigh/ExchangeLow pair overwrites the 128-bit destination.

0 if the comparand does not equal the original value of the destination. The value of the destination is unchanged and the value of the comparand is overwritten with the value of the destination.

Requirements

Intrinsic

Architecture

_InterlockedCompareExchange128

x64

Header file <intrin.h>

Remarks

This intrinsic generates the cmpxchg16b instruction (with the lock prefix) to perform a 128-bit locked compare and exchange. Early versions of AMD 64-bit hardware do not support this instruction. To check for hardware support for the cmpxchg16b instruction, call the __cpuid intrinsic with InfoType=0x00000001 (standard function 1). Bit 13 of CPUInfo[2] (ECX); will be 1 if the instruction is supported.

Although you could use _InterlockedCompareExchange128 for simple low-level thread synchronization, you might want to use the other _InterlockedCompareExchange intrinsics instead. There is no reason to synchronize over 128 bits if you can use smaller synchronization functions. Use this intrinsic if you want atomic access to a 128-bit value in memory.

If you run code that uses this intrinsic on hardware that does not support the cmpxchg16b instruction, the results are unpredictable.

This routine is available only as an intrinsic.

Example

This example uses _InterlockedCompareExchange128 to replace the high word of an array of two 64-bit integers with the sum of its high and low words and to increment the low word. The access to the BigInt.Int array is atomic, but we use only a single thread in this example and ignore the locking for simplicity.

// 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 would 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

END Microsoft Specific

Copyright 2007 by Advanced Micro Devices, Inc. All rights reserved. Reproduced with permission from Advanced Micro Devices, Inc.

See Also

Concepts

Compiler Intrinsics

_InterlockedCompareExchange Intrinsic Functions