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