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

📄 schedulerproxy.h

📁 C语言库函数的原型,有用的拿去
💻 H
📖 第 1 页 / 共 2 页
字号:
// ==++==
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// SchedulerProxy.h
//
// RM proxy for a scheduler instance
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

namespace Concurrency
{
namespace details
{
    class SchedulerProxy : public ::Concurrency::ISchedulerProxy
    {
    public:
        /// <summary>
        ///     Constructs a scheduler proxy.
        /// </summary>
        SchedulerProxy(IScheduler * pScheduler, ResourceManager * pResourceManager, const SchedulerPolicy &policy);

        /// <summary>
        ///     Called in order to notify the resource manager that the given scheduler is shutting down.  This
        ///     will cause the resource manager to immediately reclaim all resources granted to the scheduler.
        /// </summary>
        virtual void Shutdown();

        /// <summary>
        ///     Called by a scheduler in order make an initial request for an allocation of virtual processors.  The request
        ///     is driven by policies within the scheduler queried via the IScheduler::GetPolicy method.  If the request
        ///     can be satisfied via the rules of allocation, it is communicated to the scheduler as a call to
        ///     IScheduler::AddVirtualProcessors.
        /// </summary>
        /// <param name="doSubscribeCurrentThread">
        ///     Whether to subscribe the current thread and account for it during resource allocation.
        /// </param>
        /// <returns>
        ///     The IExecutionResource instance representing current thread if doSubscribeCurrentThread was true; NULL otherwise.
        /// </returns>
        virtual IExecutionResource * RequestInitialVirtualProcessors(bool doSubscribeCurrentThread);

        /// <summary>
        ///     Ensures that a context is bound to a thread proxy.  This API should *NOT* be called in the vast majority of circumstances.
        ///     The IThreadProxy::SwitchTo will perform late binding to thread proxies as necessary.  There are, however, circumstances
        ///     where it is necessary to pre-bind a context to ensure that the SwitchTo operation switches to an already bound context.  This
        ///     is the case on a UMS scheduling context as it cannot call allocation APIs.
        /// </summary>
        /// <param name="pContext">
        ///     The context to bind.
        /// </param>
        virtual void BindContext(IExecutionContext * pContext);

        /// <summary>
        ///     Returns an **unstarted** thread proxy attached to pContext, to the thread proxy factory.  
        ///     Such a thread proxy **must** be unstarted.
        ///     This API should *NOT* be called in the vast majority of circumstances.
        /// </summary>
        /// <param name="pContext">
        ///     The context to unbind.
        /// </param>
        virtual void UnbindContext(IExecutionContext * pContext);

        /// <summary>
        ///     This API registers the current thread with the resource manager associating it with this scheduler,
        ///     and returns an instance of IExecutionResource back to the scheduler, for bookkeeping and maintenance.
        /// </summary>
        /// <returns>
        ///     The IExecutionResource instance representing current thread in the runtime.
        /// </returns>
        virtual IExecutionResource * SubscribeCurrentThread();

        /// <summary>
        ///     The unique identifier of the scheduler this proxy represents.
        /// </summary>
        unsigned int GetId() const
        {
            return m_id;
        }

        /// <summary>
        ///     Causes the resource manager to create a new virtual processor root running atop the same hardware thread as this
        ///     execution resource. Typically, this is used when a scheduler wishes to oversubscribe a particular hardware thread
        ///     for a limited amount of time.
        /// </summary>
        /// <param name="pExecutionResource">
        ///     The execution resource abstraction on which to oversubscribe.
        /// </param>
        /// <returns>
        ///     A new virtual processor root running atop the same hardware thread as this execution resource.
        /// </returns>
        virtual IVirtualProcessorRoot * CreateOversubscriber(IExecutionResource * pExecutionResource);

