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

📄 umsthreadproxy.cpp

📁 C语言库函数的原型,有用的拿去
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// ==++==
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// UMSThreadProxy.h
//
// Proxy for a UMS thread.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

#include "concrtinternal.h"

namespace Concurrency
{
namespace details
{
    /// <summary>
    ///     Constructs a thread proxy.
    /// </summary>
    UMSThreadProxy::UMSThreadProxy(IThreadProxyFactory * pFactory, PUMS_COMPLETION_LIST pStartupList, unsigned int stackSize) :
        m_pFactory(pFactory),
        m_stackSize(stackSize),
        m_yieldAction(ActionNone),
        m_activationCause(ActivationCauseNone),
        m_pTransmogrification(NULL),
        m_hPhysicalContext(NULL),
        m_hBlock(NULL),
        m_pUMSContext(NULL),
        m_pRoot(NULL),
        m_pLastRoot(NULL),
        m_criticalRegionCount(0),
        m_hyperCriticalRegionCount(0),
        m_fCanceled(FALSE),
        m_fIdlePooled(false),
        m_blockingType(BlockingNone)
#if defined(_DEBUG)
        ,m_UMSDebugBits(0)
        ,m_fShutdownValidations(false)
        ,m_lastRunPrepareTimeStamp(0)
#endif // _DEBUG
    {
        m_hBlock = CreateEventW(NULL, FALSE, FALSE, NULL);
        if (m_hBlock == NULL)
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));

        m_id = ResourceManager::GetThreadProxyId();
    
        UMS_CREATE_THREAD_ATTRIBUTES umsAttributes;
        PPROC_THREAD_ATTRIBUTE_LIST pAttributeList;
        SIZE_T sizeAttributeList;

