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

  1. /***************************************************************************\
  2. *
  3. * File: Context.inl
  4. *
  5. * History:
  6. * 4/18/2000: JStall: Created
  7. *
  8. * Copyright (C) 2000 by Microsoft Corporation. All rights reserved.
  9. *
  10. \***************************************************************************/
  11. #if !defined(SERVICES__Context_inl__INCLUDED)
  12. #define SERVICES__Context_inl__INCLUDED
  13. #pragma once
  14. #include "Thread.h"
  15. #if !USE_DYNAMICTLS
  16. extern __declspec(thread) Context * t_pContext;
  17. #endif
  18. /***************************************************************************\
  19. *****************************************************************************
  20. *
  21. * class Context
  22. *
  23. *****************************************************************************
  24. \***************************************************************************/
  25. //------------------------------------------------------------------------------
  26. inline Context *
  27. GetContext()
  28. {
  29. #if USE_DYNAMICTLS
  30. Assert(IsInitThread());
  31. Context * pContext = GetThread()->GetContext();
  32. #else
  33. Context * pContext = t_pContext;
  34. #endif
  35. AssertMsg(pContext != NULL, "Using uninitialized Context");
  36. return pContext;
  37. }
  38. //------------------------------------------------------------------------------
  39. __forceinline Context *
  40. RawGetContext()
  41. {
  42. #if USE_DYNAMICTLS
  43. Thread * pthr = RawGetThread();
  44. if (pthr != NULL) {
  45. return pthr->GetContext();
  46. } else {
  47. return (Context *) pthr;
  48. }
  49. #else
  50. return t_pContext;
  51. #endif
  52. }
  53. //------------------------------------------------------------------------------
  54. inline BOOL
  55. IsInitContext()
  56. {
  57. #if USE_DYNAMICTLS
  58. Thread * pthr = RawGetThread();
  59. return (pthr != NULL) && (pthr->GetContext() != NULL);
  60. #else
  61. return t_pContext != NULL;
  62. #endif
  63. }
  64. //------------------------------------------------------------------------------
  65. inline Context *
  66. CastContext(BaseObject * pbase)
  67. {
  68. if ((pbase != NULL) && (pbase->GetHandleType() == htContext)) {
  69. return (Context *) pbase;
  70. }
  71. return NULL;
  72. }
  73. //------------------------------------------------------------------------------
  74. inline const Context *
  75. CastContext(const BaseObject * pbase)
  76. {
  77. if ((pbase != NULL) && (pbase->GetHandleType() == htContext)) {
  78. return (const Context *) pbase;
  79. }
  80. return NULL;
  81. }
  82. //------------------------------------------------------------------------------
  83. inline void
  84. Context::MarkOrphaned()
  85. {
  86. // NOTE: A Context may be orphaned multiple times from different threads.
  87. m_fOrphaned = TRUE;
  88. }
  89. //------------------------------------------------------------------------------
  90. inline BOOL
  91. Context::IsOrphanedNL() const
  92. {
  93. return m_fOrphaned;
  94. }
  95. //------------------------------------------------------------------------------
  96. inline void
  97. Context::Enter()
  98. {
  99. AssertMsg(m_cRef > 0, "Context must be valid to be locked");
  100. m_lock.Enter();
  101. Lock();
  102. if (m_cEnterLock++ == 0) {
  103. //
  104. // Just entered, so no deferred callbacks yet.
  105. //
  106. m_fPending = FALSE;
  107. }
  108. #if DBG
  109. if (m_cEnterLock > 30) {
  110. Trace("WARNING: DUser: m_cEnterLock is getting high (%d) for Context 0x%p.\n", m_cEnterLock, this);
  111. Trace(" Probably have an Enter() without an matching Leave().\n");
  112. }
  113. #endif
  114. #if DBG
  115. m_DEBUG_pthrLock = IsInitThread() ? GetThread() : (Thread *) (void *) 0x12345678;
  116. m_DEBUG_tidLock = GetCurrentThreadId();
  117. #endif // DBG
  118. }
  119. //------------------------------------------------------------------------------
  120. inline void
  121. Context::Leave()
  122. {
  123. #if DBG
  124. m_DEBUG_pthrLock = NULL;
  125. m_DEBUG_tidLock = 0;
  126. #endif // DBG
  127. AssertMsg(m_cEnterLock > 0, "Must have a matching Enter() for every Leave()");
  128. --m_cEnterLock;
  129. AssertMsg(m_cRef > 0, "Context should still be valid when unlocked");
  130. if (xwUnlock()) {
  131. //
  132. // Only can access the object if it is still valid after being
  133. // xwUnlock()'d.
  134. //
  135. m_lock.Leave();
  136. }
  137. }
  138. //------------------------------------------------------------------------------
  139. inline void
  140. Context::Leave(BOOL fOldEnableDefer, BOOL * pfPending)
  141. {
  142. #if DBG
  143. m_DEBUG_pthrLock = NULL;
  144. m_DEBUG_tidLock = 0;
  145. #endif // DBG
  146. AssertMsg(m_cEnterLock > 0, "Must have a matching Enter() for every Leave()");
  147. *pfPending = (--m_cEnterLock == 0) && m_fPending && m_fEnableDefer; // Must --m_cEnterLock first
  148. m_fEnableDefer = fOldEnableDefer;
  149. AssertMsg(m_cRef > 0, "Context should still be valid when unlocked");
  150. if (xwUnlock()) {
  151. //
  152. // Only can access the object if it is still valid after being
  153. // xwUnlock()'d.
  154. //
  155. m_lock.Leave();
  156. }
  157. }
  158. //------------------------------------------------------------------------------
  159. inline DUserHeap *
  160. Context::GetHeap() const
  161. {
  162. AssertMsg(m_pHeap != NULL, "Heap should be specified for Context");
  163. return m_pHeap;
  164. }
  165. //------------------------------------------------------------------------------
  166. inline SubContext *
  167. Context::GetSC(ESlot slot) const
  168. {
  169. return m_rgSCs[slot];
  170. }
  171. #if DBG_CHECK_CALLBACKS
  172. //------------------------------------------------------------------------------
  173. inline void
  174. Context::BeginCallback()
  175. {
  176. m_cLiveCallbacks++;
  177. }
  178. //------------------------------------------------------------------------------
  179. inline void
  180. Context::EndCallback()
  181. {
  182. Assert(m_cLiveCallbacks > 0);
  183. m_cLiveCallbacks--;
  184. }
  185. #endif // DBG_CHECK_CALLBACKS
  186. //------------------------------------------------------------------------------
  187. inline void
  188. Context::BeginReadOnly()
  189. {
  190. AssertMsg(m_cEnterLock > 0, "Must have Enter()'d the context before making read-only");
  191. m_cReadOnly++;
  192. }
  193. //------------------------------------------------------------------------------
  194. inline void
  195. Context::EndReadOnly()
  196. {
  197. Assert(m_cEnterLock > 0);
  198. m_cReadOnly--;
  199. }
  200. //------------------------------------------------------------------------------
  201. inline BOOL
  202. Context::IsReadOnly() const
  203. {
  204. return m_cReadOnly;
  205. }
  206. //------------------------------------------------------------------------------
  207. inline UINT
  208. Context::GetThreadMode() const
  209. {
  210. return m_nThreadMode;
  211. }
  212. //------------------------------------------------------------------------------
  213. inline UINT
  214. Context::GetPerfMode() const
  215. {
  216. return m_nPerfMode;
  217. }
  218. //------------------------------------------------------------------------------
  219. inline BOOL
  220. Context::IsEnableDefer() const
  221. {
  222. return m_fEnableDefer;
  223. }
  224. //------------------------------------------------------------------------------
  225. __forceinline void
  226. Context::EnableDefer(BOOL fEnable, BOOL * pfOld)
  227. {
  228. if (pfOld != NULL) {
  229. *pfOld = m_fEnableDefer;
  230. }
  231. m_fEnableDefer = fEnable;
  232. }
  233. //------------------------------------------------------------------------------
  234. inline void
  235. Context::MarkPending()
  236. {
  237. AssertMsg(m_fEnableDefer, "Deferred callbacks must be enabled");
  238. m_fPending = TRUE;
  239. }
  240. /***************************************************************************\
  241. *****************************************************************************
  242. *
  243. * class SubContext
  244. *
  245. *****************************************************************************
  246. \***************************************************************************/
  247. //------------------------------------------------------------------------------
  248. inline void
  249. SubContext::SetParent(Context * pParent)
  250. {
  251. AssertMsg(m_pParent == NULL, "Must set only once");
  252. m_pParent = pParent;
  253. }
  254. /***************************************************************************\
  255. *****************************************************************************
  256. *
  257. * class ContextPackBuilder
  258. *
  259. *****************************************************************************
  260. \***************************************************************************/
  261. //------------------------------------------------------------------------------
  262. inline ContextPackBuilder *
  263. ContextPackBuilder::GetBuilder(Context::ESlot slot)
  264. {
  265. AssertMsg(s_rgBuilders[slot] != NULL, "Build must be defined");
  266. return s_rgBuilders[slot];
  267. }
  268. /***************************************************************************\
  269. *****************************************************************************
  270. *
  271. * Various lock helpers
  272. *
  273. *****************************************************************************
  274. \***************************************************************************/
  275. //------------------------------------------------------------------------------
  276. inline
  277. ContextLock::ContextLock()
  278. {
  279. pctx = NULL;
  280. }
  281. //------------------------------------------------------------------------------
  282. inline
  283. ContextLock::~ContextLock()
  284. {
  285. if (pctx != NULL) {
  286. //
  287. // Leaving the lock, so notify the Thread and give it a chance to do
  288. // anything it needed afterwards.
  289. //
  290. BOOL fPending;
  291. pctx->Leave(fOldDeferred, &fPending);
  292. if (fPending) {
  293. GetThread()->xwLeftContextLockNL();
  294. }
  295. }
  296. }
  297. //------------------------------------------------------------------------------
  298. inline
  299. ReadOnlyLock::ReadOnlyLock(Context * pctxThread)
  300. {
  301. pctx = pctxThread;
  302. pctx->BeginReadOnly();
  303. }
  304. //------------------------------------------------------------------------------
  305. inline
  306. ReadOnlyLock::~ReadOnlyLock()
  307. {
  308. pctx->EndReadOnly();
  309. }
  310. #endif // SERVICES__Context_inl__INCLUDED