Udostępnij za pośrednictwem


funkcje wewnętrzne _InterlockedCompareExchange128

Specyficzne dla firmy Microsoft

Wykonuje 128-bitowe porównanie i wymianę.

Składnia

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

Lokalizacja docelowa
[in, out] Wskaźnik do miejsca docelowego, który jest tablicą dwóch 64-bitowych liczb całkowitych uważanych za pole 128-bitowe. Dane docelowe muszą być wyrównane 16 bajtów, aby uniknąć ogólnego błędu ochrony.

ExchangeHigh
[in] 64-bitowa liczba całkowita, która może być wymieniana z dużą częścią miejsca docelowego.

ExchangeLow
[in] 64-bitowa liczba całkowita, która może być wymieniana z małą częścią miejsca docelowego.

ComparandResult
[in, out] Wskaźnik do tablicy dwóch 64-bitowych liczb całkowitych (uważanych za pole 128-bitowe) do porównania z miejscem docelowym. W danych wyjściowych ta tablica jest zastępowana oryginalną wartością miejsca docelowego.

Wartość zwracana

1, jeśli 128-bitowy comparand jest równa oryginalnej wartości miejsca docelowego. ExchangeHigh i ExchangeLow zastąp lokalizację docelową 128-bitową.

0, jeśli comparand nie jest równy oryginalnej wartości miejsca docelowego. Wartość miejsca docelowego jest niezmieniona, a wartość comparand jest zastępowana wartością miejsca docelowego.

Wymagania

Nieodłączny Architektura
_InterlockedCompareExchange128 x64, ARM64
_InterlockedCompareExchange128_acq, , _InterlockedCompareExchange128_nf_InterlockedCompareExchange128_rel ARM64
_InterlockedCompareExchange128_np x64

Plik<nagłówka intrin.h>

Uwagi

Funkcja wewnętrzna _InterlockedCompareExchange128 generuje instrukcję cmpxchg16b (z prefiksem lock ), aby wykonać 128-bitową blokadę porównania i wymiany. Wczesne wersje sprzętu AMD 64-bitowego nie obsługują tej instrukcji. Aby sprawdzić obsługę sprzętu instrukcji cmpxchg16b , wywołaj funkcję wewnętrzną __cpuid za pomocą polecenia InfoType=0x00000001 (standard function 1). Bit 13 CPUInfo[2] (ECX) jest 1, jeśli instrukcja jest obsługiwana.

Uwaga

Wartość ComparandResult jest zawsze zastępowana. Po instrukcji lock ta funkcja wewnętrzna natychmiast kopiuje początkową wartość Destination do ComparandResult. Z tego powodu należy wskazać oddzielne lokalizacje pamięci, ComparandResult Destination aby uniknąć nieoczekiwanego zachowania.

Chociaż można używać _InterlockedCompareExchange128 do synchronizacji wątków niskiego poziomu, nie trzeba synchronizować ponad 128 bitów, jeśli zamiast tego można używać mniejszych funkcji synchronizacji (takich jak inne _InterlockedCompareExchange funkcje wewnętrzne). Użyj _InterlockedCompareExchange128 polecenia , jeśli chcesz uzyskać dostęp niepodzielne do wartości 128-bitowej w pamięci.

Jeśli uruchamiasz kod korzystający z wewnętrznego sprzętu, który nie obsługuje cmpxchg16b instrukcji, wyniki są nieprzewidywalne.

Na platformach ARM użyj funkcji wewnętrznych z sufiksami _acq i _rel do uzyskiwania i semantyki wydania, takich jak na początku i na końcu sekcji krytycznej. Funkcje wewnętrzne arm z sufiksem _nf ("bez ogrodzenia") nie działają jako bariera pamięci.

Funkcje wewnętrzne z sufiksem _np ("brak pobierania wstępnego") uniemożliwiają wstawienie możliwej operacji pobierania wstępnego przez kompilator.

Ta rutyna jest dostępna tylko jako wewnętrzna.

Przykład

W tym przykładzie użyto _InterlockedCompareExchange128 metody , aby zastąpić wysokie słowo tablicy dwóch 64-bitowych liczb całkowitych sumą wysokich i niskich wyrazów oraz zwiększać niski wyraz. Dostęp do BigInt.Int tablicy jest niepodzielna, ale w tym przykładzie jest używany pojedynczy wątek i ignoruje blokowanie dla uproszczenia.

// 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

Zobacz też

Funkcje wewnętrzne kompilatora
funkcje wewnętrzne _InterlockedCompareExchange
Konflikty z kompilatorem x86