        if (!UMS::CreateUmsThreadContext(&m_pUMSContext))
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));

        UMSBaseObject *pThis = this;
        if (!UMS::SetUmsThreadInformation(m_pUMSContext, UmsThreadUserContext, &pThis, sizeof(pThis)))
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));

        umsAttributes.UmsVersion = UMS_VERSION;
        umsAttributes.UmsContext = m_pUMSContext;
        umsAttributes.UmsCompletionList = pStartupList;

        UMS::InitializeProcThreadAttributeList(NULL, 1, 0, &sizeAttributeList);
        ASSERT(GetLastError() == ERROR_INSUFFICIENT_BUFFER);

        pAttributeList = reinterpret_cast<PPROC_THREAD_ATTRIBUTE_LIST>(new char[sizeAttributeList]);
        if (!UMS::InitializeProcThreadAttributeList(pAttributeList, 1, 0, &sizeAttributeList))
        {
            delete[] (reinterpret_cast<char*>(pAttributeList));
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
        }

        if (!UMS::UpdateProcThreadAttribute(pAttributeList, 0, PROC_THREAD_ATTRIBUTE_UMS_THREAD, &umsAttributes, sizeof(UMS_CREATE_THREAD_ATTRIBUTES), NULL, NULL))
        {
            delete[] (reinterpret_cast<char *>(pAttributeList));
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
        }

        m_hPhysicalContext = UMS::CreateRemoteThreadEx(GetCurrentProcess(), 
                                                       NULL, 
                                                       stackSize*KB, 
                                                       UMSThreadProxyMain, 
                                                       this, 
                                                       STACK_SIZE_PARAM_IS_A_RESERVATION, 
                                                       pAttributeList, 
                                                       &m_threadId);

        UMS::DeleteProcThreadAttributeList(pAttributeList);
        delete[] (reinterpret_cast<char *>(pAttributeList));

        if (m_hPhysicalContext == NULL)
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));

    }

    /// <summary>
    ///     Destroys a thread proxy.
    /// </summary>
    UMSThreadProxy::~UMSThreadProxy()
    {
        if (m_hBlock != NULL)
            CloseHandle(m_hBlock);

        if (m_hPhysicalContext != NULL)
            CloseHandle(m_hPhysicalContext);

        if (m_pUMSContext != NULL)
            UMS::DeleteUmsThreadContext(m_pUMSContext);
    }

    /// <summary>
    ///     Returns a process unique identifier for the thread proxy.
    /// </summary>
    unsigned int UMSThreadProxy::GetId() const
    {
        return m_id;
    }

    /// <summary>
    ///     Thread start routine for proxies.
    /// </summary>
    /// <param name="lpParameter">
    ///     Pointer to the thread proxy
    /// </param>
    DWORD CALLBACK UMSThreadProxy::UMSThreadProxyMain(LPVOID lpParameter)
    {
        UMSThreadProxy* pThreadProxy = reinterpret_cast<UMSThreadProxy*> (lpParameter);

        pThreadProxy->ReadyForDispatch();

        CORE_ASSERT(pThreadProxy->GetCriticalRegionType() == OutsideCriticalRegion || pThreadProxy->m_pRoot->IsDeleting());
        pThreadProxy->Dispatch();

        ASSERT(pThreadProxy->m_fCanceled);

        //
        // The data structure needs to remain until we jump back to the primary executing it for the last time and the primary detects that
        // the thread has terminated.  Otherwise, the primary will read an invalid data structure to determine what just terminated!
        //
        return 0;
    }

    /// <summary>
    ///     Indicate that the thread proxy is ready for dispatch.
    /// </summary>
    void UMSThreadProxy::ReadyForDispatch()
    {
        // If the UT is started up on a dedicated primary then we need not be in a hypercritical
        // region. We enter a hypercritical region here to ensure that this would work if we decide
        // to move UT startup to vprocs.
        EnterHyperCriticalRegion();
        m_yieldAction = ActionStartup;
        UMS::UmsThreadYield(this);
        
       // Critical region count will be cleared on dispatch.
    }

    /// <summary>
    ///     Returns our understanding of a UMS context (a UMS thread proxy) from the UMS system's understanding (a UMS_CONTEXT)
    /// </summary>
    /// <param name="pUMSContext">
    ///     UMS context
    /// </param>
    /// <returns>
    ///     UMS thread proxy
    /// </returns>
    UMSThreadProxy *UMSThreadProxy::FromUMSContext(PUMS_CONTEXT pUMSContext)
    {
        if (pUMSContext == NULL)
            return NULL;

        UMSBaseObject *pObj = NULL;
        UMSThreadProxy *pProxy = NULL;
        ULONG returnLength;

        if (!UMS::QueryUmsThreadInformation(pUMSContext, UmsThreadUserContext, reinterpret_cast <PVOID> (&pObj), sizeof(pObj), &returnLength))
            throw scheduler_resource_allocation_error(HRESULT_FROM_WIN32(GetLastError()));
        
        ASSERT(returnLength == sizeof(pObj));

        if (pObj != NULL && !pObj->IsPrimary())
            pProxy = static_cast<UMSThreadProxy *>(pObj);

        return pProxy;

    }

    /// <summary>
    ///     Returns our understanding of a UMS context (a UMS thread proxy) from the SLIST_ENTRY used to 
    ///     place it on an SLIST (e.g.: the transfer list).
    /// </summary>
    /// <param name="pListEntry">
    ///     Pointer to the SList entry in the thread proxy
    /// </param>
    /// <returns>
    ///     UMS thread proxy
    /// </returns>
    UMSThreadProxy *UMSThreadProxy::FromListEntry(PSLIST_ENTRY pListEntry)
    {
        if (pListEntry == NULL) return NULL;
        return CONTAINING_RECORD(pListEntry, UMSThreadProxy, m_listEntry);
    }

    /// <summary>
    ///     Switch from the current thread proxy to pProxy.
    /// </summary>
    /// <param name="pProxy">
    ///     The thread proxy to switch to.
    /// </param>
    /// <param name="switchState">
    ///     The reason for the switch.
    /// </param>
    void UMSThreadProxy::InternalSwitchTo(UMSThreadProxy *pProxy, SwitchingProxyState switchState)
    {
        const YieldAction stateActions[] = {
            ActionSwitchToAndRetire /* Idle */, 
            ActionSwitchTo /* Blocking */,
            ActionTransmogrify /* Nesting */
            };

        //
        // 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();

        //
        // On nesting, we have to transmogrify the currently running UMS thread to a "virtual"-thread so that it can continue
        // to run as an external context of a nested scheduler without having to be scheduled atop a virtual processor (something
        // outside our model).
        //
        if (switchState == Nesting)
        {
            CORE_ASSERT(m_pTransmogrification == NULL);
            
            //
            // We cannot perform an allocation or thread creation here, so we ask the transmogrificator to do this for us.  Oh fun.
            //
            Transmogrificator *pTransmogrificator = m_pRoot->GetResourceManager()->GetTransmogrificator();
            pTransmogrificator->PerformTransmogrification(this);
        }

        RVPMTRACE(switchState == Idle ? MTRACE_EVT_SWITCHTO_IDLE : (switchState == Blocking ? MTRACE_EVT_SWITCHTO_BLOCKING : MTRACE_EVT_SWITCHTO_NESTING), this, m_pRoot, pProxy);

⌨️ 快捷键说明

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