Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

389 lines
9.7 KiB

/***************************************************************************\
*
* File: Context.inl
*
* History:
* 4/18/2000: JStall: Created
*
* Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
*
\***************************************************************************/
#if !defined(SERVICES__Context_inl__INCLUDED)
#define SERVICES__Context_inl__INCLUDED
#pragma once
#include "Thread.h"
#if !USE_DYNAMICTLS
extern __declspec(thread) Context * t_pContext;
#endif
/***************************************************************************\
*****************************************************************************
*
* class Context
*
*****************************************************************************
\***************************************************************************/
//------------------------------------------------------------------------------
inline Context *
GetContext()
{
#if USE_DYNAMICTLS
Assert(IsInitThread());
Context * pContext = GetThread()->GetContext();
#else
Context * pContext = t_pContext;
#endif
AssertMsg(pContext != NULL, "Using uninitialized Context");
return pContext;
}
//------------------------------------------------------------------------------
__forceinline Context *
RawGetContext()
{
#if USE_DYNAMICTLS
Thread * pthr = RawGetThread();
if (pthr != NULL) {
return pthr->GetContext();
} else {
return (Context *) pthr;
}
#else
return t_pContext;
#endif
}
//------------------------------------------------------------------------------
inline BOOL
IsInitContext()
{
#if USE_DYNAMICTLS
Thread * pthr = RawGetThread();
return (pthr != NULL) && (pthr->GetContext() != NULL);
#else
return t_pContext != NULL;
#endif
}
//------------------------------------------------------------------------------
inline Context *
CastContext(BaseObject * pbase)
{
if ((pbase != NULL) && (pbase->GetHandleType() == htContext)) {
return (Context *) pbase;
}
return NULL;
}
//------------------------------------------------------------------------------
inline const Context *
CastContext(const BaseObject * pbase)
{
if ((pbase != NULL) && (pbase->GetHandleType() == htContext)) {
return (const Context *) pbase;
}
return NULL;
}
//------------------------------------------------------------------------------
inline void
Context::MarkOrphaned()
{
// NOTE: A Context may be orphaned multiple times from different threads.
m_fOrphaned = TRUE;
}
//------------------------------------------------------------------------------
inline BOOL
Context::IsOrphanedNL() const
{
return m_fOrphaned;
}
//------------------------------------------------------------------------------
inline void
Context::Enter()
{
AssertMsg(m_cRef > 0, "Context must be valid to be locked");
m_lock.Enter();
Lock();
if (m_cEnterLock++ == 0) {
//
// Just entered, so no deferred callbacks yet.
//
m_fPending = FALSE;
}
#if DBG
if (m_cEnterLock > 30) {
Trace("WARNING: DUser: m_cEnterLock is getting high (%d) for Context 0x%p.\n", m_cEnterLock, this);
Trace(" Probably have an Enter() without an matching Leave().\n");
}
#endif
#if DBG
m_DEBUG_pthrLock = IsInitThread() ? GetThread() : (Thread *) (void *) 0x12345678;
m_DEBUG_tidLock = GetCurrentThreadId();
#endif // DBG
}
//------------------------------------------------------------------------------
inline void
Context::Leave()
{
#if DBG
m_DEBUG_pthrLock = NULL;
m_DEBUG_tidLock = 0;
#endif // DBG
AssertMsg(m_cEnterLock > 0, "Must have a matching Enter() for every Leave()");
--m_cEnterLock;
AssertMsg(m_cRef > 0, "Context should still be valid when unlocked");
if (xwUnlock()) {
//
// Only can access the object if it is still valid after being
// xwUnlock()'d.
//
m_lock.Leave();
}
}
//------------------------------------------------------------------------------
inline void
Context::Leave(BOOL fOldEnableDefer, BOOL * pfPending)
{
#if DBG
m_DEBUG_pthrLock = NULL;
m_DEBUG_tidLock = 0;
#endif // DBG
AssertMsg(m_cEnterLock > 0, "Must have a matching Enter() for every Leave()");
*pfPending = (--m_cEnterLock == 0) && m_fPending && m_fEnableDefer; // Must --m_cEnterLock first
m_fEnableDefer = fOldEnableDefer;
AssertMsg(m_cRef > 0, "Context should still be valid when unlocked");
if (xwUnlock()) {
//
// Only can access the object if it is still valid after being
// xwUnlock()'d.
//
m_lock.Leave();
}
}
//------------------------------------------------------------------------------
inline DUserHeap *
Context::GetHeap() const
{
AssertMsg(m_pHeap != NULL, "Heap should be specified for Context");
return m_pHeap;
}
//------------------------------------------------------------------------------
inline SubContext *
Context::GetSC(ESlot slot) const
{
return m_rgSCs[slot];
}
#if DBG_CHECK_CALLBACKS
//------------------------------------------------------------------------------
inline void
Context::BeginCallback()
{
m_cLiveCallbacks++;
}
//------------------------------------------------------------------------------
inline void
Context::EndCallback()
{
Assert(m_cLiveCallbacks > 0);
m_cLiveCallbacks--;
}
#endif // DBG_CHECK_CALLBACKS
//------------------------------------------------------------------------------
inline void
Context::BeginReadOnly()
{
AssertMsg(m_cEnterLock > 0, "Must have Enter()'d the context before making read-only");
m_cReadOnly++;
}
//------------------------------------------------------------------------------
inline void
Context::EndReadOnly()
{
Assert(m_cEnterLock > 0);
m_cReadOnly--;
}
//------------------------------------------------------------------------------
inline BOOL
Context::IsReadOnly() const
{
return m_cReadOnly;
}
//------------------------------------------------------------------------------
inline UINT
Context::GetThreadMode() const
{
return m_nThreadMode;
}
//------------------------------------------------------------------------------
inline UINT
Context::GetPerfMode() const
{
return m_nPerfMode;
}
//------------------------------------------------------------------------------
inline BOOL
Context::IsEnableDefer() const
{
return m_fEnableDefer;
}
//------------------------------------------------------------------------------
__forceinline void
Context::EnableDefer(BOOL fEnable, BOOL * pfOld)
{
if (pfOld != NULL) {
*pfOld = m_fEnableDefer;
}
m_fEnableDefer = fEnable;
}
//------------------------------------------------------------------------------
inline void
Context::MarkPending()
{
AssertMsg(m_fEnableDefer, "Deferred callbacks must be enabled");
m_fPending = TRUE;
}
/***************************************************************************\
*****************************************************************************
*
* class SubContext
*
*****************************************************************************
\***************************************************************************/
//------------------------------------------------------------------------------
inline void
SubContext::SetParent(Context * pParent)
{
AssertMsg(m_pParent == NULL, "Must set only once");
m_pParent = pParent;
}
/***************************************************************************\
*****************************************************************************
*
* class ContextPackBuilder
*
*****************************************************************************
\***************************************************************************/
//------------------------------------------------------------------------------
inline ContextPackBuilder *
ContextPackBuilder::GetBuilder(Context::ESlot slot)
{
AssertMsg(s_rgBuilders[slot] != NULL, "Build must be defined");
return s_rgBuilders[slot];
}
/***************************************************************************\
*****************************************************************************
*
* Various lock helpers
*
*****************************************************************************
\***************************************************************************/
//------------------------------------------------------------------------------
inline
ContextLock::ContextLock()
{
pctx = NULL;
}
//------------------------------------------------------------------------------
inline
ContextLock::~ContextLock()
{
if (pctx != NULL) {
//
// Leaving the lock, so notify the Thread and give it a chance to do
// anything it needed afterwards.
//
BOOL fPending;
pctx->Leave(fOldDeferred, &fPending);
if (fPending) {
GetThread()->xwLeftContextLockNL();
}
}
}
//------------------------------------------------------------------------------
inline
ReadOnlyLock::ReadOnlyLock(Context * pctxThread)
{
pctx = pctxThread;
pctx->BeginReadOnly();
}
//------------------------------------------------------------------------------
inline
ReadOnlyLock::~ReadOnlyLock()
{
pctx->EndReadOnly();
}
#endif // SERVICES__Context_inl__INCLUDED