📄 memorytestimpl.cpp
字号:
//---------------------------------------------------------------------------
//
// MemoryTestImpl.cpp: CMemoryTest Class Implementation
//
//---------------------------------------------------------------------------
#include "StdAfx.h"
#include "MemoryTestImpl.h"
const char* szTestNames[] =
{
"Microarchitecture - Memory Bandwidth",
"Microarchitecture - D-Cache Latency",
"Microarchitecture - Memory Walk",
"Microarchitecture - D-Cache Bandwidth",
"Microarchitecture - D-Cache Arrival",
"Microarchitecture - Decode Bandwidth",
"Microarchitecture - I-Cache Latency",
"Microarchitecture - I-ROB",
"Microarchitecture - D-TLB",
"Microarchitecture - I-TLB",
"RAM Performance - Stream",
"RAM Performance - Checksum",
"RAM Performance - Substring Search",
"RAM Stability"
};
// Thread and event handles
HANDLE hThread[32];
// Default thread function
DWORD WINAPI ThreadFunc(void* lpParam)
{
// Wait for the exit condition
while (WaitForSingleObject(hThread[0], 0) != WAIT_OBJECT_0)
{
__asm pause;
}
// Exit the thread
return 0;
}
// Message queue processing
void __fastcall CMemoryTest::ProcessMessages()
{
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
{
break;
}
if (msg.message == WM_SIZE)
{
Graph.Resize();
}
if (msg.message == WM_KEYDOWN)
{
if (msg.wParam == VK_ESCAPE)
{
IsTerminatePending = true;
}
}
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
}
// Log file output
void __fastcall CMemoryTest::UpdateLogFile(char* pString)
{
FILE* fp = fopen("stability.log", "at");
if (fp)
{
fputs(pString, fp);
fclose(fp);
}
}
//***************************************************************************
// LoggedSetLockPagesPrivilege: a function to obtain, if possible, or
// release the privilege of locking physical pages.
//
// Inputs:
//
// HANDLE hProcess: Handle for the process for which the
// privilege is needed
//
// BOOL bEnable: Enable (TRUE) or disable?
//
// Return value: TRUE indicates success, FALSE failure.
//
//***************************************************************************
BOOL __fastcall CMemoryTest::LoggedSetLockPagesPrivilege(HANDLE hProcess, BOOL bEnable, char* pError)
{
struct
{
DWORD Count;
LUID_AND_ATTRIBUTES Privilege[1];
} Info;
HANDLE Token;
BOOL Result;
// Runtime link to ADVAPI32.DLL
PTOpenProcessToken OpenProcessToken =
(PTOpenProcessToken)::GetProcAddress(::GetModuleHandle("advapi32"), "OpenProcessToken");
if (! OpenProcessToken)
{
if (pError) strcpy(pError, "OpenProcessToken() entry point not found (no OS support).");
return FALSE;
}
// @WARNING: explicitly using ANSI version
PTLookupPrivilegeValue LookupPrivilegeValue =
(PTLookupPrivilegeValue)::GetProcAddress(::GetModuleHandle("advapi32"), "LookupPrivilegeValueA");
if (! LookupPrivilegeValue)
{
if (pError) strcpy(pError, "LookupPrivilegeValue() entry point not found (no OS support).");
return FALSE;
}
PTAdjustTokenPrivileges AdjustTokenPrivileges =
(PTAdjustTokenPrivileges)::GetProcAddress(::GetModuleHandle("advapi32"), "AdjustTokenPrivileges");
if (! AdjustTokenPrivileges)
{
if (pError) strcpy(pError, "AdjustTokenPrivileges() entry point not found (no OS support).");
return FALSE;
}
// Open the token.
Result = OpenProcessToken(hProcess,
TOKEN_ADJUST_PRIVILEGES,
&Token);
if (Result != TRUE)
{
if (pError) strcpy(pError, "Cannot open process token.");
return FALSE;
}
// Enable or disable?
Info.Count = 1;
if (bEnable)
{
Info.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
}
else
{
Info.Privilege[0].Attributes = 0;
}
// Get the LUID.
Result = LookupPrivilegeValue(NULL,
SE_LOCK_MEMORY_NAME,
&(Info.Privilege[0].Luid));
if (Result != TRUE)
{
if (pError) sprintf(pError, "Cannot get privilege value for %s.", SE_LOCK_MEMORY_NAME);
return FALSE;
}
// Adjust the privilege.
Result = AdjustTokenPrivileges(Token, FALSE,
(PTOKEN_PRIVILEGES)&Info,
NULL, NULL, NULL);
// Check the result.
if (Result != TRUE)
{
if (pError) sprintf(pError, "Cannot adjust token privileges, error %u.", ::GetLastError());
return FALSE;
}
else
{
if (::GetLastError() != ERROR_SUCCESS)
{
if (pError) strcpy(pError, "Cannot enable SE_LOCK_MEMORY privilege, please check the local policy.");
return FALSE;
}
}
::CloseHandle(Token);
return TRUE;
}
void __fastcall CMemoryTest::SetBlockPointers(DWORD SegmentsCount)
{
// Finding the closest 1MB offset for each segment
DWORD off;
if (SegmentsCount <= 2)
{
off = MAX_MEMORY_BLOCK_SIZE >> 1;
}
else if (SegmentsCount <= 4)
{
off = MAX_MEMORY_BLOCK_SIZE >> 2;
}
else if (SegmentsCount <= 8)
{
off = MAX_MEMORY_BLOCK_SIZE >> 3;
}
else if (SegmentsCount <= 16)
{
off = MAX_MEMORY_BLOCK_SIZE >> 4;
}
else if (SegmentsCount <= 32)
{
off = MAX_MEMORY_BLOCK_SIZE >> 5;
}
else
{
off = MAX_MEMORY_BLOCK_SIZE >> 6;
}
for (DWORD l = 1; l < SegmentsCount; ++l)
{
ptr[l] = (DWORD *)(DWORD(ptr[l - 1]) + off);
}
}
void __fastcall CMemoryTest::SetMemoryFunc(DWORD PrefetchDistance)
{
switch (TestData.RegisterType)
{
case RT_64_BIT_MMX:
{
WriteMem = (TestData.UseNonTemporalStore) ?
&WriteMMX_NT :
&WriteMMX;
if ((PrefetchDistance > 0) ||
(TestData.PrefetchType == PT_BLOCK_PREFETCH_1) ||
(TestData.PrefetchType == PT_BLOCK_PREFETCH_2))
{
switch (TestData.PrefetchType)
{
case PT_PREFETCHNTA:
{
switch (TestData.LogStrideSize[0])
{
case 4:
ReadMem = &ReadMMX_PFNTA_16;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFNTA_16_NT :
&CopyMMX_PFNTA_16;
break;
case 5:
ReadMem = &ReadMMX_PFNTA_32;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFNTA_32_NT :
&CopyMMX_PFNTA_32;
break;
case 6:
default:
ReadMem = &ReadMMX_PFNTA_64;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFNTA_64_NT :
&CopyMMX_PFNTA_64;
break;
case 7:
ReadMem = &ReadMMX_PFNTA_128;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFNTA_128_NT :
&CopyMMX_PFNTA_128;
break;
case 8:
ReadMem = &ReadMMX_PFNTA_256;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFNTA_256_NT :
&CopyMMX_PFNTA_256;
break;
case 9:
ReadMem = &ReadMMX_PFNTA_512;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFNTA_512_NT :
&CopyMMX_PFNTA_512;
break;
}
break;
}
case PT_PREFETCHT0:
{
switch (TestData.LogStrideSize[0])
{
case 4:
ReadMem = &ReadMMX_PFT0_16;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT0_16_NT :
&CopyMMX_PFT0_16;
break;
case 5:
ReadMem = &ReadMMX_PFT0_32;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT0_32_NT :
&CopyMMX_PFT0_32;
break;
case 6:
default:
ReadMem = &ReadMMX_PFT0_64;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT0_64_NT :
&CopyMMX_PFT0_64;
break;
case 7:
ReadMem = &ReadMMX_PFT0_128;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT0_128_NT :
&CopyMMX_PFT0_128;
break;
case 8:
ReadMem = &ReadMMX_PFT0_256;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT0_256_NT :
&CopyMMX_PFT0_256;
break;
case 9:
ReadMem = &ReadMMX_PFT0_512;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT0_512_NT :
&CopyMMX_PFT0_512;
break;
}
break;
}
case PT_PREFETCHT1:
{
switch (TestData.LogStrideSize[0])
{
case 4:
ReadMem = &ReadMMX_PFT1_16;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT1_16_NT :
&CopyMMX_PFT1_16;
break;
case 5:
ReadMem = &ReadMMX_PFT1_32;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT1_32_NT :
&CopyMMX_PFT1_32;
break;
case 6:
default:
ReadMem = &ReadMMX_PFT1_64;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT1_64_NT :
&CopyMMX_PFT1_64;
break;
case 7:
ReadMem = &ReadMMX_PFT1_128;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT1_128_NT :
&CopyMMX_PFT1_128;
break;
case 8:
ReadMem = &ReadMMX_PFT1_256;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT1_256_NT :
&CopyMMX_PFT1_256;
break;
case 9:
ReadMem = &ReadMMX_PFT1_512;
CopyMem = (TestData.UseNonTemporalStore) ?
&CopyMMX_PFT1_512_NT :
&CopyMMX_PFT1_512;
break;
}
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -