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.

287 lines
7.2 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 1999 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * critsec.hpp
  8. *
  9. * Abstract:
  10. *
  11. * Critical Section object for protecting LoadLibrary calls
  12. *
  13. * Revision History:
  14. *
  15. * 3/17/2000 asecchia
  16. * Created it.
  17. *
  18. \**************************************************************************/
  19. #ifndef _CRITSEC_HPP
  20. #define _CRITSEC_HPP
  21. // !!! [agodfrey]: We should establish a ranking of critical sections and
  22. // assert that it doesn't get inverted.
  23. // Here's a start:
  24. //
  25. // GdiplusStartupCriticalSection
  26. // BackgroundThreadCriticalSection
  27. //
  28. // (e.g. to acquire both BackgroundThreadCriticalSection and
  29. // GdiplusStartupCriticalSection, acquire GdiplusStartupCriticalSection
  30. // first, and release it last.)
  31. // This is a CriticalSection Proxy designed to
  32. // automatically acquire the critical section
  33. // when the instance is created and release
  34. // it when it goes out of scope.
  35. class LoadLibraryCriticalSection
  36. {
  37. public:
  38. static VOID InitializeCriticalSection()
  39. {
  40. __try
  41. {
  42. ::InitializeCriticalSection(&critSec);
  43. }
  44. __except(EXCEPTION_CONTINUE_SEARCH)
  45. {
  46. }
  47. // If we throw then initialized will be false;
  48. // It's the caller's responsability to ensure that the throw is caught
  49. initialized = TRUE;
  50. }
  51. static VOID DeleteCriticalSection()
  52. {
  53. if (initialized)
  54. {
  55. ::DeleteCriticalSection(&critSec);
  56. initialized = FALSE;
  57. }
  58. }
  59. LoadLibraryCriticalSection()
  60. {
  61. ASSERT(initialized);
  62. EnterCriticalSection(&critSec);
  63. }
  64. ~LoadLibraryCriticalSection()
  65. {
  66. ASSERT(initialized);
  67. LeaveCriticalSection(&critSec);
  68. }
  69. private:
  70. static CRITICAL_SECTION critSec;
  71. static BOOL initialized;
  72. };
  73. // This is a CriticalSection Proxy used for GdiplusStartup and GdiplusShutdown.
  74. class GdiplusStartupCriticalSection
  75. {
  76. public:
  77. static VOID InitializeCriticalSection()
  78. {
  79. __try
  80. {
  81. ::InitializeCriticalSection(&critSec);
  82. }
  83. __except(EXCEPTION_CONTINUE_SEARCH)
  84. {
  85. }
  86. // If we throw then initialized will be false;
  87. // It's the caller's responsability to ensure that the throw is caught
  88. initialized = TRUE;
  89. }
  90. static VOID DeleteCriticalSection()
  91. {
  92. if (initialized)
  93. {
  94. ::DeleteCriticalSection(&critSec);
  95. initialized = FALSE;
  96. }
  97. }
  98. GdiplusStartupCriticalSection()
  99. {
  100. ASSERT(initialized);
  101. EnterCriticalSection(&critSec);
  102. }
  103. ~GdiplusStartupCriticalSection()
  104. {
  105. ASSERT(initialized);
  106. LeaveCriticalSection(&critSec);
  107. }
  108. private:
  109. static CRITICAL_SECTION critSec;
  110. static BOOL initialized;
  111. };
  112. // [agodfrey] This is a CriticalSection Proxy used for globals touched
  113. // by the background thread. We can't use GdiplusStartupCriticalSection for
  114. // these, because (at least as things are now) the background thread can't
  115. // acquire GdiplusStartupCriticalSection.
  116. //
  117. // If it did, we could deadlock when we wait for the background thread to
  118. // finish.
  119. class BackgroundThreadCriticalSection
  120. {
  121. public:
  122. static VOID InitializeCriticalSection()
  123. {
  124. __try
  125. {
  126. ::InitializeCriticalSection(&critSec);
  127. }
  128. __except(EXCEPTION_CONTINUE_SEARCH)
  129. {
  130. }
  131. // If we throw then initialized will be false;
  132. // It's the caller's responsability to ensure that the throw is caught
  133. initialized = TRUE;
  134. }
  135. static VOID DeleteCriticalSection()
  136. {
  137. if (initialized)
  138. {
  139. ::DeleteCriticalSection(&critSec);
  140. initialized = FALSE;
  141. }
  142. }
  143. BackgroundThreadCriticalSection()
  144. {
  145. ASSERT(initialized);
  146. EnterCriticalSection(&critSec);
  147. }
  148. ~BackgroundThreadCriticalSection()
  149. {
  150. ASSERT(initialized);
  151. LeaveCriticalSection(&critSec);
  152. }
  153. private:
  154. static CRITICAL_SECTION critSec;
  155. static BOOL initialized;
  156. };
  157. // This is a CriticalSection Proxy designed to
  158. // automatically acquire the critical section
  159. // when the instance is created and release
  160. // it when it goes out of scope.
  161. // NB: this critical section should only be used for the malloc tracking
  162. // code. If you use it for anything else, then you should probably make sure you
  163. // don't allocate or free memory under this critsec.
  164. class GpMallocTrackingCriticalSection
  165. {
  166. public:
  167. static VOID InitializeCriticalSection()
  168. {
  169. // Only call InitializeCriticalSection if this is the first
  170. // time we're calling this code.
  171. // Note: this refCount thing is not actually thread safe, but
  172. // we only call this from our dllinit function so we should be
  173. // ok.
  174. // The refcount can tell us if the critical section is initialized
  175. if(refCount==0)
  176. {
  177. __try
  178. {
  179. ::InitializeCriticalSection(&critSec);
  180. }
  181. __except(EXCEPTION_CONTINUE_SEARCH)
  182. {
  183. }
  184. }
  185. refCount++;
  186. }
  187. static VOID DeleteCriticalSection()
  188. {
  189. // Decrement the refCount. If it hits zero,
  190. // delete the critical section.
  191. refCount--;
  192. // If the refCount is ever negative that means we're being called
  193. // to delete the critical section without ever having initialized it.
  194. #if DBG
  195. if(refCount<0)
  196. {
  197. // !!! [asecchia] don't know if deleting an uninitialized critical
  198. // section is bad or not. This could happen if we failed
  199. // initialization somewhere and we're trying to clean up
  200. // afterward.
  201. WARNING(("Trying to delete the GpMallocTrackingCriticalSection without initializing it first"));
  202. }
  203. #endif
  204. if(refCount==0)
  205. {
  206. ::DeleteCriticalSection(&critSec);
  207. }
  208. }
  209. GpMallocTrackingCriticalSection()
  210. {
  211. // Entering the critical section without first having called
  212. // InitializeCriticalSection will cause a crash.
  213. ASSERT(refCount>0);
  214. EnterCriticalSection(&critSec);
  215. }
  216. ~GpMallocTrackingCriticalSection()
  217. {
  218. // Leaving the critical section without first having called
  219. // InitializeCriticalSection will cause a crash.
  220. ASSERT(refCount>0);
  221. LeaveCriticalSection(&critSec);
  222. }
  223. private:
  224. static CRITICAL_SECTION critSec;
  225. // This critical section is initialized in imaging.dll and gdiplus.dll.
  226. // The gdiplus initialization code initializes the imaging module.
  227. // To avoid initializing and deleting this critical section more
  228. // than once, we refcount it.
  229. // !!! [agodfrey]: Now that we've eliminated imaging.dll, I don't think
  230. // we need this refcount.
  231. static INT refCount;
  232. };
  233. #endif