📄 memorytestimpl.cpp
字号:
ptr[0] = (DWORD *)((DWORD(lpMemReserved) + 4092) & DWORD(-4096L));
// Page-lock memory
if (! ::VirtualLock((void *)ptr[0], MAX_MEMORY_BLOCK_SIZE))
{
DWORD err = ::GetLastError();
if (pError) sprintf(pError, "VirtualLock() failed, error %u.", err);
return HRESULT_FROM_WIN32(err);
}
break;
}
case MA_AWE:
{
BOOL bResult;
// Runtime-link to the AWE functions in KERNEL32.DLL
PTAllocateUserPhysicalPages AllocateUserPhysicalPages =
(PTAllocateUserPhysicalPages)::GetProcAddress(::GetModuleHandle("kernel32"),
"AllocateUserPhysicalPages");
if (! AllocateUserPhysicalPages)
{
if (pError) strcpy(pError, "AllocateUserPhysicalPages() entry point not found\n"
"(no OS support for AWE).");
return E_FAIL;
}
PTMapUserPhysicalPages MapUserPhysicalPages =
(PTMapUserPhysicalPages)::GetProcAddress(::GetModuleHandle("kernel32"),
"MapUserPhysicalPages");
if (! MapUserPhysicalPages)
{
if (pError) strcpy(pError, "MapUserPhysicalPages() entry point not found\n"
"(no OS support for AWE).");
return E_FAIL;
}
// Enable the privilege.
if (! LoggedSetLockPagesPrivilege(::GetCurrentProcess(), TRUE, pError))
{
return E_FAIL;
}
// Calculate the number of pages of memory to request.
NumberOfPages = MAX_MEMORY_RESERVED_SIZE / sSysInfo.dwPageSize;
// Calculate the size of the user PFN array.
PFNArraySize = NumberOfPages * sizeof(ULONG_PTR);
aPFNs = (ULONG_PTR *)::HeapAlloc(::GetProcessHeap(), 0, PFNArraySize);
if (aPFNs == NULL)
{
DWORD err = ::GetLastError();
if (pError) sprintf(pError, "HeapAlloc() failed, error %u.", err);
return HRESULT_FROM_WIN32(err);
}
// Allocate the physical memory.
NumberOfPagesInitial = NumberOfPages;
bResult = AllocateUserPhysicalPages(::GetCurrentProcess(),
&NumberOfPages,
aPFNs);
if (! bResult)
{
DWORD err = ::GetLastError();
if (pError) sprintf(pError, "Cannot allocate physical pages, error %u.", err);
return HRESULT_FROM_WIN32(err);
}
if (NumberOfPagesInitial != NumberOfPages)
{
if (pError) sprintf(pError, "Allocated only %u physical pages of %u requested.", NumberOfPages, NumberOfPagesInitial);
return E_OUTOFMEMORY;
}
// Reserve the virtual memory.
lpMemReserved = ::VirtualAlloc(NULL,
MAX_MEMORY_RESERVED_SIZE,
MEM_RESERVE | MEM_PHYSICAL,
PAGE_READWRITE);
if (! lpMemReserved)
{
DWORD err = ::GetLastError();
if (pError) sprintf(pError, "VirtualAlloc() failed to reserve memory, error %u.", err);
return HRESULT_FROM_WIN32(err);
}
// Map the physical memory into the window.
bResult = MapUserPhysicalPages(lpMemReserved,
NumberOfPages,
aPFNs);
if (! bResult)
{
DWORD err = ::GetLastError();
if (pError) sprintf(pError, "MapUserPhysicalPages() failed to map, error %u.", err);
return HRESULT_FROM_WIN32(err);
}
// main aligned pointer to the allocated memory
ptr[0] = (DWORD *)((DWORD(lpMemReserved) + 4092) & DWORD(-4096L));
break;
}
}
} __finally {
if (sSysInfo.dwNumberOfProcessors > 1)
{
// Reset the main thread affinity mask
::SetThreadAffinityMask(::GetCurrentThread(), (1 << sSysInfo.dwNumberOfProcessors) - 1);
}
}
return S_OK;
}
HRESULT __stdcall CMemoryTest::SetPriority(DWORD dwCpuIndex)
{
// Set the highest priority for the process
if (! ::SetPriorityClass(::GetCurrentProcess(), REALTIME_PRIORITY_CLASS))
{
return HRESULT_FROM_WIN32(::GetLastError());
}
// Set the highest priority for the main thread
if (! ::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL))
{
return HRESULT_FROM_WIN32(::GetLastError());
}
if (sSysInfo.dwNumberOfProcessors > 1)
{
// Set a thread affinity mask to allow the thread run on the N-th processor.
if (! ::SetThreadAffinityMask(::GetCurrentThread(), 1 << dwCpuIndex))
{
return HRESULT_FROM_WIN32(::GetLastError());
}
}
::Sleep(DEF_SLEEP_TIME);
return S_OK;
}
HRESULT __stdcall CMemoryTest::Lock(DWORD dwCpuIndex)
{
if (sSysInfo.dwNumberOfProcessors < 2)
{
return S_FALSE;
}
// Create the main event in the signaled state
hThread[0] = ::CreateEvent(NULL, // pointer to security attributes
TRUE, // flag for manual-reset event
FALSE, // flag for initial state
NULL); // pointer to event-object name
if (! hThread[0])
{
return HRESULT_FROM_WIN32(::GetLastError());
}
DWORD j = 0; // Index of starting CPU to "Lock"
// Create aux threads
for (DWORD i = 1; i < sSysInfo.dwNumberOfProcessors; ++i)
{
DWORD dwThreadId;
hThread[i] = ::CreateThread(NULL, // pointer to thread security attributes
0, // initial thread stack size, in bytes
&ThreadFunc, // pointer to thread function
NULL, // argument for new thread
CREATE_SUSPENDED, // creation flags
&dwThreadId); // pointer to returned thread identifier
if (! hThread[i])
{
return HRESULT_FROM_WIN32(::GetLastError());
}
// Set the highest thread priority
if (! ::SetThreadPriority(hThread[i], THREAD_PRIORITY_TIME_CRITICAL))
{
return HRESULT_FROM_WIN32(::GetLastError());
}
// Set the thread affininty mask to run on an j-th CPU
if (j == dwCpuIndex)
{
++j; // skip the active CPU
}
if (! ::SetThreadAffinityMask(hThread[i], 1 << j))
{
return HRESULT_FROM_WIN32(::GetLastError());
}
++j; // increment the CPU index
// Resume the thread
::ResumeThread(hThread[i]);
::Sleep(DEF_SLEEP_TIME);
}
return S_OK;
}
HRESULT __stdcall CMemoryTest::ResetPriority()
{
if (sSysInfo.dwNumberOfProcessors > 1)
{
// Reset the main thread affinity mask
::SetThreadAffinityMask(::GetCurrentThread(), (1 << sSysInfo.dwNumberOfProcessors) - 1);
}
// Reset the main thread priority
::SetPriorityClass(::GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
// Reset the process priority
::SetThreadPriority(::GetCurrentThread(), THREAD_PRIORITY_NORMAL);
::Sleep(DEF_SLEEP_TIME);
return S_OK;
}
HRESULT __stdcall CMemoryTest::Unlock()
{
if (sSysInfo.dwNumberOfProcessors < 2)
{
return S_FALSE;
}
// Set the main event to signaled state
if (hThread[0])
{
::SetEvent(hThread[0]);
}
// Wait for aux threads to exit
while (::WaitForMultipleObjects(sSysInfo.dwNumberOfProcessors - 1, &hThread[1], TRUE, 100) != WAIT_OBJECT_0)
;
// Close threads and event handles
for (DWORD i = 0; i < sSysInfo.dwNumberOfProcessors; ++i)
{
::CloseHandle(hThread[i]);
}
return S_OK;
}
HRESULT __stdcall CMemoryTest::Terminate(MEMORYALLOCATION memAlloc, char* pError)
{
LatencyFunc.Terminate();
HRESULT hr = S_OK;
BOOL bResult;
switch (memAlloc)
{
case MA_STANDARD:
{
// Is memory allocated?
if (lpMemReserved)
{
// Deallocate memory
free(lpMemReserved);
lpMemReserved = NULL;
}
break;
}
case MA_VIRTUALLOCK:
{
// Is memory allocated?
if (lpMemReserved)
{
// Page-unlock memory
bResult = ::VirtualUnlock((void *)ptr[0], MAX_MEMORY_BLOCK_SIZE);
if (! bResult)
{
DWORD err = ::GetLastError();
if (pError) sprintf(pError, "VirtualUnlock() failed, error %u.", err);
hr = HRESULT_FROM_WIN32(err);
}
// Decommit virtual memory.
bResult = ::VirtualFree(lpMemReserved,
MAX_MEMORY_RESERVED_SIZE,
MEM_DECOMMIT);
if (! bResult)
{
DWORD err = ::GetLastError();
if (pError) sprintf(pError, "VirtualFree() failed, error %u.", err);
hr = HRESULT_FROM_WIN32(err);
}
// Free virtual memory.
bResult = ::VirtualFree(lpMemReserved,
0,
MEM_RELEASE);
if (! bResult)
{
DWORD err = ::GetLastError();
if (pError) sprintf(pError, "VirtualFree() failed, error %u.", err);
hr = HRESULT_FROM_WIN32(err);
}
lpMemReserved = NULL;
// Reset the process working set size
if (! ::SetProcessWorkingSetSize(::GetCurrentProcess(),
dwMinimumWorkingSetSize,
dwMaximumWorkingSetSize))
{
DWORD err = ::GetLastError();
if (pError) sprintf(pError, "SetProcessWorkingSetSize() failed, error %u.", err);
hr = HRESULT_FROM_WIN32(err);
}
}
break;
}
case MA_AWE:
{
// Is memory allocated?
if (lpMemReserved)
{
// Run-time link to the AWE functions in KERNEL32.DLL
PTMapUserPhysicalPages MapUserPhysicalPages =
(PTMapUserPhysicalPages)::GetProcAddress(::GetModuleHandle("kernel32"),
"MapUserPhysicalPages");
if (! MapUserPhysicalPages)
{
if (pError) strcpy(pError, "MapUserPhysicalPages() entry point not found\n"
"(no OS support for AWE).");
hr = E_FAIL;
}
PTFreeUserPhysicalPages FreeUserPhysicalPages =
(PTFreeUserPhysicalPages)::GetProcAddress(::GetModuleHandle("kernel32"),
"FreeUserPhysicalPages");
if (! FreeUserPhysicalPages)
{
if (pError) strcpy(pError, "FreeUserPhysicalPages() entry point not found\n"
"(no OS support for AWE).");
hr = E_FAIL;
}
// unmap
if (MapUserPhysicalPages)
{
bResult = MapUserPhysicalPages(lpMemReserved,
NumberOfPages,
NULL);
if (! bResult)
{
DWORD err = ::GetLastError();
if (pError) sprintf(pError, "MapUserPhysicalPages() failed to unmap, error %u.", err);
hr = HRESULT_FROM_WIN32(err);
}
}
// Free the physical pages.
if (FreeUserPhysicalPages)
{
bResult = FreeUserPhysicalPages(::GetCurrentProcess(),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -