⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 memorytestimpl.cpp

📁 获得多核硬件所有的相关信息。汇编源代码。Visual Studio2003、2005环境皆可。速度快。
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        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 + -