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

/*++
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,CmpLockKCB)
#pragma alloc_text(PAGE,CmpLockKCBTree)
#pragma alloc_text(PAGE,CmpLockKCBTreeExclusive)
#pragma alloc_text(PAGE,CmpUnlockRegistry)
#pragma alloc_text(PAGE,CmpUnlockKCB)
#pragma alloc_text(PAGE,CmpUnlockKCBTree)
#if DBG
#pragma alloc_text(PAGE,CmpTestRegistryLock)
#pragma alloc_text(PAGE,CmpTestRegistryLockExclusive)
#pragma alloc_text(PAGE,CmpTestKCBTreeLockExclusive)
#endif
#endif
//
// Global registry lock
//
ERESOURCE CmpRegistryLock;
EX_PUSH_LOCK CmpKcbLock;
PKTHREAD CmpKcbOwner;
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg("PAGEDATA")
#endif
EX_PUSH_LOCK CmpKcbLocks[MAX_KCB_LOCKS] = {0};
#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg()
#endif
LONG 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);
}
BOOLEAN
CmpTestKCBTreeLockExclusive(VOID)
{
return ( CmpKcbOwner == KeGetCurrentThread() ? TRUE : FALSE);
}
#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)
//
ExAcquirePushLockShared(&CmpKcbLock);
#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)
//
ExAcquirePushLockExclusive(&CmpKcbLock);
CmpKcbOwner = KeGetCurrentThread();
#if DBG
RtlGetCallersAddress(&CmpKCBLockCaller, &CmpKCBLockCallerCaller);
#endif //DBG
}
VOID
CmpUnlockKCBTree(
)
/*++
Routine Description:
Unlock the KCB_TREE.
--*/
{
if( CmpKcbOwner == KeGetCurrentThread() ) {
CmpKcbOwner = NULL;
}
ExReleasePushLock(&CmpKcbLock);
}
VOID
CmpLockKCB(
PCM_KEY_CONTROL_BLOCK Kcb
)
/*++
Routine Description:
Lock an individual KCB exclusive by hashing the KCB address
into an array of 1024 pushlocks
Arguments:
None.
Return Value:
None
--*/
{
ExAcquirePushLockExclusive(&CmpKcbLocks[ (HASH_KEY( ((SIZE_T)Kcb)>>6 ))%MAX_KCB_LOCKS ]);
}
VOID
CmpUnlockKCB(
PCM_KEY_CONTROL_BLOCK Kcb
)
/*++
Routine Description:
Unlock an individual KCB exclusive by hashing the KCB address
into an array of 1024 pushlocks
Arguments:
None.
Return Value:
None
--*/
{
ExReleasePushLock(&CmpKcbLocks[ (HASH_KEY( ((SIZE_T)Kcb)>>6 ))%MAX_KCB_LOCKS ]);
}