// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// ExecutionResource.h
//
// Part of the ConcRT Resource Manager -- this header file contains the internal definition for the
// execution resource.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#pragma once
namespace Concurrency
{
namespace details
{
#pragma warning(push)
#pragma warning(disable: 4265) // non-virtual destructor in base class
///
/// An abstraction for an execution resource -- an entity on top of which a single thread of execution (of whatever
/// type) runs.
///
class ExecutionResource final : public IExecutionResource
{
public:
///
/// Constructs a new execution resource.
///
///
/// The scheduler proxy this resource is created for. A scheduler proxy holds RM data associated with an instance of
/// a scheduler.
///
///
/// The processor node that this resource belongs to. The processor node is one among the nodes allocated to the
/// scheduler proxy.
///
///
/// The index into the array of cores for the processor node specified.
///
ExecutionResource(SchedulerProxy *pSchedulerProxy, SchedulerNode* pNode, unsigned int coreIndex);
///
/// Constructs a new execution resource.
///
///
/// The scheduler proxy this resource is created for. A scheduler proxy holds RM data associated with an instance of
/// a scheduler.
///
/// The parent execution resource representing this thread
/// scheduler proxy.
///
ExecutionResource(SchedulerProxy * pSchedulerProxy, ExecutionResource * pParentExecutionResource);
///
/// Destroys an execution resource.
///
~ExecutionResource()
{
ASSERT(m_numThreadSubscriptions == 0);
}
///
/// Returns a unique identifier for the node that the given execution resource belongs to. The identifier returned
/// will fall in the range [0, nodeCount] where nodeCount is the value returned from Concurrency::GetProcessorNodeCount.
///
virtual unsigned int GetNodeId() const
{
return m_nodeId;
}
///
/// Returns a unique identifier for the execution resource that this execution resource runs atop.
///
virtual unsigned int GetExecutionResourceId() const
{
return m_executionResourceId;
}
///
/// Called to indicate that a scheduler is done with an execution resource and wishes to return it to the resource manager.
///
///
/// The scheduler making the request to remove this execution resource.
///
virtual void Remove(IScheduler *pScheduler);
///
/// Returns the subscription level on the core that this execution resource represents
///
///
/// A current subscription level of the underlying execution resource.
///
virtual unsigned int CurrentSubscriptionLevel() const;
// **************************************************
// Internal
// **************************************************
///
/// Returns a pointer to the scheduler proxy this execution resource was created by.
///
SchedulerProxy * GetSchedulerProxy()
{
return m_pSchedulerProxy;
}
///
/// Returns the core index into the array of cores, for the node that this execution resource is part of.
///
unsigned int GetCoreIndex()
{
return m_coreIndex;
}
///
/// Retrieves a virtual processor root that contains this execution resource, if any.
///
VirtualProcessorRoot * GetVirtualProcessorRoot()
{
return m_pVirtualProcessorRoot;
}
///
/// Set this execution resource as current on this thread
///
void SetAsCurrent();
///
/// Clear the current execution resource on this thread.
///
void ResetCurrent();
///
/// Initializes the execution resource as either standalone or belonging to virtual processor root.
///
void MarkAsVirtualProcessorRoot(VirtualProcessorRoot * pVPRoot)
{
ASSERT(m_pVirtualProcessorRoot == NULL);
m_pVirtualProcessorRoot = pVPRoot;
}
///
/// Increments the number of external threads that run on this execution resource as well as
/// the number of fixed threads that are running on the underlying core.
///
///
/// This information is used to validate matching SubscribeCurrentThread/Release calls, as well as
/// to mark a core on which this resource runs as fixed (not-movable).
///
void IncrementUseCounts();
///
/// Called to update the crucial counts, which must be done under the RM lock.
///
void DecrementUseCounts();
protected:
// Guards critical regions of the Execution Resource
_NonReentrantLock m_lock;
// The previous affinity of the external thread
HardwareAffinity m_oldAffinity;
// The scheduler proxy associated with the scheduler for which
// this resource was created.
SchedulerProxy * m_pSchedulerProxy;
// Parent execution resource in the case of a nested subscribe
ExecutionResource * m_pParentExecutionResource;
// Virtual processor root that this execution resource is a part of, if any
VirtualProcessorRoot * m_pVirtualProcessorRoot;
// The value to use when external resource subscription of a virtual processor is removed
size_t m_tlsResetValue;
// The node to which this execution resource belongs.
unsigned int m_nodeId;
// The core index within this node.
unsigned int m_coreIndex;
// The hardware thread upon which this execution resource executes.
unsigned int m_executionResourceId;
// Number of subscription requests that have been received for this execution resource.
unsigned int m_numThreadSubscriptions;
private:
template friend class List;
// Intrusive links
ExecutionResource * m_pPrev{}, * m_pNext{};
};
#pragma warning(pop)
} // namespace details
} // namespace Concurrency