Поделиться через


встроенные функции _InterlockedCompareExchange128

Блок, относящийся только к системам Майкрософт

Выполняет 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-разрядным полем) для сравнения с назначением. В выходных данных этот массив перезаписывается с исходным значением назначения.

Возвращаемое значение

1, если 128-битное сравнение равно исходному значению назначения. ExchangeHigh и ExchangeLow перезапись 128-разрядного назначения.

Значение 0, если сравниваемое значение не равно исходному значению назначения. Значение назначения не изменяется, а значение сравнения перезаписывается со значением назначения.

Требования

Intrinsic Архитектура
_InterlockedCompareExchange128 x64, ARM64
_InterlockedCompareExchange128_acq, , _InterlockedCompareExchange128_nf_InterlockedCompareExchange128_rel ARM64
_InterlockedCompareExchange128_np x64

Файл<заголовка intrin.h>

Замечания

Встроенные _InterlockedCompareExchange128 функции создают cmpxchg16b инструкцию (с lock префиксом) для выполнения 128-разрядного заблокированного сравнения и обмена. Ранние версии оборудования AMD 64-разрядной версии не поддерживают эту инструкцию. Чтобы проверить поддержку оборудования для инструкции cmpxchg16b , вызовите встроенную __cpuid функцию InfoType=0x00000001 (standard function 1). Бит 13 из CPUInfo[2] (ECX) равен 1, если инструкция поддерживается.

Примечание.

Значение ComparandResult всегда перезаписывается. После инструкции lock эта встроенная функция немедленно копирует начальное значение Destination ComparandResultв . По этой причине следует Destination указывать на отдельные расположения памяти, ComparandResult чтобы избежать непредвиденного поведения.

Хотя вы можете использовать _InterlockedCompareExchange128 для низкоуровневой синхронизации потоков, вам не нужно синхронизировать более 128 бит, если вместо этого можно использовать небольшие функции синхронизации (например, другие _InterlockedCompareExchange встроенные компоненты). Используйте _InterlockedCompareExchange128 , если требуется атомарный доступ к 128-разрядному значению в памяти.

Если вы запускаете код, использующий встроенную функцию на оборудовании, которое не поддерживает инструкцию cmpxchg16b , результаты непредсказуемы.

На платформах ARM используются встроенные функции с суффиксами _acq и _rel для получения и освобождения семантики, например, в начале и конце критической секции. Встроенные компоненты ARM с суффиксом _nf (без ограждения) не действуют в качестве барьера памяти.

Встроенные функции с суффиксом _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

Завершение блока, относящегося только к системам Майкрософт

См. также

Встроенные компоненты компилятора
встроенные функции _InterlockedCompareExchange
Конфликты с 32-разрядным (x86) компилятором