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