📄 umsthreadproxy.h
字号:
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// UMSThreadProxy.h
//
// Proxy for a UMS thread.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#if defined(_DEBUG)
#define UMS_DEBUGBIT_CRITICALBLOCK 0x00000001
#define UMS_DEBUGBIT_BLOCKED 0x00000002
#define UMS_DEBUGBIT_COMPLETION 0x00000004
#define UMS_DEBUGBIT_TRANSFERLIST 0x00000008
#define UMS_DEBUGBIT_CRITICALNOTIFY 0x00000010
#define UMS_DEBUGBIT_SKIPPEDCOMPLETION 0x00000020
#define UMS_DEBUGBIT_HANDEDTOPOLLER 0x00000040
#define UMS_DEBUGBIT_PULLEDFROMTRANSFERLIST 0x00000080
#define UMS_DEBUGBIT_POLLERFOUNDCOMPLETION 0x00000100
#define UMS_DEBUGBIT_YIELDED 0x00000200
#define UMS_DEBUGBIT_FREELIST 0x00000400
#define UMS_DEBUGBIT_CRITICALAWAKENING 0x00000800
#define UMS_DEBUGBIT_DEACTIVATEDPROXY 0x00001000
#define UMS_DEBUGBIT_ACTIVATEDPROXY 0x00002000
#define UMS_DEBUGBIT_COMPLETIONTERMINATED 0x00004000
#define UMS_DEBUGBIT_EXECUTEFAILURESUSPENDED 0x80000000
#define UMS_DEBUGBIT_EXECUTEFAILURETERMINATED 0x40000000
#endif // _DEBUG
// A magic value for m_pTransmogrification that indicates it should be immediately unblocked when defer created.
#define TRANSMOGRIFICATION_UNBLOCKED ((PVOID)1)
namespace Concurrency
{
namespace details
{
class UMSThreadProxy : public UMSBaseObject, public Concurrency::IUMSThreadProxy, public Concurrency::IUMSUnblockNotification
{
public:
/// <summary>
/// Constructs a thread proxy.
/// </summary>
/// <param name="pFactory">
/// The thread proxy factory that created this thread proxy, and maintains the idle pool of thread proxies.
/// </param>
/// <param name="pStartupList">
/// The initial UMS completion list that this UMS thread should be put on upon creation. A primary cannot schedule
/// the thread until it has appeared on the specified completion list.
/// </param>
/// <param name="stackSize">
/// The stack size of the created thread.
/// </param>
UMSThreadProxy(IThreadProxyFactory * pFactory, PUMS_COMPLETION_LIST pStartupList, unsigned int stackSize);
/// <summary>
/// Destroys a thread proxy.
/// </summary>
virtual ~UMSThreadProxy();
/// <summary>
/// Retrieves a process unique id for the thread proxy.
/// </summary>
unsigned int GetId() const;
/// <summary>
/// Gets the stack size of the thread proxy. Multiply by 1 KB to get actual stack size in bytes.
/// </summary>
unsigned int GetStackSize()
{
return m_stackSize;
}
/// <summary>
/// Cancels the thread proxy causing the underlying thread to exit.
/// </summary>
void Cancel();
/// <summary>
/// Returns the virtual processor root the thread proxy is running on.
/// </summary>
UMSFreeVirtualProcessorRoot *GetVirtualProcessorRoot()
{
return m_pRoot;
}
/// <summary>
/// Returns the previous virtual processor root the thread proxy is running on. If it is running, the current one is returned.
/// </summary>
UMSFreeVirtualProcessorRoot *GetLastVirtualProcessorRoot()
{
return m_pLastRoot;
}
/// <summary>
/// Returns a Win32 handle to the thread that is backing this proxy.
/// </summary>
HANDLE GetThreadHandle()
{
return m_hPhysicalContext;
}
/// <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>
static UMSThreadProxy *FromUMSContext(PUMS_CONTEXT pUMSContext);
/// <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>
static UMSThreadProxy *FromListEntry(PSLIST_ENTRY pListEntry);
/// <summary>
/// Returns the current UMS context.
/// </summary>
/// <returns>
/// Current UMS thread proxy
/// </returns>
static UMSThreadProxy *GetCurrent()
{
return UMSThreadProxy::FromUMSContext(UMS::GetCurrentUmsThread());
}
/// <summary>
/// Returns the PUMS_CONTEXT associated with this UMS thread.
/// </summary>
/// <returns>
/// UMS context for this thread
/// </returns>
PUMS_CONTEXT GetUMSContext() const
{
return m_pUMSContext;
}
/// <summary>
/// Returns whether the action that this thread took to get itself "unscheduled" was a message/yield pair. This could be an explicit
/// SwitchTo, a Deactivate, a pooling, etc...
/// </summary>
/// <returns>
/// Returns true if the thread last yielded to the primary
/// </returns>
bool MessagedYield()
{
return (m_yieldAction != ActionNone);
}
/// <summary>
/// Enters a critical region within the resource manager. This definition is constrained to the resource manager's definition
/// of a critical region. While inside a critical region, asynchronous suspensions (page faults, etc...) are hidden from view
/// of the underlying scheduling code (within the RM and the scheduler).
/// </summary>
/// <returns>
/// Returns the current critical region count
/// </returns>
virtual int EnterCriticalRegion()
{
// Entering a critical region should be done on the same thread
CORE_ASSERT(UMSThreadProxy::GetCurrent() == this);
return(++m_criticalRegionCount);
}
/// <summary>
/// Exits a critical region within the resource manager. This definition is constrained to the resource manager's definition
/// of a critical region. While inside a critical region, asynchronous suspensions (page faults, etc...) are hidden from view
/// of the underlying scheduling code (within the RM and the scheduler).
/// </summary>
/// <returns>
/// Returns the current critical region count
/// </returns>
virtual int ExitCriticalRegion()
{
CORE_ASSERT(m_criticalRegionCount > 0);
return(--m_criticalRegionCount);
}
/// <summary>
/// Identical to EnterHyperCriticalRegion -- this is a private version for utilization within the RM that does not follow the
/// "on-the-owning" thread rule.
/// </summary>
/// <returns>
/// Returns the current hypercritical region count
/// </returns>
int ForceEnterHyperCriticalRegion()
{
m_criticalRegionCount++;
return(++m_hyperCriticalRegionCount);
}
/// <summary>
/// Enters a hyper-critical region within the resource manager. This definition is constrained to the resource manager's definition
/// of a hyper-critical region. When inside a hyper-critical region, any suspension is hidden from view of the underlying scheduling
/// code. This requires EXTRA care with regards to the locks which are taken inside the region. No lock taken inside the region
/// can be shared with code outside such a region!
/// </summary>
/// <returns>
/// Returns the current hypercritical region count
/// </returns>
virtual int EnterHyperCriticalRegion()
{
// Entering a critical region should be done on the same thread
CORE_ASSERT(UMSThreadProxy::GetCurrent() == this);
return ForceEnterHyperCriticalRegion();
}
/// <summary>
/// Exit a hyper-critical region within the resource manager. This definition is constrained to the resource manager's definition
/// of a hyper-critical region. When inside a hyper-critical region, any suspension is hidden from view of the underlying scheduling
/// code. This requires EXTRA care with regards to the locks which are taken inside the region. No lock taken inside the region
/// can be shared with code outside such a region!
/// </summary>
/// <returns>
/// Returns the current hypercritical region count
/// </returns>
virtual int ExitHyperCriticalRegion()
{
CORE_ASSERT(m_hyperCriticalRegionCount > 0);
CORE_ASSERT(m_criticalRegionCount > 0);
int val = --m_hyperCriticalRegionCount;
m_criticalRegionCount--;
return val;
}
/// <summary>
/// Returns whether or not this UMS thread proxy is within a critical region (either inside the RM or inside the scheduler).
/// Note that the scheduler's definition of a critical region may be stronger than ours.
/// </summary>
/// <returns>
/// Whether or not this UMS thread proxy is within a critical region.
/// </returns>
virtual CriticalRegionType GetCriticalRegionType() const
{
if (m_hyperCriticalRegionCount > 0)
return InsideHyperCriticalRegion;
if (m_criticalRegionCount > 0)
return InsideCriticalRegion;
return OutsideCriticalRegion;
}
/// <summary>
/// Clears the critical region bits. This should be done before reusing the context or placing it on the idle pool as certain operations
/// require a "until the end of time" critical region.
/// </summary>
void ClearCriticalRegion()
{
m_criticalRegionCount = m_hyperCriticalRegionCount = 0;
}
/// <summary>
/// Gets the priority of the thread proxy.
/// </summary>
/// <returns>
/// The priority of the thread proxy
/// </returns>
int GetPriority()
{
return m_threadPriority;
}
/// <summary>
/// Sets the priority of the underlying thread.
/// </summary>
/// <param name="priority">
/// The new priority value for the thread.
/// </param>
void SetPriority(int priority);
/// <summary>
/// Notifies the thread proxy that it is blocked (due to UMS activation of the primary).
/// </summary>
/// <param name="fCritically">
/// Indication that this thread is critically blocked (inside critical region)
/// </param>
void NotifyBlocked(bool fCritically)
{
CORE_ASSERT(m_pRoot != NULL);
#if defined(_DEBUG)
CORE_ASSERT((m_UMSDebugBits & (UMS_DEBUGBIT_DEACTIVATEDPROXY | UMS_DEBUGBIT_ACTIVATEDPROXY)) != UMS_DEBUGBIT_DEACTIVATEDPROXY);
#endif // _DEBUG
m_blockingType = fCritically ? BlockingCritical : BlockingNormal;
if (!fCritically)
InterlockedExchangePointer((volatile PVOID*)&m_pRoot, (PVOID)NULL);
}
/// <summary>
/// Returns whether or not this thread is currently suspended.
/// </summary>
/// <returns>
/// Returns true if the thread is suspended
/// </returns>
bool IsSuspended();
/// <summary>
/// Returns whether or not this thread is currently terminated.
/// </summary>
/// <returns>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -