Partager via


__llwpcb

Visual Studio 2010 SP1 est requis

Spécifique à Microsoft

Génère le llwpcb de l'instruction du profilage léger (LWP) pour transmettre l'adresse d'un bloc de contrôle du profilage léger (LWPCB) au matériel LWP et activer ou désactiver le profilage léger.

void __llwpcb(
   void *pcbaddress
);

Paramètres

  • [in] pcbaddress
    Zéro ou un pointeur à un bloc du contrôle LWP.

Valeur de retour

Aucun

Configuration requise

Intrinsèque

Architecture

__llwpcb

LWP

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

Notes

Cet intrinsèque génère le code qui active ou désactive le profilage léger. Le profilage léger écrit les enregistrements pour certains événements matériel et logiciel sélectionnés par l'utilisateur dans une mémoire tampon de l'anneau de l'espace de l'utilisateur. Le bloc de contrôle LWP sélectionne les événements à enregistrer et décrit la mémoire tampon de l'anneau. Les enregistrements de l'événement d'échantillonnage et d'écriture se produisent très rapidement, avec une interruption minimale du code utilisateur. Lorsque la mémoire tampon de l'anneau est presque saturée, le matériel peut générer une interruption pour activer le code qui traite les entrées dans la mémoire tampon de l'anneau. Pour plus d'informations sur le profilage LWP, consultez « Spécification du profilage LWP (Lightweight Profiling) d'AMD » (Numéro de publication 43724) (éventuellement en anglais).

Lorsque le paramètre pcbaddress pointe sur un bloc du contrôle LWP valide, le profilage léger est activé comme décrit par le bloc de contrôle. Lorsque pcbaddress a la valeur 0, les mémoires tampons internes LWP sont vidées de la mémoire tampon d'anneau LWP et LWP est désactivé.

L'instruction llwpcb fait partie de la famille LWP des instructions. Les instructions LWP requièrent à la fois une prise en charge du matériel et du système d'exploitation. Pour déterminer la prise en charge du matériel de LWP, appelez la fonction intrinsèque __cpuid avec InfoType = 0x80000001 et vérifiez le bit 15 de CPUInfo[2] (ECX). Ce bit est égal à 1 lorsque LWP est pris en charge par le matériel, sinon il est égal à 0. Dès que vous savez que LWP est pris en charge par le matériel, appelez la fonction intrinsèque __cpuid avec InfoType = 0x8000001C et vérifiez le bit 0 de CPUInfo [0] (EAX). Ce bit est égal à 1 si le système d'exploitation a mis LWP à disposition, sinon il est égal à 0. Si le bit est 1, d'autres informations importantes sont disponibles dans CPUInfo [], comme décrit ci-dessous. Notez que les valeurs dans CPUInfo [3] (EDX) représentent les mêmes fonctions LWP que celles dans CPUInfo [0] (EAX), mais les valeurs dans EDX représentent les fonctions LWP du matériel, tandis que les valeurs dans EAX représentent les fonctionnalités LWP actuellement activées par le système d'exploitation.

CpuInfo[]

Bits

Nom du champ

Description

0 (EAX)

0

LwpAvail

LWP est pris en charge par le matériel et le système d'exploitation

1

LwpVAL

Instruction LWPVAL disponible

2

LwpIRE

Instructions retirées, événement disponible

3

LwpBRE

Branche retirée, événement disponible

4

LwpDME

Échec DCache, événement disponible

5

LwpCNH

Horloges UC non interrompues, événement disponible

6

LwpRNH

Horloges de référence UC non interrompues, événement disponible

30-7

Réservé.

31

LwpInt

Interruption du dépassement de capacité du seuil disponible

1 (EBX)

7-0

LwpCbSize

Taille LWPCB en mots quadruples

15-8

LwpEventSize

Taille d'un enregistrement d'événement de la mémoire tampon de l'anneau en octets

23-16

LwpMaxEvents

Valeur Eventid maximale prise en charge (255 non compris)

31-24

LwpEventOffset

Offset en octets du champ EventInterval1 à partir du début de LWPCB. Toujours un multiple de 8.

2 (ECX)

4-0

LwpLatencyMax

Nombre de bits dans les compteurs de la latence du cache

5

LwpDataAddress

1 si l'événement d'échec de l'accès au cache enregistre l'adresse des données du rapport de la référence manquante

8-6

LwpLatencyRnd

Bits utilisés pour arrondir la latence du cache (0 à 4)

15-9

LwpVersion

