📄 resourcemanager.h
字号:
// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// ResourceManager.h
//
// Implementation of IResourceManager.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#pragma once
namespace Concurrency
{
namespace details
{
class ResourceManager : public Concurrency::IResourceManager
{
public:
/// <summary>
/// Increments the reference count on a resource manager.
/// </summary>
/// <returns>
/// Returns the resulting reference count.
/// </returns>
virtual unsigned int Reference();
/// <summary>
/// Decrements the reference count on a resource manager.
/// </summary>
/// <returns>
/// Returns the resulting reference count.
/// </returns>
virtual unsigned int Release();
/// <summary>
/// Associates an IScheduler with the ISchedulerProxy that represents the part
/// of IResourceManager associated with the IScheduler.
/// </summary>
/// <param name="pScheduler">
/// The scheduler to be associated.
/// </param>
/// <param name="version">
/// The version of the RM<->Scheduler communication channel that is being utilized.
/// </param>
virtual ISchedulerProxy * RegisterScheduler(IScheduler *pScheduler, unsigned int version);
/// <summary>
/// Creates an instance of the resource manager.
/// </summary>
static ResourceManager* CreateSingleton();
/// <summary>
/// Returns the OS version.
/// </summary>
static IResourceManager::OSVersion Version();
/// <summary>
/// Returns whether we must work around a Win7 RTM UMS bug.
/// </summary>
static bool RequireUMSWorkaround()
{
return s_fRequireUMSWorkaround;
}
/// <summary>
/// Returns the number of nodes (processor packages or NUMA nodes)
/// </summary>
static unsigned int GetNodeCount();
/// <summary>
/// Returns the number of cores.
/// </summary>
static unsigned int GetCoreCount();
/// <summary>
/// Returns a pointer to the manager of factories for thread proxies.
/// </summary>
ThreadProxyFactoryManager * GetThreadProxyFactoryManager() { return &m_threadProxyFactoryManager; }
/// <summary>
/// These APIs return unique identifiers for use by schedulers, execution contexts and thread proxies.
/// </summary>
static unsigned int GetSchedulerId() { return InterlockedIncrement(&s_schedulerIdCount); }
static unsigned int GetExecutionContextId() { return InterlockedIncrement(&s_executionContextIdCount); }
static unsigned int GetThreadProxyId() { return InterlockedIncrement(&s_threadProxyIdCount); }
/// <summary>
/// Creates UMS background threads.
/// </summary>
void CreateUMSBackgroundThreads();
/// <summary>
/// Returns an instance of the UMS background poller thread.
/// </summary>
UMSBackgroundPoller *GetUMSBackgroundPoller() { return m_pUMSPoller; }
/// <summary>
/// Returns an instance of transmogrificator.
/// </summary>
Transmogrificator *GetTransmogrificator() { return m_pTransmogrificator; }
/// <summary>
/// The main allocation routine that allocates cores for a newly created scheduler proxy.
/// </summary>
ExecutionResource * PerformAllocation(SchedulerProxy *pSchedulerProxy, bool doExternalThreadAllocation);
/// <summary>
/// This API registers the current thread with the resource manager, associating it with this scheduler proxy,
/// and returns an instance of IExecutionResource back to the scheduler, for bookkeeping and maintenance.
/// </summary>
ExecutionResource * SubscribeCurrentThread(SchedulerProxy *pSchedulerProxy);
/// <summary>
/// The allocation routine that allocates a single core for a newly registered external thread.
/// </summary>
ExecutionResource * PerformExternalThreadAllocation(SchedulerProxy *pSchedulerProxy);
/// <summary>
/// Removes an execution resource that was created for an external thread.
/// </summary>
void RemoveExecutionResource(ExecutionResource * pExecutionResource);
/// <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>
void Shutdown(SchedulerProxy *pProxy);
/// <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="pProxy">
/// The scheduler proxy that is making the allocation request.
/// </param>
/// <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>
IExecutionResource * RequestInitialVirtualProcessors(SchedulerProxy *pProxy, bool doSubscribeCurrentThread);
/// <summary>
/// Debug CRT test hook to create artificial topologies. With the retail CRT, this API simply returns.
/// </summary>
virtual void CreateNodeTopology(unsigned int nodeCount, unsigned int *pCoreCount, unsigned int **pNodeDistance, unsigned int *pProcessorGroups);
/// <summary>
/// The API returns after ensuring that all store buffers on processors that are running threads from this process,
/// are flushed. It does this by either calling a Win32 API that explictly does this on versions of Windows that
/// support the functionality, or by changing the protection on a page that is locked into the working set, forcing
/// a TB flush on all processors in question.
/// </summary>
void FlushStoreBuffers();
/// <summary>
/// Returns the TLS slot where information about an execution resource is supposed to be stored.
/// </summary>
/// <remarks>
/// Used to check whether SubscribeCurrentThread already has an execution resource on which it is running.
/// </remarks>
DWORD GetExecutionResourceTls() const
{
return m_threadProxyFactoryManager.GetExecutionResourceTls();
}
/// <summary>
/// Decrements the use count on a particular global core. Used for removal of external threads.
/// </summary>
void DecrementCoreUseCount(unsigned int nodeId, unsigned int coreIndex)
{
// NOTE: Caller is responsible for holding the RM lock!
GlobalCore * pGlobalCore = &(m_pGlobalNodes[nodeId].m_pCores[coreIndex]);
pGlobalCore->m_useCount--;
}
/// <summary>
/// Returns the current thread's node id and core id (relative to that node).
/// </summary>
unsigned int GetCurrentNodeAndCore(unsigned int * pCore);
/// <summary>
/// Returns the global subscription level of the underlying core.
/// </summary>
unsigned int CurrentSubscriptionLevel(unsigned int nodeId, unsigned int coreIndex);
/// <summary>
/// Returns true if there are any schedulers in the RM that need notifications sent, false, otherwise.
/// </summary>
bool SchedulersNeedNotifications()
{
return (m_numSchedulersNeedingNotifications > 0);
}
/// <summary>
/// Returns the number of schedulers that need core busy/idle notifications.
/// </summary>
unsigned int GetNumSchedulersForNotifications()
{
return m_numSchedulersNeedingNotifications;
}
/// <summary>
/// Wakes up the dynamic RM worker from a wait state.
/// </summary>
void WakeupDynamicRMWorker()
{
SetEvent(m_hDynamicRMEvent);
}
/// <summary>
/// Sends NotifyResourcesExternallyIdle/NotifyResourcesExternallyBusy notifications to the schedulers that
/// qualify for them, to let them know that the hardware resources allocated to them are in use or out of use
/// by other schedulers that share those resources.
/// </summary>
/// <param name ="pNewlyAllocatedProxy">
/// The newly allocated scheduler proxy, if one was just allocated.
/// </param>
void SendResourceNotifications(SchedulerProxy * pNewlyAllocatedProxy = NULL);
/// <summary>
/// Inform the resource manager that termination is happening.
/// </summary>
static void SetTerminating()
{
InterlockedExchange(&s_terminating, 1);
}
/// <summary>
/// Queries the resource manager to determine if termination is happening.
/// </summary>
static bool IsTerminating()
{
return (s_terminating != 0);
}
private:
// State that controls what the dynamic RM worker thread does.
enum DynamicRMWorkerState
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -