__llwpcb

Visual Studio 2010 SP1 wird benötigt.

Microsoft-spezifisch

Generiert die LWP-Anweisung (einfache Profilerstellung) llwpcb, um die Adresse eines einfachen Profilerstellungskontrollblocks (LWPCB) an die LWP-Hardware zu übergeben und die einfache Profilerstellung zu aktivieren oder zu deaktivieren.

void __llwpcb(
   void *pcbaddress
);

Parameter

  • [in] pcbaddress
    0 (null) oder ein Zeiger auf einen LWP-Kontrollblock.

Rückgabewert

Keine.

Anforderungen

Intrinsisch

Architektur

__llwpcb

LWP

Headerdatei <intrin.h>

Hinweise

Diese systeminterne Funktion generiert Code, der die einfache Profilerstellung aktiviert oder deaktiviert. Die einfache Profilerstellung schreibt Datensätze für bestimmte vom Benutzer ausgewählte Hardware oder Softwareereignisse in einen Ringpuffer im Benutzerbereich. Der LWP-Kontrollblock wählt die aufzuzeichnenden Ereignisse aus und beschreibt den Ringpuffer. Sampling- und Schreibereignisdatensätze werden sehr schnell geschehen, mit minimaler Beeinträchtigung des Benutzercodes. Wenn der Ringpuffer beinahe voll ist, kann die Hardware einen Interrupt generieren, um Code zu aktivieren, in dem die Einträge im Ringpuffer verarbeitet werden. Ausführliche Informationen zur einfachen Profilerstellung finden Sie unter AMD "Einfache Profilerstellungsspezifikation (Publikation Number 43724)".

Wenn der Parameter pcbaddress auf einen gültigen LWP-Kontrollblock zeigt, wird die einfache Profilerstellung wie im Kontrollblock beschrieben aktiviert. Wenn pcbaddress 0 (null) ist, werden die internen LWP-Puffer in den LWP-Ringpuffer geleert, und LWP wird deaktiviert.

Die llwpcb-Anweisung ist Teil der LWP-Anweisungsfamilie. Die LWP-Anweisungen erfordern sowohl Hardware- als auch Betriebssystemunterstützung. Um die Hardwareunterstützung für LWP zu bestimmen, rufen Sie die systeminterne Funktion __cpuid mit InfoType = 0x80000001 auf, und prüfen Sie Bit 15 von CPUInfo[2] (ECX). Dieses Bit ist 1, wenn LWP von der Hardware unterstützt wird, und andernfalls 0. Sobald bekannt ist, dass LWP von der Hardware unterstützt wird, rufen Sie die systeminterne Funktion __cpuid mit InfoType = 0x8000001C auf, und überprüfen Sie Bit 0 von CPUInfo[0] (EAX). Dieses Bit ist 1, wenn das Betriebssystem LWP verfügbar gemacht hat, andernfalls 0. Wenn das Bit 1 ist, sind andere wichtige Informationen in CPUInfo[] verfügbar, wie unten beschrieben. Beachten Sie, dass die Werte in CPUInfo[3] (EDX) die gleichen LWP-Funktionen wie in CPUInfo[0] (EAX) darstellen, aber die Werte in EDX stellen die LWP-Funktionen der Hardware dar, während die Werte in EAX die derzeit im Betriebssystem aktivierten LWP-Funktionen darstellen.

CpuInfo[]

Bits

Feldname

Beschreibungen

0 (EAX)

0

LwpAvail

LWP wird von HW und Betriebssystem unterstützt

1

LwpVAL

LWPVAL-Anweisung verfügbar

2

LwpIRE

Ereignis für zurückgezogene Anweisungen verfügbar

3

LwpBRE

Ereignis für deaktivierte Verzweigung verfügbar

4

LwpDME

DCache Auslassungsereignis verfügbar

5

LwpCNH

Ereignis für nicht angehaltenen CPU-Takt verfügbar

6

LwpRNH

Ereignis für nicht angehaltenen CPU-Referenztakt verfügbar

30-7

Reserviert.

31

LwpInt

Interrupt für Schwellenwertüberlauf verfügbar

1 (EBX)

7-0

LwpCbSize

Größe von LWPCB in Vierfachwörtern

15-8

LwpEventSize

Größe eines Ringpufferereignisdatensatzes in Bytes

23-16

LwpMaxEvents

Maximaler Eventid-Wert unterstützt (exklusive 255)

31-24

LwpEventOffset

Offset in Bytes von EventInterval1-Feld von Start von LWPCB. Immer ein Vielfache von 8.

2 (ECX)

4-0

LwpLatencyMax

Anzahl von Bits in Cachewartezeitindikatoren

5

LwpDataAddress

1, wenn Datensätze für Cachefehlerereignisse die Datenadresse des fehlenden Verweises melden

8-6

LwpLatencyRnd

Bits, um die die Cachelatenz gerundet wird (0 bis 4)

15-9

LwpVersion

Version der LWP-Implementierung

23-16

LwpMinBufferSize

Minimale Größe des LWP-Ringpuffers, in Einheiten von 32*EventSize

Beispiel

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

Siehe auch

Weitere Ressourcen

__lwpval32, __lwpval64

__lwpins32, __lwpins64

__slwpcb

In Visual Studio 2010 SP1 hinzugefügte systeminterne LWP-Funktionen

Änderungsprotokoll

Datum

Versionsgeschichte

Grund

März 2011

Diesen Inhalt hinzugefügt.

SP1-Funktionsänderung.