встроенные функции _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) компилятором