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
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 ]);
|
|
}
|