__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
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. |