Channels ▼
RSS

.NET

Concurrency Runtime (CRT): The Resource Manager


Resource Allocation Workflow

Step 1: Get Resources Information From the System

The ResourceManager needs all physical information concerning processors and cores when allocating resources for schedulers. Let's examines the data manipulated by this component.


SELECT FIELDS WHERE IsDirectlyUsedBy "Concurrency.details.ResourceManager"

[Click image to view at full size]

These structs represent all data needed by ResourceManager. The basic ones are ProcessorCore and ProcessorNode representing information about physical resources. Other structs contains some scheduler data needed for the allocation algorithm.

The good news is that ResourceManager didn't directly access to fields of other logical classes used by it. Let's examine where ResourceManager gets basic information about physical resources. To do so, you can search for methods using GetLogicalProcessorInformation.


SELECT METHODS WHERE IsDirectlyUsing "WindowsAPIGlobalMembers.GetLogicalProcessorInformation(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION,PDWORD)"

[Click image to view at full size]

Only ResourceManager::InitializeSystemInformation uses this method to get information from the system. So what method is responsible for populating ProcessorCore and ProcessorNode.

For that, you can search for methods assigning a field of ProcessorCore:


SELECT METHODS WHERE IsDirectlyWritingField "Concurrency.details.ProcessorCore.m_processorNumber"

[Click image to view at full size]

So ResourceManager invokes the DetermineTopology method to populate data into structs. Here's a dependency graph showing methods concerned by getting nodes and cores information.

[Click image to view at full size]

Step 2: Scheduler Requests for Resource Allocation

After ResourceManager gets all the data needed for allocation algorithm, a scheduler can ask it to allocate ressources. When the Scheduler is created, it asks for a ResourceManager and invoke CreateResourceManager to get the singleton. After that it invokes IResourceManager::RegisterScheduler to register it self with the resource manager, and get a pointer to ISchedulerProxy, and with this interface the Scheduler will interact with the resource manager. After that the Scheduler is ready to ask for resources allocation by invoking RequestInitialVirtualProcessors.

[Click image to view at full size]

Again, the Scheduler communicates with resource manager using the IScheduleProxy interface to enforces low coupling, and the concrete implemenatation of this interface invoke ResourceManager::RequestInitialVirtualprocessors.

[Click image to view at full size]

Step 3: Resource Allocation

The ResourceManager has to give resources to Schedulers when Schedulers are created. It does the allocation depending on the policies and taking into account the other schedulers in the process. Eventually the resources will be provided to the scheduler in need.

The entry point for allocating requests is RequestInitialVirtualProcessors. Here's a dependency graph showing methods used to acheive allocation.

[Click image to view at full size]

The PerformAllocation method implements the allocation logic, it asks for Scheduler policies from SchedulerProxy, and invokes the AllocateCores method to perform allocation. Here are some characteristics of PerformAllocation and AllocateCores:

[Click image to view at full size]

Those methods are well documented and the cyclomatic complexity is not high. This a good indicator that the algorithm of initial allocation is not very complicated.

Step 4: Giving Resources to Scheduler

After ResourceManager allocates resources, the scheduler is notified with resources allocated. For that, the ResourceManager invokes the GrantAllocation method.

[Click image to view at full size]

What resources the ResourceManager have to give to Scheduler?

Well, the resource is a virtual processor associated to a specific thread and runing in a specific core. As shown in the dependency graph, the ResourceManager doesn't give VirtualProcessors to SchedulerProxy, but an array of SchedulerNodes. SchedulerProxy creates VirtualProcessorRoot classes, which represents an abstraction for a hardware thread on which a thread proxy can execute.

Who is creating VirtualProcessor? Before answering this question, let's search for classes that represent a virtual processor, starting with classes inheriting from this one.

[Click image to view at full size]

So VirtualProcessor could concern a simple thread or an User-Mode Scheduling (UMS) thread -- a lightweight mechanism introduced in Windows7 and Windows Server 2008 R2, that applications can use to schedule their own threads. Let's search for methods creating ThreadVirtualProcessor.

[Click image to view at full size]

So the Scheduler is the responsible of creating VirtualProcessors and all information needed to create it are given by the manager.

Step 5: Dynamic Resource Management

After the initial allocation of resources, the second main responsability of ResourceManager is constant monitoring of the utilization of resources by schedulers, and dynamically migrating resources between schedulers.

[Click image to view at full size]

As shown in the following graph, the ResourceManager creates DynamicResourceManage thread. This worker thread wakes up at fixed intervals and load balances resources among schedulers. Here's the dependency graph of DynamicResourceManager:

[Click image to view at full size]

Is ResourceManager customizable?

ResourceManager is well designed and is decoupled from other Concurrency Runtime framework by using interfaces, but it's possible to customize the allocation behavior of resource manager. For that let's search for ResourceManager virtual methods:


SELECT METHODS FROM TYPES "Concurrency.details.ResourceManager" WHERE IsVirtual

[Click image to view at full size]

However, these methods are virtual and only implement the IResourceManager methods, so it's not possible to overload allocation resource manager logic and customize it.


Lahlali Issam is the developer of CppDepend code analysis tool for C/C++.


For more on CRT, see Concurrency Runtime (CRT): The Task Scheduler


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video