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

📄 resourcemanager.cpp

📁 C语言库函数的原型,有用的拿去
💻 CPP
📖 第 1 页 / 共 5 页
字号:
// ==++==
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// ResourceManager.cpp
//
// Implementation of IResourceManager.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

#include "concrtinternal.h"
#include <float.h>
#include <algorithm>

namespace Concurrency
{
    /// <summary>
    ///     Returns the OS version.
    /// </summary>
    _CRTIMP IResourceManager::OSVersion GetOSVersion()
    {
        return ::Concurrency::details::ResourceManager::Version();
    }

    /// <summary>
    ///     Returns an interface that represents the singleton resource manager instance. The API references the
    ///     resource manager, and must be matched by a call to IResourceManager::Release(), when the caller is done.
    /// </summary>
    _CRTIMP IResourceManager* CreateResourceManager()
    {
        return ::Concurrency::details::ResourceManager::CreateSingleton();
    }

    /// <summary>
    ///     The number of hardware threads on the underlying machine is returned here.
    /// </summary>
    _CRTIMP unsigned int GetProcessorCount()
    {
        return ::Concurrency::details::ResourceManager::GetCoreCount();
    }

    /// <summary>
    ///     The number of NUMA nodes or processor packages on the underlying machine is returned here.
    ///     If the processor contains more NUMA nodes than processor packages, the number of NUMA nodes
    ///     is returned, otherwise the number of packages is returned.
    /// </summary>
    _CRTIMP unsigned int GetProcessorNodeCount()
    {
        return ::Concurrency::details::ResourceManager::GetNodeCount();
    }

    /// <summary>
    ///     Returns an identifier for a scheduler. Before calling an API with an IScheduler interface as a parameter,
    ///     an identifier must be obtained for the scheduler using this API.
    /// </summary>
    _CRTIMP unsigned int GetSchedulerId()
    {
        return ::Concurrency::details::ResourceManager::GetSchedulerId();
    }

    /// <summary>
    ///     Returns an identifier for an execution context. Before calling an API with an IExecutionContext interface as a parameter,
    ///     an identifier must be obtained for the execution context using this API.
    /// </summary>
    _CRTIMP unsigned int GetExecutionContextId()
    {
        return ::Concurrency::details::ResourceManager::GetExecutionContextId();
    }
}

namespace Concurrency
{
namespace details
{
    // Static counters to generate unique identifiers.
    volatile LONG ResourceManager::s_schedulerIdCount = -1L;
    volatile LONG ResourceManager::s_executionContextIdCount = -1L;
    volatile LONG ResourceManager::s_threadProxyIdCount = -1L;

    // Operating system characteristics.
    unsigned int ResourceManager::s_physicalProcessorCount = 0;
    unsigned int ResourceManager::s_packageCount = 0;
    unsigned int ResourceManager::s_nodeCount = 0;
    IResourceManager::OSVersion ResourceManager::s_version = IResourceManager::UnsupportedOS;
    bool ResourceManager::s_fNativeX64 = false;
    bool ResourceManager::s_fRequireUMSWorkaround = false;

    volatile LONG ResourceManager::s_terminating = 0;

    ResourceManager *ResourceManager::s_pResourceManager = NULL;

    // Variables used to obtain information about the topology of the system.
    DWORD ResourceManager::s_logicalProcessorInformationLength = 0;
    PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ResourceManager::s_pSysInfo = NULL;

    // The encoded pointer to the SetThreadGroupAffinity function used for Win7 and higher
    HardwareAffinity::PFnSetThreadGroupAffinity HardwareAffinity::s_pfnSetThreadGroupAffinity = NULL;

    // The encoded pointer to the GetThreadGroupAffinity function used for Win7 and higher
    HardwareAffinity::PFnGetThreadGroupAffinity HardwareAffinity::s_pfnGetThreadGroupAffinity = NULL;

    // The encoded pointer to the GetCurrentProcessorNumberEx function used for Win7 and higher
    ResourceManager::PFnGetCurrentProcessorNumberEx ResourceManager::s_pfnGetCurrentProcessorNumberEx = NULL;

