Partager via


fonctions intrinsèques _InterlockedCompareExchange128

Section spécifique à Microsoft

Effectue une comparaison et un échange verrouillés 128 bits.

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
);

Paramètres

Destination
[in, out] Pointeur vers la destination, qui est un tableau de deux entiers 64 bits considérés comme un champ 128 bits. Les données de destination doivent être alignées sur 16 octets pour éviter une erreur de protection générale.

ExchangeHigh
[in] Entier 64 bits qui peut être échangé avec la partie élevée de la destination.

ExchangeLow
[in] Entier 64 bits qui peut être échangé avec la partie basse de la destination.

ComparandResult
[in, out] Pointeur vers un tableau de deux entiers 64 bits (considérés comme un champ 128 bits) à comparer avec la destination. En sortie, ce tableau est remplacé par la valeur d’origine de la destination.

Valeur retournée

1 si le comparand 128 bits est égal à la valeur d’origine de la destination. ExchangeHigh et ExchangeLow remplacez la destination 128 bits.

0 si le comparand n’est pas égal à la valeur d’origine de la destination. La valeur de la destination est inchangée et la valeur du comparand est remplacée par la valeur de la destination.

Spécifications

Intrinsic Architecture
_InterlockedCompareExchange128 x64, ARM64
_InterlockedCompareExchange128_acq, _InterlockedCompareExchange128_nf, _InterlockedCompareExchange128_rel ARM64
_InterlockedCompareExchange128_np x64

Fichier<d’en-tête intrin.h>

Notes

L’intrinsèque _InterlockedCompareExchange128 génère l’instruction cmpxchg16b (avec le lock préfixe) pour effectuer une comparaison et un échange verrouillés 128 bits. Les premières versions du matériel AMD 64 bits ne prennent pas en charge cette instruction. Pour case activée pour la prise en charge matérielle de l’instructioncmpxchg16b, appelez l’intrinsèque __cpuid avec InfoType=0x00000001 (standard function 1). Le bit 13 de CPUInfo[2] (ECX) est 1 si l’instruction est prise en charge.

Remarque

La valeur de ComparandResult est toujours remplacée. Après l’instructionlock, cette intrinsèque copie immédiatement la valeur initiale de Destination .ComparandResult Pour cette raison, ComparandResult et Destination doit pointer vers des emplacements de mémoire distincts pour éviter un comportement inattendu.

Bien que vous puissiez utiliser _InterlockedCompareExchange128 pour la synchronisation de threads de bas niveau, vous n’avez pas besoin de synchroniser plus de 128 bits si vous pouvez utiliser des fonctions de synchronisation plus petites (telles que les autres _InterlockedCompareExchange intrinsèques) à la place. Utilisez _InterlockedCompareExchange128 si vous souhaitez un accès atomique à une valeur 128 bits en mémoire.

Si vous exécutez du code qui utilise l’intrinsèque sur le matériel qui ne prend pas en charge l’instruction cmpxchg16b , les résultats sont imprévisibles.

Sur les plateformes ARM, utilisez les intrinsèques avec les suffixes _acq et _rel pour la sémantique Acquire et Release, comme au début et à la fin d'une section critique. Les intrinsèques ARM avec un _nf suffixe (« sans clôture ») ne font pas office de barrière de mémoire.

Les fonctions intrinsèques avec un suffixe _np (pour « no prefetch », « pas de prérécupération ») empêchent l'insertion par le compilateur d'une possible opération de prérécupération.

Cette routine n’est disponible qu’en tant qu’intrinsèque.

Exemple

Cet exemple utilise _InterlockedCompareExchange128 pour remplacer le mot élevé d’un tableau de deux entiers 64 bits par la somme de ses mots hauts et bas et pour incrémenter le mot bas. L’accès au BigInt.Int tableau est atomique, mais cet exemple utilise un thread unique et ignore le verrouillage par souci de simplicité.

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

FIN de la section spécifique à Microsoft

Voir aussi

Intrinsèques du compilateur
fonctions intrinsèques _InterlockedCompareExchange
Conflits avec le compilateur x86