/*++ Copyright (c) 1991 Microsoft Corporation Module Name: cmsubs3.c Abstract: This module contains locking support routines for the configuration manager. Author: Bryan M. Willman (bryanwi) 30-Mar-1992 Revision History: --*/ #include "cmp.h" #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE,CmpLockRegistry) #pragma alloc_text(PAGE,CmpLockRegistryExclusive) #pragma alloc_text(PAGE,CmpLockKCBTree) #pragma alloc_text(PAGE,CmpLockKCBTreeExclusive) #pragma alloc_text(PAGE,CmpUnlockRegistry) #pragma alloc_text(PAGE,CmpUnlockKCBTree) #if DBG #pragma alloc_text(PAGE,CmpTestRegistryLock) #pragma alloc_text(PAGE,CmpTestRegistryLockExclusive) #pragma alloc_text(PAGE,CmpTestKCBLock) #pragma alloc_text(PAGE,CmpTestKCBLockExclusive) #endif #endif // // Global registry lock // ERESOURCE CmpRegistryLock; ERESOURCE CmpKcbLock; ULONG CmpFlushStarveWriters = 0; BOOLEAN CmpFlushOnLockRelease = FALSE; LONG CmRegistryLogSizeLimit = -1; #if DBG PVOID CmpRegistryLockCaller; PVOID CmpRegistryLockCallerCaller; PVOID CmpKCBLockCaller; PVOID CmpKCBLockCallerCaller; #endif //DBG extern BOOLEAN CmpSpecialBootCondition; VOID CmpLockRegistry( VOID ) /*++ Routine Description: Lock the registry for shared (read-only) access Arguments: None. Return Value: None, the registry lock will be held for shared access upon return. --*/ { #if DBG PVOID Caller; PVOID CallerCaller; #endif KeEnterCriticalRegion(); if( CmpFlushStarveWriters ) { // // a flush is in progress; starve potential writers // ExAcquireSharedStarveExclusive(&CmpRegistryLock, TRUE); } else { // // regular shared mode // ExAcquireResourceSharedLite(&CmpRegistryLock, TRUE); } #if DBG RtlGetCallersAddress(&Caller, &CallerCaller); CmKdPrintEx((DPFLTR_CONFIG_ID,CML_LOCKING,"CmpLockRegistry: c, cc: %p %p\n", Caller, CallerCaller)); #endif } VOID CmpLockRegistryExclusive( VOID ) /*++ Routine Description: Lock the registry for exclusive (write) access. Arguments: None. Return Value: TRUE - Lock was acquired exclusively FALSE - Lock is owned by another thread. --*/ { KeEnterCriticalRegion(); ExAcquireResourceExclusiveLite(&CmpRegistryLock,TRUE); ASSERT( CmpFlushStarveWriters == 0 ); #if DBG RtlGetCallersAddress(&CmpRegistryLockCaller, &CmpRegistryLockCallerCaller); #endif //DBG } VOID CmpUnlockRegistry( ) /*++ Routine Description: Unlock the registry. --*/ { ASSERT_CM_LOCK_OWNED(); // // test if bit set to force flush; and we own the reglock exclusive and ownercount is 1 // if( CmpFlushOnLockRelease && ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock) && (CmpRegistryLock.OwnerThreads[0].OwnerCount == 1) ) { // // we need to flush now // ASSERT_CM_LOCK_OWNED_EXCLUSIVE(); CmpDoFlushAll(TRUE); CmpFlushOnLockRelease = FALSE; } ExReleaseResourceLite(&CmpRegistryLock); KeLeaveCriticalRegion(); } #if DBG BOOLEAN CmpTestRegistryLock(VOID) { BOOLEAN rc; rc = TRUE; if (ExIsResourceAcquiredShared(&CmpRegistryLock) == 0) { rc = FALSE; } return rc; } BOOLEAN CmpTestRegistryLockExclusive(VOID) { if (ExIsResourceAcquiredExclusiveLite(&CmpRegistryLock) == 0) { return(FALSE); } return(TRUE); } #endif VOID CmpLockKCBTree( VOID ) /*++ Routine Description: Lock the KCB tree for shared (read-only) access Arguments: None. Return Value: None, the kcb lock will be held for shared access upon return. --*/ { #if DBG PVOID Caller; PVOID CallerCaller; #endif // // we don't need to enter critical section here as we are already there // (i.e. kcb lock can be aquired only while holding the registry lock) // ExAcquireResourceSharedLite(&CmpKcbLock, TRUE); #if DBG RtlGetCallersAddress(&Caller, &CallerCaller); CmKdPrintEx((DPFLTR_CONFIG_ID,CML_LOCKING,"CmpLockKCBTree: c, cc: %p %p\n", Caller, CallerCaller)); #endif } VOID CmpLockKCBTreeExclusive( VOID ) /*++ Routine Description: Lock the KCB tree for exclusive (write) access. Arguments: None. Return Value: None, the kcb lock will be held for exclusive access upon return. --*/ { // // we don't need to enter critical section here as we are already there // (i.e. kcb lock can be aquired only while holding the registry lock) // ExAcquireResourceExclusiveLite(&CmpKcbLock,TRUE); #if DBG RtlGetCallersAddress(&CmpKCBLockCaller, &CmpKCBLockCallerCaller); #endif //DBG } VOID CmpUnlockKCBTree( ) /*++ Routine Description: Unlock the KCB_TREE. --*/ { ASSERT_KCB_LOCK_OWNED(); ExReleaseResourceLite(&CmpKcbLock); } #if DBG BOOLEAN CmpTestKCBLock(VOID) { BOOLEAN rc; rc = TRUE; if (ExIsResourceAcquiredShared(&CmpKcbLock) == 0) { rc = FALSE; } return rc; } BOOLEAN CmpTestKCBLockExclusive(VOID) { if (ExIsResourceAcquiredExclusiveLite(&CmpKcbLock) == 0) { return(FALSE); } return(TRUE); } #endif