        /// <summary>
        ///     Getters for the various policy elements.
        /// </summary>
        unsigned int MaxConcurrency() const
        {
            return m_maxConcurrency; 
        }
        unsigned int MinConcurrency() const 
        {
            return m_minConcurrency; 
        }
        unsigned int TargetOversubscriptionFactor() const 
        {
            return m_targetOversubscriptionFactor; 
        }
        int ContextStackSize () const
        {
            return m_contextStackSize; 
        }
        int ContextPriority () const 
        {
            return m_contextPriority; 
        }

        unsigned int MinVprocHWThreads() const
        {
            // Compute number of cores used for virtual processors that are fixed
            ASSERT(m_numFixedCores >= m_numExternalThreadCores);
            unsigned int fixedVprocCores = m_numFixedCores - m_numExternalThreadCores;
            // Compute maximum(t1, minimum set by policy) which is minimum of virtual processor cores
            return max(fixedVprocCores, m_minimumHardwareThreads);
        }

        unsigned int MinHWThreads() const
        {
            // The minimum needed number of hardware threads (cores) is equal to:
            //  - minimum needed vproc cores + minimum needed external thread cores
            unsigned int minimumCores = MinVprocHWThreads() + m_numExternalThreadCores;

            ASSERT(minimumCores <= m_physicalResourceCount);
            return minimumCores;
        }

        unsigned int DesiredHWThreads() const
        {
            unsigned int desiredCores = min(m_physicalResourceCount, m_desiredHardwareThreads + m_numExternalThreadCores);

            ASSERT(m_numExternalThreads != 0 || desiredCores == m_desiredHardwareThreads);
            return desiredCores;
        }

        unsigned int ComputeMinHWThreadsWithExternalThread() const
        {
            unsigned int newMin = min(m_physicalResourceCount, MinHWThreads() + 1);
            return newMin;
        }

        unsigned int ComputeDesiredHWThreadsWithExternalThread() const
        {
            unsigned int newDesired = min(m_physicalResourceCount, DesiredHWThreads() + 1);
            return newDesired;
        }

        /// <summary>
        ///     Returns the number of external thread subscriptions
        /// </summary>
        unsigned int GetNumNestedThreadSubscriptions()
        {
            return m_threadSubscriptions.Count();
        }

        /// <summary>
        ///     Called to adjust the suggested allocation such that we do not exceed maxConcurrency.
        ///     This routine takes into account vprocs that are marked for removal but haven't yet been
        ///     retired by the scheduler. The suggested allocation would be decreased to account for such
        ///     vprocs.
        /// </summary>
        unsigned int AdjustAllocationIncrease(unsigned int suggestedAllocation) const;

        /// <summary>
        ///     Returns the number of cores allocated to the proxy at any time.
        /// </summary>
        unsigned int GetNumAllocatedCores() const
        {
            return m_numAllocatedCores; 
        }

        /// <summary>
        ///     Returns the number of borrowed cores. These are cores that were oversubscribed and temporarily
        ///     assigned to this scheduler during dynamic core migration as they were found to be unused
        ///     by the other scheduler(s) they were assigned to. The reason these cores were oversubscribed
        ///     instead of migrated was that they contributed to the minimum number of cores on the other
        ///     scheduler(s) and hence couldn't be taken away.
        /// </summary>
        unsigned int GetNumBorrowedCores() const 
        {
            return m_numBorrowedCores; 
        }

        /// <summary>
        ///     Returns the number of owned cores. This is the total allocated cores minus the borrowed cores.
        /// </summary>
        unsigned int GetNumOwnedCores() const 
        {
            return m_numAllocatedCores - m_numBorrowedCores; 
        }

        /// <summary>
        ///     Returns the number of fixed cores - cores that have a subscribed thread on them.
        /// </summary>
        unsigned int GetNumFixedCores() const 
        {
            return m_numFixedCores; 
        }

        /// <summary>
        ///     Tells if cores were stolen from this proxy during the course of a new allocation.
        /// </summary>
        bool GetCoresStolen() const
        {
            return m_fCoresStolen;
        }

        /// <summary>
        ///     Sets or clears a flag indicating the RM is stealing cores from this proxy to satsify a new scheduler's
        ///     allocation.
        /// </summary>
        void SetCoresStolen(bool stolen) 
        {
            m_fCoresStolen = stolen; 
        }

