__llwpcb
Требуется Visual Studio 2010 с пакетом обновления 1 (SP1).
Только для систем Microsoft
Формирует инструкцию облегченного профилирования (LWP) llwpcb для передачи адреса управляющего блока облегченного профилирования (LWPCB) аппаратному обеспечению LWP и включения или отключения облегченного профилирования.
void __llwpcb(
void *pcbaddress
);
Параметры
- [входящий] pcbaddress
Нуль или указатель на управляющий блок LWP.
Возвращаемое значение
Отсутствует.
Требования
Встроенный объект |
Архитектура |
---|---|
__llwpcb |
LWP |
Файл заголовка <intrin.h>
Заметки
Эта встроенная инструкция формирует код, включающий или отключающий облегченное профилирование. Облегченное профилирование делает записи для определенных выбранных пользователем аппаратных или программных событий в кольцевой буфер в пространстве пользователя. Управляющий блок LWP выбирает события для записи и описывает кольцевой буфер. Выборка и создание записей событий происходит очень быстро, с минимальным нарушением работы пользовательского кода. Когда кольцевой буфер приближается к заполнению, аппаратное обеспечение может сгенерировать прерывание для активации кода, обрабатывающего записи в кольцевом буфере. Подробные сведения об облегченном профилировании см в документе "Lightweight Profiling Specification" корпорации AMD (публикация № 43724).
Когда параметр pcbaddress указывает на допустимый управляющий блок LWP, облегченное профилирование включается, как описано в управляющем блоке. Когда параметр pcbaddress равен 0, внутренние буферы LWP сбрасываются в кольцевой буфер LWP и LWP отключается.
Инструкция llwpcb входит в состав семейства инструкций LWP. Инструкции LWP требуют поддержки как аппаратного обеспечения, так и операционной системы. Чтобы определить, имеется ли аппаратная поддержка LWP, вызовите встроенную инструкцию __cpuid с InfoType = 0x80000001 и проверьте бит 15 в CPUInfo[2] (ECX). Этот бит равен 1, если аппаратное обеспечение поддерживает LWP, и 0 в противном случае. Определив, что аппаратное обеспечение поддерживает LWP, вызовите встроенную инструкцию __cpuid с InfoType = 0x8000001C и проверьте бит 0 в CPUInfo[0] (EAX). Этот бит равен 1, если операционная система предоставляет LWP, и 0 в противном случае. Если бит равен 1, в CPUInfo[] будет содержаться другая важная информация, как описано ниже. Обратите внимание, что значения в CPUInfo[3] (EDX) представляют те же функции LWP, что и функции в CPUInfo[0] (EAX), однако значения EDX представляют LWP-возможности аппаратного обеспечения, тогда как значения в EAX представляют функции LWP, в настоящее время реализованные операционной системой.
CpuInfo[] |
Биты |
Имя поля |
Описание |
---|---|---|---|
0 (EAX) |
0 |
LwpAvail |
LWP поддерживается аппаратным обеспечением и ОС |
1 |
LwpVAL |
Доступна инструкция LWPVAL |
|
2 |
LwpIRE |
Доступно событие "инструкции удалены" |
|
3 |
LwpBRE |
Доступно событие "ветвление удалено" |
|
4 |
LwpDME |
Доступно событие "промах DCache" |
|
5 |
LwpCNH |
Доступно событие "такты ЦП в неприостановленном состоянии" |
|
6 |
LwpRNH |
Доступно событие "опорные такты ЦП в неприостановленном состоянии" |
|
30-7 |
Зарезервировано. |
||
31 |
LwpInt |
Доступно прерывание переполнения порога |
|
1 (EBX) |
7-0 |
LwpCbSize |
Размер LWPCB в учетверенных словах |
15-8 |
LwpEventSize |
Размер записи события в кольцевом буфере в байтах |
|
23-16 |
LwpMaxEvents |
Максимальное поддерживаемое значение Eventid (не включая 255) |
|
31-24 |
LwpEventOffset |
Смещение в байтах поля EventInterval1 от начала LWPCB. Всегда является кратным 8. |
|
2 (ECX) |
4-0 |
LwpLatencyMax |
Количество битов в счетчиках задержки кэша |
5 |
LwpDataAddress |
1, если в записях событий промахов кэша сообщается адрес данных отсутствующей ссылки |
|
8-6 |
LwpLatencyRnd |
Биты, на которые округляется задержка кэша (0–4) |
|
15-9 |
LwpVersion |
Версия реализации LWP |
|
23-16 |
LwpMinBufferSize |
Минимальный размер кольцевого буфера LWP в единицах 32*EventSize |
Пример
#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);
}
См. также
Другие ресурсы
Встроенные объекты LWP, добавленные в Visual Studio 2010 с пакетом обновления 1 (SP1)
Журнал изменений
Дата |
Журнал |
Причина |
---|---|---|
Март 2011 |
Добавлено это содержимое. |
Изменение функции SP1. |