    /// <summary>
    ///     Constructs a hardware affinity from a given thread.
    /// </summary>
    HardwareAffinity::HardwareAffinity(HANDLE hThread)
    {
        memset(&m_affinity, 0, sizeof(m_affinity));
        if (::Concurrency::GetOSVersion() == ::Concurrency::IResourceManager::Win7OrLater ||
            ::Concurrency::GetOSVersion() == ::Concurrency::IResourceManager::UmsThreadAwareOS)
        {
            PFnGetThreadGroupAffinity fnDecodedFunction = (PFnGetThreadGroupAffinity) Security::DecodePointer(s_pfnGetThreadGroupAffinity);
            VERIFY(fnDecodedFunction(hThread, &m_affinity));
        }
        else
        {
            // On operating systems older than Win7, we don't have access to the correct information about thread's affinity,
            // so we will assume that the affinity is that of the process.
            DWORD_PTR pProcessAffinityMask;
            DWORD_PTR pSystemAffinityMask;

            GetProcessAffinityMask(GetCurrentProcess(), &pProcessAffinityMask, &pSystemAffinityMask);
            m_affinity.Group = 0;
            m_affinity.Mask = pProcessAffinityMask;
        }
    }

    /// <summary>
    ///     Applies this hardware affinity to a thread.
    /// </summary>
    /// <param name="hThread">
    ///     The thread handle to which to apply this affinity.
    /// </param>
    void HardwareAffinity::ApplyTo(HANDLE hThread)
    {
        if (::Concurrency::GetOSVersion() == ::Concurrency::IResourceManager::Win7OrLater || 
            ::Concurrency::GetOSVersion() == ::Concurrency::IResourceManager::UmsThreadAwareOS)
        {
            PFnSetThreadGroupAffinity fnDecodedFunction = (PFnSetThreadGroupAffinity) Security::DecodePointer(s_pfnSetThreadGroupAffinity);
            VERIFY(fnDecodedFunction(hThread, &m_affinity, NULL));
        }
        else
        {
            VERIFY(SetThreadAffinityMask(hThread, m_affinity.Mask));
        }
    }

    /// <summary>
    ///     Called to initialize the SetThreadGroupAffinity function
    /// </summary>
    void HardwareAffinity::InitializeSetThreadGroupAffinityFn()
    {
        // Get the SetThreadGroupAffinity function for Win7
        PFnSetThreadGroupAffinity pfnSetFunction = (PFnSetThreadGroupAffinity) GetProcAddress(GetModuleHandleW(L"kernel32.dll"), 
                                                                                              "SetThreadGroupAffinity");

        PFnGetThreadGroupAffinity pfnGetFunction = (PFnGetThreadGroupAffinity) GetProcAddress(GetModuleHandleW(L"kernel32.dll"),
                                                                                              "GetThreadGroupAffinity");

        if (pfnSetFunction == NULL || pfnGetFunction == NULL)
        {
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
        }

        s_pfnSetThreadGroupAffinity = (PFnSetThreadGroupAffinity) Security::EncodePointer(pfnSetFunction);
        s_pfnGetThreadGroupAffinity = (PFnGetThreadGroupAffinity) Security::EncodePointer(pfnGetFunction);
    }

    /// <summary>
    ///     Returns the OS version.
    /// </summary>
    IResourceManager::OSVersion ResourceManager::Version()
    {
        if (s_version == ::Concurrency::IResourceManager::UnsupportedOS)
        {
            { // begin locked region
                _StaticLock::_Scoped_lock lock(s_lock);
                if (s_version == ::Concurrency::IResourceManager::UnsupportedOS)
                {
                    InitializeSystemInformation();
                }
            } // end locked region
        }
        return s_version;
    }

