Funções intrínsecas _InterlockedCompareExchange128
Seção específica da Microsoft
Executa uma comparação e troca interconectada de 128 bits.
Sintaxe
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
);
Parâmetros
Destino
[in, out] Ponteiro para o destino, que é uma matriz de dois inteiros de 64 bits considerado como um campo de 128 bits. Os dados de destino precisam estar alinhados a 16 bytes para evitar uma falha de proteção geral.
ExchangeHigh
[in] Um inteiro de 64 bits que pode ser trocado com a parte alta do destino.
ExchangeLow
[in] Um inteiro de 64 bits que pode ser trocado com a parte baixa do destino.
ComparandResult
[in, out] Ponteiro para uma matriz de dois inteiros de 64 bits (considerado um campo de 128 bits) para comparar com o destino. Na saída, essa matriz é substituída com o valor original do destino.
Valor retornado
1 se a comparação de 128 bits for igual ao valor original do destino. ExchangeHigh
e ExchangeLow
substituem o destino de 128 bits.
0 se o comparand não for igual ao valor original do destino. O valor do destino é inalterado e o comparand é substituído com o valor do destino.
Requisitos
Intrinsic | Arquitetura |
---|---|
_InterlockedCompareExchange128 |
x64, ARM64 |
_InterlockedCompareExchange128_acq , _InterlockedCompareExchange128_nf , _InterlockedCompareExchange128_rel |
ARM64 |
_InterlockedCompareExchange128_np |
x64 |
Arquivo de cabeçalho<intrin.h>
Comentários
O intrínseco _InterlockedCompareExchange128
gera a instrução cmpxchg16b
(com o prefixo lock
) para executar uma comparação e troca bloqueada em 128 bits. As versões iniciais do hardware AMD de 64 bits não dão suporte a esta instrução. Para verificar se há suporte de hardware para a instrução cmpxchg16b
, chame o intrínseco __cpuid
com InfoType=0x00000001 (standard function 1)
. O bit 13 de CPUInfo[2]
(ECX) será 1 se a instrução for compatível.
Observação
O valor de ComparandResult
é sempre substituído. Após a instrução lock
, esse intrínseco copia imediatamente o valor inicial de Destination
para ComparandResult
. Por esse motivo, ComparandResult
e Destination
deve apontar para locais de memória separados para evitar um comportamento inesperado.
Embora você possa usar _InterlockedCompareExchange128
para sincronização de thread de nível baixo, não será necessário sincronizar mais de 128 bits se você puder usar funções de sincronização menores (como os outros intrínsecos _InterlockedCompareExchange
). Use _InterlockedCompareExchange128
se você quiser acesso atômico a um valor de 128 bits na memória.
Se você executar código que usa o intrínseco em hardware que não dá suporte à instrução cmpxchg16b
, os resultados serão imprevisíveis.
Em plataformas ARM, use intrínsecos com os sufixos _acq
e _rel
para semântica de aquisição e liberação, como no início e no final de uma seção crítica. Os intrínsecos de ARM com um sufixo _nf
("no fence") não funcionam como uma barreira de memória.
Intrínsecos com um sufixo _np
("no prefetch") impedem que uma possível operação de pré-busca seja inserida pelo compilador.
Essa rotina só está disponível como intrínseca.
Exemplo
Este exemplo usa _InterlockedCompareExchange128
para substituir a palavra alta de uma matriz de dois inteiros de 64 bits pela soma de suas palavras altas e baixas e incrementar a palavra baixa. O acesso à matriz BigInt.Int
é atômico, mas este exemplo usa apenas um thread e ignora o bloqueio para simplificar.
// 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
Fim da seção específica da Microsoft
Confira também
Intrínsecos do compilador
Funções intrínsecas _InterlockedCompareExchange
conflitos com o compilador x86