📄 umsthreadproxy.cpp
字号:
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 + -