Version d'implémentation LWP

23-16

LwpMinBufferSize

Taille minimum de la mémoire tampon d'anneau LWP, en unités de 32*EventSize

Exemple

#include <intrin.h>
#include <stdio.h>

#define MAX_EVENTS 6
#define LWPEVENTSIZE 32
#define BUFFERSIZE 4096

struct lwpEventRecord {
    unsigned __int64 EventId : 8;
    unsigned __int64 CoreId : 8;
    unsigned __int64 Flags : 16;
    unsigned __int64 Data1 : 32;
    unsigned __int64 InstructionAddress;
    unsigned __int64 Data2;
    unsigned __int64 Reserved;
};

struct lwpEventRecord ringBuffer[BUFFERSIZE];

struct lwpcb0 {
    unsigned __int64 Flags : 32;
    unsigned __int64 BufferSize : 28;
    unsigned __int64 Random : 4;
};

struct lwpcbEvent {
    unsigned __int64 EventInterval : 26;
    unsigned __int64 EIReserved1 : 6;
    unsigned __int64 EventCounter : 26;
    unsigned __int64 EIReserved2 : 6;

};

struct lwpcbStruct {
    unsigned __int64 Flags : 32;
    unsigned __int64 BufferSize : 28;
    unsigned __int64 Random : 4;

    unsigned __int64 BufferBase;

    unsigned __int64 BufferHeadOffset : 32;
    unsigned __int64 Reserved1 : 32;

    unsigned __int64 MissedEvents;

    unsigned __int64 Threshold : 32;
    unsigned __int64 Filters : 32;

    unsigned __int64 BaseIP;

    unsigned __int64 LimitIP;

    unsigned __int64 Reserved2;

    unsigned __int64 BufferTailOffset : 32;
    unsigned __int64 Reserved3 : 32;

    unsigned __int64 Reserved4[7];

    struct lwpcbEvent Events[MAX_EVENTS]; // event 1 == index 0
} myLWPCBStruct;

__m128d data[100];

extern void __cpuid(int *CPUInfo, int InfoType);
// Return 1 if LWP is supported by the hardware
int LwpSupported()
{
    int cpuInfo[4] = {0};
    __cpuid(cpuInfo, 0x80000001);
    if (cpuInfo[2] & (1 << 15)) return 1;
    else return 0;
}

// Return 1 if LWP is enabled by the OS
// Assumes LWP is supported by the hardware
int LwpAvailable()
{
    int cpuInfo[4] = {0};
    __cpuid(cpuInfo, 0x8000001C);
    if (cpuInfo[0] & 1) return 1;
    else return 0;
}

// Return 1 if LWPVAL instruction is supported by this hardware
// Assumes LWP is supported by the hardware
int LwpvalSupported()
{
    int cpuInfo[4] = {0};
    __cpuid(cpuInfo, 0x8000001C);
    if (cpuInfo[3] & (1 << 1)) return 1;
    else return 0;
}

// Return 1 if LWPVAL instruction is enabled by the OS
// Assumes LWPVAL is supported by the hardware
int LwpvalAvailable()
{
    int cpuInfo[4] = {0};
    __cpuid(cpuInfo, 0x8000001C);
    if (cpuInfo[3] & (1 << 1)) return 1;
    else return 0;
}

