Compartir a través de


__llwpcb

Se requiere Visual Studio 2010 SP1.

Específicos de Microsoft

Genera la instrucción llwpcb de generación de perfiles ligera (LWP) para pasar la dirección de un bloque de control de generación de perfiles ligera (LWPCB) al hardware LWP y habilitar o deshabilitar la generación de perfiles ligera.

void __llwpcb(
   void *pcbaddress
);

Parámetros

  • [in] pcbaddress
    Cero o un puntero a un bloque de control LWP.

Valor devuelto

Ninguno.

Requisitos

Intrínseco

Arquitectura

__llwpcb

LWP

Archivo de encabezado <intrin.h>

Comentarios

Esta característica genera un código que habilita o deshabilita la generación de perfiles ligera. La generación de perfiles ligera se registra para un determinado hardware seleccionado por el usuario o los eventos de software en un búfer de anillo en el espacio de usuario. El bloque de control LWP selecciona los eventos que se van a grabar y describe el búfer de anillo. El muestreo y la escritura de registros de evento suceden muy rápidamente, con interrupción mínima en el código de usuario. Cuando el búfer de anillo se encuentra casi completo, el hardware puede generar una interrupción para activar el código que procesa las entradas en el búfer de anillo. Para obtener información detallada acerca de la generación de perfiles ligera, vea la publicación sobre la especificación de generación de perfiles ligera de AMD (publicación número 43724).

Cuando el parámetro pcbaddress señala a un bloque de control LWP válido, la generación de perfiles ligera se habilita como se describe en el bloque de control. Cuando pcbaddress es 0, los búferes internos LWP se vacían al búfer de anillo LWP y LWP está deshabilitado.

La instrucción llwpcb forma parte de la familia LWP de instrucciones. Las instrucciones LWP requieren la compatibilidad del hardware y del sistema operativo. Para determinar la compatibilidad del hardware para LWP, llame a __cpuid intrínseco con InfoType = 0x80000001 y compruebe el bit 15 de CPUInfo [2] (ECX). Este bit es 1 cuando el hardware admite LWP, de lo contrario es 0. Cuando sepa si el hardware admite LWP, llame a __cpuid intrínseco con InfoType = 0x8000001C y compruebe el bit 0 de CPUInfo [0] (EAX). Este bit es 1 si el sistema operativo ha establecido que LWP esté disponible, de lo contrario es 0. Si el bit es 1, habrá otra información importante disponible en CPUInfo [], tal y como se describe a continuación. Tenga en cuenta que los valores en CPUInfo [3] (EDX) representan las mismas características LWP que los valores en CPUInfo [0] (EAX), pero los valores en EDX representan la funcionalidad LWP del hardware, mientras que los valores en EAX representan las características LWP actualmente habilitadas por el sistema operativo.

CpuInfo []

Bits

Nombre del campo

Descripción

0 (EAX)

0

LwpAvail

HW y SO admiten LWP

1

LwpVAL

Instrucción LWPVAL disponible

2

LwpIRE

Las instrucciones retiraron el evento disponible

3

LwpBRE

Bifurcación retirada del evento disponible

4

LwpDME

Evento de línea no ejecutada DCache disponible

5

LwpCNH

Evento de relojes no detenidos de la CPU disponible

6

LwpRNH

Evento de relojes no detenidos de referencia de la CPU disponible

30-7

Reservado

31

LwpInt

Interrupción de desbordamiento de umbral disponible

1 (EBX)

7-0

LwpCbSize

Tamaño de LWPCB en palabras cuádruples

15-8

LwpEventSize

Tamaño de un registro de eventos del búfer de anillo en bytes

23-16

LwpMaxEvents

Máximo valor Eventid admitido (no incluye 255)

31-24

LwpEventOffset

Desplazamiento en bytes del campo EventInterval1 desde el inicio de LWPCB. Siempre un múltiplo de 8.

2 (ECX)

4-0

LwpLatencyMax

El número de bits en contadores de latencia de memoria caché

5

LwpDataAddress

1 si el evento de línea no ejecutada de la caché graba la dirección de los datos del informe o falta la referencia

8-6

LwpLatencyRnd

Bits por los que se redondea (0 a 4) la latencia de la memoria caché

15-9

LwpVersion

Versión de implementación LWP

23-16

LwpMinBufferSize

El tamaño mínimo del búfer de anillo de LWP, en unidades de 32*EventSize

Ejemplo

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

Vea también

Otros recursos

__lwpval32, __lwpval64

__lwpins32, __lwpins64

__slwpcb

Intrínsecos LWP agregados para Visual Studio 2010 SP1

Historial de cambios

Fecha

Historial

Motivo

Marzo de 2011

Se agrega este contenido.

Cambio de características de SP1.