// ==++==
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// ==--==
// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
//
// UMSSchedulingContext.h
//
// Header file for the UMS scheduling context. This is a special context whose sole purpose in life is to determine
// which context to run next at initial startup of a virtual processor and whenever a UMS thread running on the virtual
// processor blocks. The RM will invoke this scheduling context whenever a return to primary happens.
//
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
#pragma once
namespace Concurrency
{
namespace details
{
#pragma warning(push)
#pragma warning(disable: 4265) // non-virtual destructor in base class
class UMSSchedulingContext final : public ::Concurrency::IExecutionContext
{
public:
///
/// Creates a new UMS scheduling context that is bound to a particular virtual processor. Once the scheduling context
/// is created, it is always bound to the virtual processor used at creation time.
///
///
/// The scheduler to which this virtual processor belongs.
///
///
/// The virtual processor to which this scheduling context is bound.
///
UMSSchedulingContext(UMSThreadScheduler *pScheduler, UMSThreadVirtualProcessor *pBoundVProc);
///
/// Destroys a UMS scheduling context.
///
~UMSSchedulingContext()
{
}
///
/// Returns a scheduler unique identifier for the context.
///
///
/// The Id of the context.
///
virtual unsigned int GetId() const;
///
/// Returns the scheduler to which this context belongs.
///
///
/// The owning scheduler.
///
virtual IScheduler * GetScheduler();
///
/// Returns the thread proxy which is executing this context. Until the SetProxy method has been called on the given
/// context, this will return NULL. Once the SetProxy method has been called, this returns the IThreadProxy which
/// was passed into the SetProxy method.
///
///
/// The thread proxy which dispatched this particular context.
///
///
/// An indication of success.
///
virtual IThreadProxy * GetProxy();
///
/// Sets the thread proxy which is executing this context. The caller must save this and return it upon a call to the GetProxy method.
/// Note that the resource manager guarantees stability of the thread proxy while inside the Dispatch method.
///
///
/// The thread proxy which dispatched this particular context.
///
///
/// An indication of success.
///
virtual void SetProxy(IThreadProxy *pThreadProxy);
///
/// The method that is called when a thread proxy starts executing a particular context. The thread proxy which executes
/// the context is set in SetProxy before entering the dispatch loop and must be saved and returned on a call to the GetProxy method.
///
///
/// The state under which this IExecutionContext is being dispatched.
///
virtual void Dispatch(DispatchState * pDispatchState);
///
/// Returns whether we are on a primary thread.
///
static bool OnPrimary();
private:
///
/// Sets the current scheduling context to TLS.
///
void SetAsCurrentTls()
{
TlsSetValue(UMSThreadScheduler::t_dwSchedulingContextIndex, this);
}
///
/// Sets all blocked status on a given context.
///
///
/// The previously running context.
///
///
/// Is previously running context asynchronously blocked.
///
void SetUMSBlocked(UMSThreadInternalContext *pPreviousContext, bool fAsynchronous);
///
/// Claims the bound virtual processor and swallows an activation.
///
void ClaimBoundProcessorAndSwallowActivation();
// Unique identifier
unsigned int m_id;
// The scheduler to which we belong.
UMSThreadScheduler *m_pScheduler;
// The virtual processor to which this context is bound.
UMSThreadVirtualProcessor *m_pBoundVProc;
// The underlying thread proxy.
IThreadProxy *m_pThreadProxy;
};
#pragma warning(pop)
} // namespace details
} // namespace Concurrency