    /// <summary>
    ///     Returns the number of nodes (processor packages or NUMA nodes, whichever is greater)
    /// </summary>
    unsigned int ResourceManager::GetNodeCount()
    {
        if (s_nodeCount == 0)
        {
            { // begin locked region
                _StaticLock::_Scoped_lock lock(s_lock);
                if (s_nodeCount == 0)
                {
                    InitializeSystemInformation();
                }
            } // end locked region
        }
        return (s_nodeCount >= s_packageCount) ? s_nodeCount : s_packageCount;
    }

    /// <summary>
    ///     Returns the number of cores.
    /// </summary>
    unsigned int ResourceManager::GetCoreCount()
    {
        if (s_physicalProcessorCount == 0)
        {
            { // begin locked region
                _StaticLock::_Scoped_lock lock(s_lock);
                if (s_physicalProcessorCount == 0)
                {
                    InitializeSystemInformation();
                }
            } // end locked region
        }
        return s_physicalProcessorCount;
    }

    /// <summary>
    ///     Returns the current thread's node id and core id (relative to that node).
    /// </summary>
    unsigned int ResourceManager::GetCurrentNodeAndCore(unsigned int * pCore)
    {
        if (::Concurrency::GetOSVersion() == ::Concurrency::IResourceManager::Win7OrLater || 
            ::Concurrency::GetOSVersion() == ::Concurrency::IResourceManager::UmsThreadAwareOS)
        {
            // For Win7 or later, we can use a simple function
            PROCESSOR_NUMBER procNum;
            PFnGetCurrentProcessorNumberEx fnDecodedFunction = (PFnGetCurrentProcessorNumberEx) Security::DecodePointer(s_pfnGetCurrentProcessorNumberEx);

            fnDecodedFunction(&procNum);

            DWORD processorNumber = procNum.Number;
            ULONG_PTR processorAffinity = 1 << processorNumber;

            for (unsigned int nodeIndex = 0; nodeIndex < m_nodeCount; nodeIndex++)
            {
                GlobalNode * pNode = &m_pGlobalNodes[nodeIndex];
                if ((pNode->m_processorGroup == procNum.Group) && ((pNode->m_nodeAffinity & processorAffinity) != 0))
                {
                    for (unsigned int coreIndex = 0; coreIndex < pNode->m_coreCount; coreIndex++)
                    {
                        if (pNode->m_pCores[coreIndex].m_processorNumber == processorNumber)
                        {
                            if (pCore != NULL)
                            {
                                *pCore = coreIndex;
                            }
                            return nodeIndex;
                        }
                    }
                }
            }

            ASSERT(UNREACHED);
            return 0;
        }
        else if (::Concurrency::GetOSVersion() == ::Concurrency::IResourceManager::Win2k3 ||
            ::Concurrency::GetOSVersion() == ::Concurrency::IResourceManager::Vista)
        {
            // For Win2k3 or Vista, we need to compute the node id and core id from the absolute processor id
            typedef DWORD (WINAPI *PFnGetCurrentProcessorNumber)(VOID);
            PFnGetCurrentProcessorNumber pFnGetCurrentProcessorNumber
                = (PFnGetCurrentProcessorNumber) GetProcAddress(GetModuleHandleW(L"kernel32.dll"), 
                                                                     "GetCurrentProcessorNumber");

            if (pFnGetCurrentProcessorNumber == NULL)
            {
                throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
            }

            DWORD processorNumber = pFnGetCurrentProcessorNumber();
            ULONG_PTR processorAffinity = 1 << processorNumber;

            for (unsigned int nodeIndex = 0; nodeIndex < m_nodeCount; nodeIndex++)
            {
                GlobalNode * pNode = &m_pGlobalNodes[nodeIndex];
                if ((pNode->m_nodeAffinity & processorAffinity) != 0)
                {
                    for (unsigned int coreIndex = 0; coreIndex < pNode->m_coreCount; coreIndex++)
                    {
                        if (pNode->m_pCores[coreIndex].m_processorNumber == processorNumber)
                        {
                            if (pCore != NULL)
                            {
                                *pCore = coreIndex;
                            }
                            return nodeIndex;
                        }
                    }
                }
            }

            ASSERT(UNREACHED);
            return 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -