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

См. также

Другие ресурсы

__lwpval32, __lwpval64

__lwpins32, __lwpins64

__slwpcb

Встроенные объекты LWP, добавленные в Visual Studio 2010 с пакетом обновления 1 (SP1)

Журнал изменений

Дата

Журнал

Причина

Март 2011

Добавлено это содержимое.

Изменение функции SP1.