Sdílet prostřednictvím


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