vnitřní funkce _InterlockedCompareExchange128
Specifické pro Microsoft
Provede 128bitový vzájemně propojený porovnání a výměnu.
Syntaxe
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
);
Parametry
Cíl
[in, out] Ukazatel na cíl, což je pole se dvěma 64bitovými celými čísly, které se považuje za 128bitové pole. Aby nedocházelo k obecné chybě ochrany, musí být cílová data zarovnaná na 16 bajtů.
ExchangeHigh
[v] 64bitové celé číslo, které se může vyměnit s vysokou částí cíle.
ExchangeLow
[v] 64bitové celé číslo, které se může vyměnit s nízkou částí cíle.
ComparandResult
[in, out] Ukazatel na pole se dvěma 64bitovými celými čísly (považováno za 128bitové pole) pro porovnání s cílem. Ve výstupu se toto pole přepíše původní hodnotou cíle.
Vrácená hodnota
1, pokud se 128bitová srovnávací hodnota rovná původní hodnotě cíle. ExchangeHigh
a ExchangeLow
přepište 128bitový cíl.
0, pokud se porovnávaná hodnota nerovná původní hodnotě cíle. Hodnota cíle se nezmění a hodnota srovnávacího parametru se přepíše hodnotou cíle.
Požadavky
Vnitřní | Architektura |
---|---|
_InterlockedCompareExchange128 |
x64, ARM64 |
_InterlockedCompareExchange128_acq , , _InterlockedCompareExchange128_nf _InterlockedCompareExchange128_rel |
ARM64 |
_InterlockedCompareExchange128_np |
x64 |
Hlavičkový soubor<intrin.h>
Poznámky
Vnitřní _InterlockedCompareExchange128
vygeneruje cmpxchg16b
instrukce (s lock
předponou) k provedení 128bitového uzamčeného porovnání a výměny. Dřívější verze 64bitového hardwaru AMD nepodporují tuto instrukci. Chcete-li zkontrolovat podporu hardwaru cmpxchg16b
pro instrukce, zavolejte __cpuid
vnitřní s InfoType=0x00000001 (standard function 1)
. Bit 13 ( CPUInfo[2]
ECX) je 1, pokud je instrukce podporovaná.
Poznámka:
Hodnota ComparandResult
je vždy přepsána. lock
Po instrukci tento vnitřní objekt okamžitě zkopíruje počáteční hodnotu Destination
do ComparandResult
. Z tohoto důvodu by Destination
měly odkazovat na samostatná umístění paměti, ComparandResult
aby nedocházelo k neočekávanému chování.
I když můžete použít _InterlockedCompareExchange128
pro synchronizaci vláken nízké úrovně, nemusíte synchronizovat více než 128 bitů, pokud místo toho můžete použít menší synchronizační funkce (například ostatní _InterlockedCompareExchange
vnitřní funkce). Použijte _InterlockedCompareExchange128
, pokud chcete atomický přístup k 128bitové hodnotě v paměti.
Pokud spustíte kód, který používá vnitřní objekt na hardwaru, který nepodporuje cmpxchg16b
instrukce, budou výsledky nepředvídatelné.
Na platformách ARM použijte vnitřní objekty s příponami _acq
a získejte a _rel
uvolněte sémantiku, například na začátku a na konci kritické části. Vnitřní objekty ARM s příponou _nf
(bez plotu) nefungují jako paměťová bariéra.
Vnitřní objekty s příponou (bez předběžného _np
načtení) brání vložení možné operace předběžného načtení kompilátorem.
Tato rutina je k dispozici pouze jako vnitřní.
Příklad
Tento příklad používá _InterlockedCompareExchange128
k nahrazení vysokého slova pole se dvěma 64bitovými celými čísly součtem jeho vysokých a nízkých slov a zvýšením nízkého slova. Přístup k BigInt.Int
poli je atomický, ale tento příklad používá jedno vlákno a ignoruje uzamčení pro jednoduchost.
// 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
END Microsoft Specific
Viz také
Vnitřní funkce kompilátoru
vnitřní funkce _InterlockedCompareExchange
Konflikty s kompilátorem x86