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.

353 lines
6.2 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. cmsubs3.c
  5. Abstract:
  6. This module contains locking support routines for the configuration manager.
  7. Author:
  8. Bryan M. Willman (bryanwi) 30-Mar-1992
  9. Revision History:
  10. --*/
  11. #include "cmp.h"
  12. #ifdef ALLOC_PRAGMA
  13. #pragma alloc_text(PAGE,CmpLockRegistry)
  14. #pragma alloc_text(PAGE,CmpLockRegistryExclusive)
  15. #pragma alloc_text(PAGE,CmpLockKCB)
  16. #pragma alloc_text(PAGE,CmpLockKCBTree)
  17. #pragma alloc_text(PAGE,CmpLockKCBTreeExclusive)
  18. #pragma alloc_text(PAGE,CmpUnlockRegistry)
  19. #pragma alloc_text(PAGE,CmpUnlockKCB)
  20. #pragma alloc_text(PAGE,CmpUnlockKCBTree)
  21. #if DBG
  22. #pragma alloc_text(PAGE,CmpTestRegistryLock)
  23. #pragma alloc_text(PAGE,CmpTestRegistryLockExclusive)
  24. #pragma alloc_text(PAGE,CmpTestKCBTreeLockExclusive)
  25. #endif
  26. #endif
  27. //
  28. // Global registry lock
  29. //
  30. ERESOURCE CmpRegistryLock;
  31. EX_PUSH_LOCK CmpKcbLock;
  32. PKTHREAD CmpKcbOwner;
  33. #ifdef ALLOC_DATA_PRAGMA
  34. #pragma data_seg("PAGEDATA")
  35. #endif
  36. EX_PUSH_LOCK CmpKcbLocks[MAX_KCB_LOCKS] = {0};
  37. #ifdef ALLOC_DATA_PRAGMA
  38. #pragma data_seg()
  39. #endif
  40. LONG CmpFlushStarveWriters = 0;
  41. BOOLEAN CmpFlushOnLockRelease = FALSE;
  42. LONG CmRegistryLogSizeLimit = -1;
  43. #if DBG
  44. PVOID CmpRegistryLockCaller;
  45. PVOID CmpRegistryLockCallerCaller;
  46. PVOID CmpKCBLockCaller;
  47. PVOID CmpKCBLockCallerCaller;
  48. #endif //DBG
  49. extern BOOLEAN CmpSpecialBootCondition;
  50. VOID
  51. CmpLockRegistry(
  52. VOID
  53. )
  54. /*++
  55. Routine Description:
  56. Lock the registry for shared (read-only) access
  57. Arguments:
  58. None.
  59. Return Value:
  60. None, the registry lock will be held for shared access upon return.
  61. --*/
  62. {
  63. #if DBG
  64. PVOID Caller;
  65. PVOID CallerCaller;
  66. #endif
  67. KeEnterCriticalRegion();
  68. if( CmpFlushStarveWriters ) {
  69. //
  70. // a flush is in progress; starve potential writers
  71. //
  72. ExAcquireSharedStarveExclusive(&CmpRegistryLock, TRUE);
  73. } else {
  74. //
  75. // regular shared mode
  76. //
  77. ExAcquireResourceSharedLite(&CmpRegistryLock, TRUE);
  78. }
  79. #if DBG
  80. RtlGetCallersAddress(&Caller, &CallerCaller);
  81. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_LOCKING,"CmpLockRegistry: c, cc: %p %p\n", Caller, CallerCaller));
  82. #endif
  83. }
  84. VOID
  85. CmpLockRegistryExclusive(
  86. VOID
  87. )
  88. /*++
  89. Routine Description:
  90. Lock the registry for exclusive (write) access.
  91. Arguments:
  92. None.
  93. Return Value:
  94. TRUE - Lock was acquired exclusively
  95. FALSE - Lock is owned by another thread.
  96. --*/
  97. {
  98. KeEnterCriticalRegion();
  99. ExAcquireResourceExclusiveLite(&CmpRegistryLock,TRUE);
  100. ASSERT( CmpFlushStarveWriters == 0 );
  101. #if DBG
  102. RtlGetCallersAddress(&CmpRegistryLockCaller, &CmpRegistryLockCallerCaller);
  103. #endif //DBG
  104. }
  105. VOID
  106. CmpUnlockRegistry(
  107. )
  108. /*++
  109. Routine Description:
  110. Unlock the registry.
  111. --*/
  112. {
  113. ASSERT_CM_LOCK_OWNED();
  114. //
  115. // test if bit set to force flush; and we own the reglock exclusive and ownercount is 1
  116. //
  117. if( CmpFlushOnLockRelease && ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock) && (CmpRegistryLock.OwnerThreads[0].OwnerCount == 1) ) {
  118. //
  119. // we need to flush now
  120. //
  121. ASSERT_CM_LOCK_OWNED_EXCLUSIVE();
  122. CmpDoFlushAll(TRUE);
  123. CmpFlushOnLockRelease = FALSE;
  124. }
  125. ExReleaseResourceLite(&CmpRegistryLock);
  126. KeLeaveCriticalRegion();
  127. }
  128. #if DBG
  129. BOOLEAN
  130. CmpTestRegistryLock(VOID)
  131. {
  132. BOOLEAN rc;
  133. rc = TRUE;
  134. if (ExIsResourceAcquiredShared(&CmpRegistryLock) == 0) {
  135. rc = FALSE;
  136. }
  137. return rc;
  138. }
  139. BOOLEAN
  140. CmpTestRegistryLockExclusive(VOID)
  141. {
  142. if (ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock) == 0) {
  143. return(FALSE);
  144. }
  145. return(TRUE);
  146. }
  147. BOOLEAN
  148. CmpTestKCBTreeLockExclusive(VOID)
  149. {
  150. return ( CmpKcbOwner == KeGetCurrentThread() ? TRUE : FALSE);
  151. }
  152. #endif
  153. VOID
  154. CmpLockKCBTree(
  155. VOID
  156. )
  157. /*++
  158. Routine Description:
  159. Lock the KCB tree for shared (read-only) access
  160. Arguments:
  161. None.
  162. Return Value:
  163. None, the kcb lock will be held for shared access upon return.
  164. --*/
  165. {
  166. #if DBG
  167. PVOID Caller;
  168. PVOID CallerCaller;
  169. #endif
  170. //
  171. // we don't need to enter critical section here as we are already there
  172. // (i.e. kcb lock can be aquired only while holding the registry lock)
  173. //
  174. ExAcquirePushLockShared(&CmpKcbLock);
  175. #if DBG
  176. RtlGetCallersAddress(&Caller, &CallerCaller);
  177. CmKdPrintEx((DPFLTR_CONFIG_ID,CML_LOCKING,"CmpLockKCBTree: c, cc: %p %p\n", Caller, CallerCaller));
  178. #endif
  179. }
  180. VOID
  181. CmpLockKCBTreeExclusive(
  182. VOID
  183. )
  184. /*++
  185. Routine Description:
  186. Lock the KCB tree for exclusive (write) access.
  187. Arguments:
  188. None.
  189. Return Value:
  190. None, the kcb lock will be held for exclusive access upon return.
  191. --*/
  192. {
  193. //
  194. // we don't need to enter critical section here as we are already there
  195. // (i.e. kcb lock can be aquired only while holding the registry lock)
  196. //
  197. ExAcquirePushLockExclusive(&CmpKcbLock);
  198. CmpKcbOwner = KeGetCurrentThread();
  199. #if DBG
  200. RtlGetCallersAddress(&CmpKCBLockCaller, &CmpKCBLockCallerCaller);
  201. #endif //DBG
  202. }
  203. VOID
  204. CmpUnlockKCBTree(
  205. )
  206. /*++
  207. Routine Description:
  208. Unlock the KCB_TREE.
  209. --*/
  210. {
  211. if( CmpKcbOwner == KeGetCurrentThread() ) {
  212. CmpKcbOwner = NULL;
  213. }
  214. ExReleasePushLock(&CmpKcbLock);
  215. }
  216. VOID
  217. CmpLockKCB(
  218. PCM_KEY_CONTROL_BLOCK Kcb
  219. )
  220. /*++
  221. Routine Description:
  222. Lock an individual KCB exclusive by hashing the KCB address
  223. into an array of 1024 pushlocks
  224. Arguments:
  225. None.
  226. Return Value:
  227. None
  228. --*/
  229. {
  230. ExAcquirePushLockExclusive(&CmpKcbLocks[ (HASH_KEY( ((SIZE_T)Kcb)>>6 ))%MAX_KCB_LOCKS ]);
  231. }
  232. VOID
  233. CmpUnlockKCB(
  234. PCM_KEY_CONTROL_BLOCK Kcb
  235. )
  236. /*++
  237. Routine Description:
  238. Unlock an individual KCB exclusive by hashing the KCB address
  239. into an array of 1024 pushlocks
  240. Arguments:
  241. None.
  242. Return Value:
  243. None
  244. --*/
  245. {
  246. ExReleasePushLock(&CmpKcbLocks[ (HASH_KEY( ((SIZE_T)Kcb)>>6 ))%MAX_KCB_LOCKS ]);
  247. }