// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== // =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ // // UMSFreeThreadProxy.h // // Proxy for a UMS thread on a free scheduler. // // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- namespace Concurrency { namespace details { /// /// Representation of a thread running on a virtual processor root for a UMS free scheduler. /// #pragma warning(push) #pragma warning(disable: 4324) // structure was padded due to alignment specifier class UMSFreeThreadProxy : public UMSThreadProxy { public: /// /// Constructs a thread proxy for a UMS free scheduler. /// /// /// The thread proxy factory that created this thread proxy, and maintains the idle pool of thread proxies. /// /// /// 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. /// /// /// The stack size of the created thread. /// UMSFreeThreadProxy(IThreadProxyFactory * pFactory, PUMS_COMPLETION_LIST pStartupList, unsigned int stackSize) : UMSThreadProxy(pFactory, pStartupList, stackSize) { } /// /// Destroys a thread proxy for a UMS free scheduler. /// virtual ~UMSFreeThreadProxy() { } /// /// Returns our understanding of a UMS context (a UMS thread proxy) from the UMS system's understanding (a UMS_CONTEXT). Note /// that this performs no validation that it's actually a *FREE* proxy underneath. It is the caller's responsibility to ensure /// this prior to making the call! /// /// /// UMS context /// /// /// Pointer to a UMS thread proxy /// static UMSFreeThreadProxy *FromUMSContext(PUMS_CONTEXT pUMSContext) { return static_cast (UMSThreadProxy::FromUMSContext(pUMSContext)); } /// /// Called in order to perform a cooperative context switch between one context and another. After this call, pContext will /// be running atop the virtual processor root and the context which was running will not. What happens to the context that /// was running depends on the value of the reason argument. /// /// /// The context to cooperatively switch to. /// /// /// Indicates the state of the thread proxy that is executing the switch. This can determine ownership of the underlying thread /// proxy and context. /// virtual void SwitchTo(::Concurrency::IExecutionContext * pContext, SwitchingProxyState switchState); /// /// Called in order to disassociate the currently executing context from its virtual processor root, and reinitialize the root /// for future use. /// /// /// Indicates the state of the thread proxy that is executing the switch. This can determine ownership of the underlying thread /// proxy and context. /// virtual void SwitchOut(SwitchingProxyState switchState = Blocking); /// /// Called in order to yield to the underlying operating system. This allows the operating system to schedule /// other work in that time quantum. /// virtual void YieldToSystem(); /// /// Returns the context associated with the thread proxy. This is called from an IUMSUnblockNotification to get the context which /// unblocked (from the scheduler side) so that it can be SwitchTo'd. /// IExecutionContext *GetContext() { return m_pContext; } /// /// Set the thread affinity to the given affinity /// /// /// The new affinity for the thread /// void SetAffinity(HardwareAffinity newAffinity) { // // Since the ApplyTo call is SO expensive (relative to a pure user mode context switch), only make it if the affinity on the previous execution // is different. Different virtual processors may have the same affinity mask (currently likely if they're cores on the same package). // if (m_previousAffinity != newAffinity) { newAffinity.ApplyTo(GetThreadHandle()); } m_previousAffinity = newAffinity; } protected: // The context that this thread proxy is executing. ::Concurrency::IExecutionContext *m_pContext; private: template friend class LockFreeStack; friend class UMSFreeVirtualProcessorRoot; friend class UMSSchedulerProxy; friend class TransmogrifiedPrimary; /// /// Entry for freelist /// SLIST_ENTRY m_slNext; /// /// Affinity that was set for this UT /// HardwareAffinity m_previousAffinity; /// /// The main dispatch routine for a free thread proxy /// virtual void Dispatch(); /// /// Called right after obtaining a thread proxy from the factory. Associates the thread proxy with the execution /// context it is about to run. /// /// /// The context to associate with the thread proxy. /// void AssociateExecutionContext(::Concurrency::IExecutionContext * pContext); /// /// Returns a thread proxy to the factory when it is no longer in use. /// void ReturnIdleProxy(); }; #pragma warning(pop) } // namespace details } // namespace Concurrency