XState 컨텍스트 작업
이 문서에는 XState 컨텍스트 함수를 사용하여 스레드에서 확장된 기능을 검색하고 설정하는 방법을 보여 주는 예제가 포함되어 있습니다. 다음 예제에서는 FeatureId 2(기능 마스크 4)로 정의된 AVX(Intel Advanced Vector Extensions) 상태를 조작합니다. Intel AVX는 "Intel 고급 벡터 확장 프로그래밍 참조"에 정의되어 있으며, https://go.microsoft.com/fwlink/p/?linkid=212716에서 제공됩니다.
Windows 7 sp1:AVX API 먼저 WINDOWS 7 SP1에서 구현됩니다. SP1을 사용하는 Windows 7용 SDK는 없으므로 사용할 수 있는 헤더 및 라이브러리 파일이 없습니다. 이 경우 호출자는 이 설명서에서 필요한 함수를 선언하고 "Kernel32.dll"에 GetModuleHandle 사용하여 해당 함수에 대한 포인터를 가져와야 하며, 그 다음에 GetProcAddress호출해야 합니다.
#include <stdlib.h>
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <winerror.h>
// Windows 7 SP1 is the first version of Windows to support the AVX API.
// The value for CONTEXT_XSTATE has changed between Windows 7 and
// Windows 7 SP1 and greater.
// While the value will be correct for future SDK headers, we need to set
// this value manually when building with a Windows 7 SDK for running on
// Windows 7 SPI OS bits.
#undef CONTEXT_XSTATE
#if defined(_M_X64)
#define CONTEXT_XSTATE (0x00100040)
#else
#define CONTEXT_XSTATE (0x00010040)
#endif
// Since the AVX API is not declared in the Windows 7 SDK headers and
// since we don't have the proper libs to work with, we will declare
// the API as function pointers and get them with GetProcAddress calls
// from kernel32.dll. We also need to set some #defines.
#define XSTATE_AVX (XSTATE_GSSE)
#define XSTATE_MASK_AVX (XSTATE_MASK_GSSE)
typedef DWORD64 (WINAPI *PGETENABLEDXSTATEFEATURES)();
PGETENABLEDXSTATEFEATURES pfnGetEnabledXStateFeatures = NULL;
typedef BOOL (WINAPI *PINITIALIZECONTEXT)(PVOID Buffer, DWORD ContextFlags, PCONTEXT* Context, PDWORD ContextLength);
PINITIALIZECONTEXT pfnInitializeContext = NULL;
typedef BOOL (WINAPI *PGETXSTATEFEATURESMASK)(PCONTEXT Context, PDWORD64 FeatureMask);
PGETXSTATEFEATURESMASK pfnGetXStateFeaturesMask = NULL;
typedef PVOID (WINAPI *LOCATEXSTATEFEATURE)(PCONTEXT Context, DWORD FeatureId, PDWORD Length);
LOCATEXSTATEFEATURE pfnLocateXStateFeature = NULL;
typedef BOOL (WINAPI *SETXSTATEFEATURESMASK)(PCONTEXT Context, DWORD64 FeatureMask);
SETXSTATEFEATURESMASK pfnSetXStateFeaturesMask = NULL;
VOID
PrintThreadAvxState (
__in HANDLE hThread
)
{
PVOID Buffer;
PCONTEXT Context;
DWORD ContextSize;
DWORD64 FeatureMask;
DWORD FeatureLength;
ULONG Index;
BOOL Success;
PM128A Xmm;
PM128A Ymm;
// If this function was called before and we were not running on
// at least Windows 7 SP1, then bail.
if (pfnGetEnabledXStateFeatures == (PGETENABLEDXSTATEFEATURES)-1)
{
_tprintf(_T("This needs to run on Windows 7 SP1 or greater.\n"));
return;
}
// Get the addresses of the AVX XState functions.
if (pfnGetEnabledXStateFeatures == NULL)
{
HMODULE hm = GetModuleHandle(_T("kernel32.dll"));
if (hm == NULL)
{
pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)-1;
_tprintf(_T("GetModuleHandle failed (error == %d).\n"), GetLastError());
return;
}
pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)GetProcAddress(hm, "GetEnabledXStateFeatures");
pfnInitializeContext = (PINITIALIZECONTEXT)GetProcAddress(hm, "InitializeContext");
pfnGetXStateFeaturesMask = (PGETXSTATEFEATURESMASK)GetProcAddress(hm, "GetXStateFeaturesMask");
pfnLocateXStateFeature = (LOCATEXSTATEFEATURE)GetProcAddress(hm, "LocateXStateFeature");
pfnSetXStateFeaturesMask = (SETXSTATEFEATURESMASK)GetProcAddress(hm, "SetXStateFeaturesMask");
if (pfnGetEnabledXStateFeatures == NULL
|| pfnInitializeContext == NULL
|| pfnGetXStateFeaturesMask == NULL
|| pfnLocateXStateFeature == NULL
|| pfnSetXStateFeaturesMask == NULL)
{
pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)-1;
_tprintf(_T("This needs to run on Windows 7 SP1 or greater.\n"));
return;
}
}
FeatureMask = pfnGetEnabledXStateFeatures();
if ((FeatureMask & XSTATE_MASK_AVX) == 0)
{
_tprintf(_T("The AVX feature is not enabled.\n"));
return;
}
ContextSize = 0;
Success = pfnInitializeContext(NULL,
CONTEXT_ALL | CONTEXT_XSTATE,
NULL,
&ContextSize);
if ((Success == TRUE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
{
_tprintf(_T("Unexpected result from InitializeContext (success == %d, error == %d).\n"),
Success,
GetLastError());
}
Buffer = malloc(ContextSize);
if (Buffer == NULL)
{
_tprintf(_T("Out of memory.\n"));
return;
}
Success = pfnInitializeContext(Buffer,
CONTEXT_ALL | CONTEXT_XSTATE,
&Context,
&ContextSize);
if (Success == FALSE)
{
_tprintf(_T("InitializeContext failed (error == %d).\n"), GetLastError());
goto Cleanup;
}
Success = pfnSetXStateFeaturesMask(Context, XSTATE_MASK_AVX);
if (Success == FALSE)
{
_tprintf(_T("SetXStateFeaturesMask failed (error == %d).\n"), GetLastError());
goto Cleanup;
}
Success = GetThreadContext(hThread, Context);
// Note: Thread state may not be accurate. For best results, suspend
// the thread and use the CONTEXT_EXCEPTION_REQUEST flags prior to
// calling GetThreadContext.
if (Success == FALSE)
{
_tprintf(_T("GetThreadContext failed (error == %d).\n"), GetLastError());
goto Cleanup;
}
Success = pfnGetXStateFeaturesMask(Context, &FeatureMask);
if (Success == FALSE)
{
_tprintf(_T("GetXStateFeatureMask failed (error == %d).\n"), GetLastError());
goto Cleanup;
}
//
// The AVX feature consists of 8 (x86) or 16 (x64) 256-bit Ymm registers.
// The lower 128 bits share storage with the corresponding Xmm (SSE)
// registers and the high 128 bits are denoted by Ymm_H0 - Ymm_Hn.
//
if ((FeatureMask & XSTATE_MASK_AVX) == 0)
{
_tprintf(_T("AVX is in the INIT state (YMM_H registers are all zero).\n"));
goto Cleanup;
}
Xmm = (PM128A)pfnLocateXStateFeature(Context, XSTATE_LEGACY_SSE, &FeatureLength);
Ymm = (PM128A)pfnLocateXStateFeature(Context, XSTATE_AVX, NULL);
//
// Print values in the YMM registers.
//
for (Index = 0; Index < FeatureLength / sizeof(Xmm[0]); Index += 1)
{
_tprintf(_T("Ymm%d: %I64d %I64d %I64d %I64d\n"),
Index,
Xmm[Index].Low,
Xmm[Index].High,
Ymm[Index].Low,
Ymm[Index].High);
}
Cleanup:
free(Buffer);
return;
}
관련 항목