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

📄 umsthreadproxy.cpp

📁 C语言库函数的原型,有用的拿去
💻 CPP
📖 第 1 页 / 共 2 页
字号:
        CORE_ASSERT((int)switchState >= 0 && (int)switchState <= 2);
        m_yieldAction = stateActions[switchState];
        m_pNextProxy = pProxy;
        CORE_ASSERT(m_yieldAction != ActionNone);
        CORE_ASSERT(m_pRoot != NULL && m_pRoot == m_pLastRoot && m_pRoot->GetExecutingProxy() == this);
        UMS::UmsThreadYield(this);

        //
        // Idle threads have critical regions completely reset when they go on the idle pool (this is what allows us to have 
        // "until the end of time" semantics on certain critical regions from the perspective of a thread going away).
        //
        if (switchState != Idle)
            ExitHyperCriticalRegion();
        else
        {
            //
            // Note that there is now a code path in the primary where-by it must allocate a new (or get a pooled) proxy to burn on the way out to avoid
            // a Win7 bug.  In this case, the primary must continue to execute the thread until thread exit which means it must be hyper-crit.  In this circumstance,
            // m_fCanceled should already be set on the way out!
            //
            CORE_ASSERT(m_hyperCriticalRegionCount == 0 || m_fCanceled);
        }
    }

    /// <summary>
    ///     Called in order to perform a cooperative context switch out.  After this call, the context which was running will be blocked
    ///     until it is switched to or used to activate a virtual processor.
    /// </summary>
    void UMSThreadProxy::InternalSwitchOut()
    {
        EnterHyperCriticalRegion();
        
        //
        // If we are currently in a transmogrified state, undo the transmogrification.  Yielding back to the transmogrified primary will get rid of that
        // particular thread.
        //
        if (m_pTransmogrification != NULL)
        {
            m_pTransmogrification = NULL;
            UMS::UmsThreadYield(this);
        }
        else
        {
            m_yieldAction = ActionResetForSwitchOut;
            UMS::UmsThreadYield(this);
        }
        ExitHyperCriticalRegion();
    }

    /// <summary>
    ///     Yield to the underlying Operting system
    /// </summary>
    void UMSThreadProxy::InternalYieldToSystem()
    {
        // This needs to be called by the thread that is currently executing
        CORE_ASSERT(UMSThreadProxy::GetCurrent() == this);

        EnterHyperCriticalRegion();

        m_yieldAction = ActionYieldToSystem;
        m_pNextProxy = NULL;
        CORE_ASSERT(m_yieldAction != ActionNone);
        CORE_ASSERT(m_pRoot != NULL && m_pRoot == m_pLastRoot && m_pRoot->GetExecutingProxy() == this);
        UMS::UmsThreadYield(this);

        ExitHyperCriticalRegion();
    }

    /// <summary>
    ///     Deactivate the current thread proxy.  As this requires a message block set, it lives here
    ///     rather than in the VPROOT.
    /// </summary>
    /// <returns>
    ///     An indication of whether the awakening was due to an Activate call on the virtual processor root
    ///     (true) or an RM cause (e.g.: completion notification -- false).
    /// </returns>
    bool UMSThreadProxy::Deactivate()
    {
        CORE_ASSERT(GetCriticalRegionType() != OutsideCriticalRegion);
        CORE_ASSERT(m_pRoot != NULL);

        //
        // Manipulations of m_yieldAction need to be guarded under a hyper-critical region.  We cannot tolerate a page fault happening
        // which corrupts our state.
        //
        EnterHyperCriticalRegion();

        m_yieldAction = ActionDeactivate;
        m_pNextProxy = NULL;
        UMS::UmsThreadYield(this);

        CORE_ASSERT(m_activationCause != ActivationCauseNone);
        bool fActivated = (m_activationCause == ActivationCauseActivate);
        m_activationCause = ActivationCauseNone;

        ExitHyperCriticalRegion();

        return fActivated;
    }

    /// <summary>
    ///     The caller has exited the dispatch loop.  Free the thread and deactivate.
    /// <summary>
    void UMSThreadProxy::FreeViaExit()
    {
        //
        // Manipulations of m_yieldAction need to be guarded under a hyper-critical region.  We cannot tolerate a page fault happening
        // which corrupts our state.
        //
        EnterHyperCriticalRegion();

        CORE_ASSERT(!m_fIdlePooled);

        if (ResourceManager::RequireUMSWorkaround() && m_pRoot->IsDeleting())
        {
            Cancel();

            //
            // From now until the end of time, this thread must remain in a hyper-critical region.  It is imperative that the virtual processor run this thread
            // until it exits and THEN subsequently shut down.
            //
        }
        else
        {
            m_yieldAction = ActionFree;
            UMS::UmsThreadYield(this);

            //
            // We need not worry about releasing the critical region here.  When it goes on the free list, it gets completely reinitialized.  Either
            // that or we're on the way out (to get rid of the thread) and we only want to run this thread anyway.
            //
        }
    }

    /// <summary>
    ///     Sets the priority of the underlying thread.
    /// </summary>
    /// <param name="priority">
    ///     The new priority value for the thread.
    /// </param>
    void UMSThreadProxy::SetPriority(int priority)
    {
        //
        // Right now (Win7), the priority set here only impacts running atop the real UT thread (not running the primary underneath).
        // This only happens on certain kernel transitions and on certain optimizations out of the kernel.  Really,
        // the primary should be the only one setting priority. However, we do this to ensure that BOTH the primary thread
        // and the kernel portion of the UT have the same priority setting.
        //
        m_threadPriority = priority;

        if (SetThreadPriority(m_hPhysicalContext, m_threadPriority) == 0)
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
    }

    /// <summary>
    ///     Cancels the thread proxy causing the underlying thread to exit.
    /// </summary>
    void UMSThreadProxy::Cancel()
    {
        m_fCanceled = true;
    }

    /// <summary>
    ///     Spins until we've registered blocking.
    /// </summary>
    void UMSThreadProxy::SpinUntilBlocked()
    {
        if (m_pRoot != NULL)
        {
            _SpinWaitBackoffNone spinWait(_Sleep0);

            do
            {
                spinWait._SpinOnce();

            } while (m_pRoot != NULL);
        }
    }

    /// <summary>
    ///     Spins until we've registered what blocking type the last block operation was and returns the type.
    /// </summary>
    /// <returns>
    ///     Returns the blocking type.
    /// </returns>
    UMSThreadProxy::BlockingType UMSThreadProxy::SpinOnAndReturnBlockingType()
    {
        if (m_blockingType == BlockingNone)
        {
            _SpinWaitBackoffNone spinWait(_Sleep0);

            do
            {
                spinWait._SpinOnce();

            } while (m_blockingType == BlockingNone);
        }

        return m_blockingType;
    }

    /// <summary>
    ///     Returns whether or not this thread is currently suspended.
    /// </summary>
    /// <returns>
    ///     Returns true if the thread is suspended
    /// </returns>
    bool UMSThreadProxy::IsSuspended()
    {
        BOOLEAN fSuspended = FALSE;
        UMS::QueryUmsThreadInformation(m_pUMSContext, UmsThreadIsSuspended, &fSuspended, sizeof(fSuspended), NULL);

        return !!fSuspended;
    }

    /// <summary>
    ///     Returns whether or not this thread is currently terminated.
    /// </summary>
    /// <returns>
    ///     Returns true if the thread is terminated
    /// </returns>
    bool UMSThreadProxy::IsTerminated()
    {
        BOOLEAN fTerminated = FALSE;
        UMS::QueryUmsThreadInformation(m_pUMSContext, UmsThreadIsTerminated, &fTerminated, sizeof(fTerminated), NULL);

        return !!fTerminated;
    }

    /// <summary>
    ///     Called in order to prepare this thread proxy to run atop a given virtual processor root.
    /// </summary>
    void UMSThreadProxy::PrepareToRun(UMSFreeVirtualProcessorRoot *pRoot)
    {
#if defined(_DEBUG)
        m_lastRunPrepareTimeStamp = __rdtsc();
#endif // _DEBUG

        m_blockingType = BlockingNone;
        m_pLastRoot = pRoot;
        m_pRoot = pRoot;
    }

} // namespace details
} // namespace Concurrency

⌨️ 快捷键说明

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