        /// <summary>
        ///     Toggles the state on a core from borrowed to owned (and vice versa), and updates necessary counts.
        /// </summary>
        void ToggleBorrowedState(SchedulerNode * pNode, unsigned int coreIndex);

        /// <summary>
        ///     Creates a new execution resource for the external thread and registers it with the scheduler proxy.
        /// </summary>
        ExecutionResource * CreateExternalThreadResource(SchedulerNode * pNode, unsigned int coreIndex);

        /// <summary>
        ///     Called by the RM when it is done allocating cores for the scheduler proxy. Gives the proxy
        ///     an array of nodes and cores.
        /// </summary>
        ExecutionResource * GrantAllocation(SchedulerNode * pAllocatedNodes, unsigned int nodeCount, unsigned int numberAllocated, bool doExternalThreadAllocation);

        /// <summary>
        ///     Finds the core allocated by the RM on which a single subscribed external thread should run.
        /// </summary>
        ExecutionResource * GrantExternalThreadAllocation(bool doOversubscribeCore);

        /// <summary>
        ///     Returns a pointer to the copy of allocated nodes that were assigned to the proxy at
        ///     creation time.
        /// </summary>
        SchedulerNode * GetAllocatedNodes() const
        {
            return m_pAllocatedNodes;
        }

        /// <summary>
        ///     Returns a pointer to the array that holds the sorted order for nodes. This is used by the
        ///     RM to sort nodes by whatever criteria it chooses.
        /// </summary>
        unsigned int * GetSortedNodeOrder() const 
        {
            return m_pSortedNodeOrder;
        }

        /// <summary>
        ///     Returns a pointer to the scheduler associated with the sheduler proxy.
        /// </summary>
        IScheduler * Scheduler() const 
        {
            return m_pScheduler;
        }

        /// <summary>
        ///     Returns a pointer to the resource manager associated with the scheduler proxy.
        /// </summary>
        ResourceManager * GetResourceManager() const
        {
            return m_pResourceManager; 
        }

        /// <summary>
        ///     Returns a pointer to a data buffer that is used to store static allocation data. The data
        ///     is populated and manipulated by the RM, but stored in the scheduler proxy for convenience.
        /// </summary>
        StaticAllocationData * GetStaticAllocationData()
        {
            return &m_staticData;
        }

        /// <summary>
        ///     Returns a pointer to a data buffer that is used to store dynamic allocation data. The data
        ///     is populated and manipulated by the RM, but stored in the scheduler proxy for convenience.
        /// </summary>
        DynamicAllocationData * GetDynamicAllocationData()
        {
            return &m_dynamicData;
        }

        /// <summary>
        ///     Creates a virtual processor root and adds it to the scheduler proxys list of roots.
        /// </summary>
        virtual VirtualProcessorRoot * CreateVirtualProcessorRoot(SchedulerNode * pNode, unsigned int coreIndex);

        /// <summary>
        ///     Notifies the scheduler associated with this proxy to add the virtual processor roots provided.
        ///     Called by the RM during initial allocation and dynamic core migration.
        /// </summary>
        void AddVirtualProcessorRoots(IVirtualProcessorRoot ** vprocRoots, unsigned int count);

        /// <summary>
        ///     Adds an appropriate number of virtual processor roots to the scheduler associated with this proxy.
        ///     Called by the RM during core migration when the RM decides to give this scheduler an additional
        ///     core.
        /// </summary>
        void AddCore(SchedulerNode * pNode, unsigned int coreIndex, bool fBorrowed);

        /// <summary>
        ///     Notifies the scheduler associated with this proxy to remove the virtual processor roots associated
        ///     with the core provided. Called by the RM during core migration.
        /// </summary>
        void RemoveCore(SchedulerNode * pNode, unsigned int coreIndex);

        /// <summary>
        ///     Called by the RM to instruct this scheduler proxy to notify its scheduler that this core is now
        ///     externally busy or externally idle.
        /// </summary>

⌨️ 快捷键说明

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