void
initializeLWPCB(struct lwpcbStruct *p)
{
    int i, lwpvalok;
    unsigned __int64 *dummy;
    p->Flags =  0; // disable HW counters & threshold interrupts
    p->BufferSize = sizeof(ringBuffer)/sizeof(struct lwpEventRecord);
    p->BufferSize *= sizeof(struct lwpEventRecord);
    p->Random = 0; // No randomness in counters
    p->BufferBase = (unsigned __int64)&ringBuffer[0];
    /// Value of BufferHeadOffset here is arbitrary
    p->BufferHeadOffset = p->BufferSize -
                          3*sizeof(struct lwpEventRecord);
    p->MissedEvents = 0;
    p->Threshold = 2*p->BufferSize; // don't want threshold interrupts
    p->Filters = 0; // shouldn't matter for this test
    p->BaseIP = 0; // shouldn't matter for this test
    p->LimitIP = 0; // shouldn't matter for this test
    p->BufferTailOffset = p->BufferHeadOffset; // ring buffer empty
    p->Reserved1 = p->Reserved2 = p->Reserved3 = 0;
    for (i = 0; i < 7; i++) p->Reserved4[i] = 0;
    for (i = 0; i < MAX_EVENTS; i++) {
        p->Events[i-1].EventInterval = 0;
        p->Events[i-1].EIReserved1 = 0;
        p->Events[i-1].EventCounter = 0;
        p->Events[i-1].EIReserved2 = 0;
    }
    if (LwpvalSupported() && LwpvalAvailable()) {
        p->Flags |= 2; // Count LWPVAL events
        p->Events[0].EventInterval = 9; // count every 10th LWPVAL
    }
}
#define LOOPSIZE 31
main()
{
    int i;
    __m128d temp;
    double sum = 0;
    struct lwpcbstruct *plwpcb;
    unsigned int tailOffset, headOffset, bufferSize, bufferCapacity;
    unsigned int headRecord, tailRecord;
    int headMinusTail;
    unsigned int recordSize = sizeof(struct lwpEventRecord);
    unsigned int numEntries;
    unsigned int lwpvalCount, lwpinsCount;

    if (!LwpSupported()) {
        printf("LWP is not supported by this hardware\n");
        exit(1);
    }
    if (!LwpAvailable()) {
        printf("OS has not made LWP available\n");
        exit(1);
    }
#if defined(_M_X64)
    printf("64-bit compiler\n");
#else
    printf("32-bit compiler\n");
#endif
    initializeLWPCB(&myLWPCBStruct);
    __llwpcb(&myLWPCBStruct);
    plwpcb = __slwpcb();
    if ((unsigned __int64)plwpcb != (unsigned __int64)&myLWPCBStruct) {
        printf("Test failed: bad return from __slwpcb()\n");
        exit(1);
    }

    if (LwpvalSupported() && LwpvalAvailable()) {
        for (i = 0; i < LOOPSIZE; i ++) {
            if (i % 7 == 0) __lwpins32(0xdeadbeef, i, 0x01234567); 
            __lwpval32(0x0badf00d, i, 0xcad00cad);
        }
#if defined(_M_X64)
        for (i = 0; i < LOOPSIZE; i ++) {
            if (i % 7 == 0) __lwpins64(0xdeadbeefdeadbeefll, i, 0x01234567); 
            __lwpval64(0x0badf00d0badf00dll, i, 0xcad00cad);
        }
#endif
    } else {
        if (!LwpvalSupported()) {
            printf("LWPVAL instruction not supported by the hardware\n");
        } else if (!LwpvalAvailable()) {
            printf("LWPVAL instruction not enabled\n");
        }
        for (i = 0; i < LOOPSIZE; i ++) {
            if (i % 7 == 0) __lwpins32(0xdeadbeef, i, 0x01234567); 
        }
#if defined(_M_X64)
        for (i = 0; i < LOOPSIZE; i ++) {
            if (i % 7 == 0) __lwpins64(0xdeadbeefdeadbeefll, i, 0x01234567); 
        }
#endif
    }

    plwpcb = __slwpcb();

    tailOffset = myLWPCBStruct.BufferTailOffset;
    headOffset = myLWPCBStruct.BufferHeadOffset;
    bufferSize = myLWPCBStruct.BufferSize;
    bufferCapacity = bufferSize / recordSize;

    headMinusTail = headOffset;
    headMinusTail -= tailOffset;
    if (tailOffset <= headOffset) numEntries = headMinusTail;
    else numEntries = headMinusTail + bufferSize;
    numEntries /= recordSize;

    tailRecord = tailOffset / recordSize;
    headRecord = headOffset / recordSize;
    printf("%d entries in ring buffer\n", numEntries);

    lwpvalCount = lwpinsCount = 0;
    for (i = tailRecord; i != headRecord; i = (i + 1)%bufferCapacity) {
        switch(ringBuffer[i].EventId) {
            case 1:
                lwpvalCount += 1;
                break;
            case 255:
                lwpinsCount += 1;
                break;
            default:
                printf("WARNING: bad EventId %d in ring buffer\n", 
                        ringBuffer[i].EventId);
                break;
        }
    }
    printf("%d LWPVAL instructions, %d LWPINS instructions\n",
            lwpvalCount, lwpinsCount);
}
      

Voir aussi

Autres ressources

__lwpval32, __lwpval64

__lwpins32, __lwpins64

__slwpcb

Fonctions LWP intrinsèques ajoutées pour Visual Studio 2010 SP1

Historique des modifications

Date

Historique

Motif

Mars 2011

Ce contenu a été ajouté.

Modifications de fonctionnalités dans le SP1.