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

📄 resourcemanager.cpp

📁 C语言库函数的原型,有用的拿去
💻 CPP
📖 第 1 页 / 共 5 页
字号:
        }
        else if (::Concurrency::GetOSVersion() == ::Concurrency::IResourceManager::XP)
        {
            // For XP, we assume everything is on one node, so affinity plays no role.
            if (pCore != NULL)
            {
                *pCore = 0;
            }
            return 0;
        }
        else
        {
            throw ::Concurrency::unsupported_os();
        }
    }

    /// <summary>
    ///     Creates the static singleton instance of the Resource Manager.
    /// </summary>
    ResourceManager* ResourceManager::CreateSingleton()
    {
        ResourceManager *pRM = NULL;

        { // begin locked region
            _StaticLock::_Scoped_lock lock(s_lock);
            if (s_pResourceManager == NULL)
            {
                pRM = new ResourceManager();
                pRM->Reference();
                s_pResourceManager = (ResourceManager*) Security::EncodePointer(pRM);
            }
            else 
            {
                pRM = (ResourceManager*) Security::DecodePointer(s_pResourceManager);
                if ( !pRM->SafeReference())
                {
                    // pRM has refcnt=0 and will be deleted as soon as the lock is released
                    pRM = new ResourceManager();
                    pRM->Reference();
                    s_pResourceManager = (ResourceManager*) Security::EncodePointer(pRM);
                }
            }
        } // end locked region

        return pRM;
    }

    /// <summary>
    ///     Constructs the resource manager.
    /// </summary>
    ResourceManager::ResourceManager() :
          m_referenceCount(0L),
          m_hDynamicRMThreadHandle(NULL),
          m_hDynamicRMEvent(NULL),
          m_dynamicRMWorkerState(Standby),
          m_maxSchedulers(16),
          m_numSchedulersNeedingNotifications(0),
          m_allocationRound(0),
          m_ppProxyData(NULL),
          m_ppGivingProxies(NULL),
          m_ppReceivingProxies(NULL),
          m_numSchedulers(0),
          m_pGlobalNodes(NULL),
          m_pSortedNodeOrder(NULL),
          m_pUMSPoller(NULL),
          m_pTransmogrificator(NULL)
    {
        PFnFlushProcessWriteBuffers pfnFunction = (PFnFlushProcessWriteBuffers)GetProcAddress(GetModuleHandleW(L"kernel32.dll"),
                                                                                              "FlushProcessWriteBuffers");
        if (pfnFunction != NULL)
        {
            m_pfnFlushProcessWriteBuffers = (PFnFlushProcessWriteBuffers) Security::EncodePointer(pfnFunction);
            m_pPageVirtualProtect = NULL;
        }
        else
        {
            m_pfnFlushProcessWriteBuffers = NULL;
            // If we're unable to find the FlushProcessorWriteBuffers entry point in kernel32.dll, we're likely on an OS
            // with version < 6000. We need to use a different mechanism to enable write buffer flushing.

            // Start by allocating a commited region of memory the size of a page.
            m_pPageVirtualProtect = (char *) VirtualAlloc(NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
            if (m_pPageVirtualProtect == NULL)
            {
                throw std::bad_alloc();
            }

            // We expect the OS to give us an allocation starting at a page boundary.
            ASSERT(((ULONG_PTR)m_pPageVirtualProtect & 0xFFF) == 0);

            *m_pPageVirtualProtect = 1;
        }

        // Initialize static information about the system asking for the the topology information to be saved
        // so we can use it right after.
        InitializeSystemInformation(true);
        DetermineTopology();

        // The dynamic RM thread is not created up front. It is created when the number of schedulers go from 1 to 2
        // In addition, once it is created, it is placed on standby if the number of schedulers goes down to 1 again.
        // The event is created here, since it could be signaled even before the thread is created.
        m_hDynamicRMEvent = CreateEventW(NULL, FALSE, FALSE, NULL);

        // Allocate common memory used for static and dynamic allocation. Buffers specific to dynamic core migration
        // are only allocated when the DRM thread is started up.
        m_ppProxyData = new AllocationData * [m_maxSchedulers];

#if defined(CONCRT_TRACING)
        // Assumes a m x n allocation.
        m_numTotalCores = m_nodeCount * m_pGlobalNodes[0].m_coreCount;
        m_drmInitialState = new GlobalCoreData[m_numTotalCores];
        memset(m_drmInitialState, 0, sizeof(GlobalCoreData) * m_numTotalCores);

        // Maintains a trace for every core removed during preprocessing.
        memset(m_preProcessTraces, 0, sizeof(PreProcessingTraceData) * 100);
        m_preProcessTraceIndex = 0;

        // Maintains a trace for each core allocation or assignment.
        memset(m_dynAllocationTraces, 0, sizeof(DynamicAllocationTraceData) * 100);
        m_dynAllocationTraceIndex = 0;
#endif
    }

    /// <summary>
    ///     This API is called by the dynamic RM worker thread when it starts up, and right after its state changed to
    ///     LoadBalance after being on Standby for a while. We need to find the existing schedulers, and discard the
    ///     statistics they have collected so far if any. Either we've never collected statistics for this scheduler before,
    ///     or too much/too little time has passed since we last collected statistics, and this information cannot be trusted.
    /// </summary>
    void ResourceManager::DiscardExistingSchedulerStatistics()
    {
        // NOTE: This routine must be called while holding m_lock.
        ASSERT(m_numSchedulers > 1);
        ASSERT(m_dynamicRMWorkerState == LoadBalance);

        SchedulerProxy * pSchedulerProxy = NULL;

        for (pSchedulerProxy = m_schedulers.First(); pSchedulerProxy != NULL; pSchedulerProxy = m_schedulers.Next(pSchedulerProxy))
        {
            // Initialize variables needed for statistics.
            unsigned int taskCompletionRate = 0, taskArrivalRate = 0;

            // Get the stored scheduler queue length.
            unsigned int numberOfTasksEnqueued = pSchedulerProxy->GetQueueLength();

            // Collect statistical information about this scheduler.
            pSchedulerProxy->Scheduler()->Statistics(&taskCompletionRate, &taskArrivalRate, &numberOfTasksEnqueued);

            // Update the queue length using the number computed by the statistics.
            pSchedulerProxy->SetQueueLength(numberOfTasksEnqueued);
        }
    }

    /// <summary>
    ///     Creates the dynamic RM worker thread and allocates memory for its use. The worker thread wakes up at
    ///     fixed intervals and load balances resources among schedulers, until it it put on standby.
    /// </summary>
    void ResourceManager::CreateDynamicRMWorker()
    {
        // NOTE: This routine is called *without* holding m_lock.
        // Set up a background thread for dynamic RM.
        m_hDynamicRMThreadHandle = LoadLibraryAndCreateThread(NULL,
                                           DEFAULTCONTEXTSTACKSIZE,
                                           DynamicRMThreadProc,
                                           this,
                                           0,
                                           NULL);

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

        // Make sure the background thread is running at the highest priority.
        if (SetThreadPriority(m_hDynamicRMThreadHandle, THREAD_PRIORITY_TIME_CRITICAL) == 0)
        {
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
        }
    }

    /// <summary>
    ///     Initialize function pointers that are only present on specific versions of the OS (Win7 or higher)
    /// <summary>
    void ResourceManager::InitializeSystemFunctionPointers()
    {
        ASSERT(s_version == ::Concurrency::IResourceManager::Win7OrLater || s_version == ::Concurrency::IResourceManager::UmsThreadAwareOS);

        HardwareAffinity::InitializeSetThreadGroupAffinityFn();

        PFnGetCurrentProcessorNumberEx pfnFunction = (PFnGetCurrentProcessorNumberEx)GetProcAddress(GetModuleHandleW(L"kernel32.dll"),
                                                                                                    "GetCurrentProcessorNumberEx");
        if (pfnFunction == NULL)
        {
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
        }
        s_pfnGetCurrentProcessorNumberEx = (PFnGetCurrentProcessorNumberEx) Security::EncodePointer(pfnFunction);
    }

    /// <summary>
    ///     Initializes static information such as os version, number of nodes and cores.
    /// </summary>
    void ResourceManager::InitializeSystemInformation(bool fSaveTopologyInfo)
    {
        SYSTEM_INFO info;

        GetSystemInfo(&info);

        s_fNativeX64 = (info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64);
        s_fRequireUMSWorkaround = false;

        OSVERSIONINFOW osvi;
        memset(&osvi, 0, sizeof(OSVERSIONINFOW));
        osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);

        if( !GetVersionExW(&osvi))
        {
            s_version = ::Concurrency::IResourceManager::UnsupportedOS;
            throw ::Concurrency::unsupported_os();
        }
        else
        {
            switch (osvi.dwMajorVersion)
            {
            case 5:
                switch (osvi.dwMinorVersion)
                {
                case 2: // Win2k3 or XP-64
                   s_version = ::Concurrency::IResourceManager::Win2k3;
                   break;
                case 1: // XP
                   s_version = ::Concurrency::IResourceManager::XP;
                   break;
                case 0: // Win2k -- unsupported
                   s_version = ::Concurrency::IResourceManager::UnsupportedOS;
                   throw ::Concurrency::unsupported_os();
                   break;
                }
                break;
            case 6: // Vista
                switch (osvi.dwMinorVersion)
                {
                case 0: 
                    s_version = ::Concurrency::IResourceManager::Vista;
                    break;
                default: // OS with > 64 core support.  Win7 is showing up as version 6.1

                    if (s_fNativeX64)
                    {
                        s_version = ::Concurrency::IResourceManager::UmsThreadAwareOS; // OS with UMS support

                        //
                        // There is a critical bug in Win7 RTM that we must work around.  This will be addressed in the next kernel update.
                        // Key off 7600 as the RTM build to detect whether we need the workaround.
                        //
#if !_NO_WIN7_WORKAROUND
                        s_fRequireUMSWorkaround = (osvi.dwBuildNumber <= 7600);
#endif // !_NO_WIN7_WORKAROUND
                    }
                    else
                    {
                        s_version = ::Concurrency::IResourceManager::Win7OrLater;
                    }
                }
                break;

            default:
                if (osvi.dwMajorVersion >= 7)
                {
                    s_version = ::Concurrency::IResourceManager::Win7OrLater;
                    if (s_fNativeX64) 
                    {
                        s_version = ::Concurrency::IResourceManager::UmsThreadAwareOS; // OS with UMS support
                    }
                }
                else
                {
                    s_version = ::Concurrency::IResourceManager::UnsupportedOS;
                    throw ::Concurrency::unsupported_os();
                }
                break;
            }
        }

        ASSERT(s_pSysInfo == NULL);

        // There is some ambiguity around the behavior of this API for OSs < Vista. Set node count to
        // 1 for these OSs, as other areas of the implementation make assumptions around this.

        if (s_version == ::Concurrency::IResourceManager::XP || s_version == ::Concurrency::IResourceManager::Win2k3)
        {
            s_packageCount = 1;
            s_nodeCount = 1;
            s_physicalProcessorCount = info.dwNumberOfProcessors;
        }
        else if (s_version == ::Concurrency::IResourceManager::Win7OrLater ||
            s_version == ::Concurrency::IResourceManager::UmsThreadAwareOS)
        {
            typedef BOOL (WINAPI *PFnGetLogicalProcessorInformationEx)(LOGICAL_PROCESSOR_RELATIONSHIP, PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX, PDWORD);
            PFnGetLogicalProcessorInformationEx pfnGetLogicalProcessorInformationEx
                = (PFnGetLogicalProcessorInformationEx) GetProcAddress(GetModuleHandleW(L"kernel32.dll"), 
                                                                     "GetLogicalProcessorInformationEx");
            if (pfnGetLogicalProcessorInformationEx == NULL)
            {
                throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));

⌨️ 快捷键说明

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