Index: cc/cacheman.c =================================================================== --- ntoskrnl/cc/cacheman.c (revision 71963) +++ ntoskrnl/cc/cacheman.c (working copy) @@ -15,6 +15,11 @@ PFSN_PREFETCHER_GLOBALS CcPfGlobals; +#if CC_MUTEX_DEBUGGING +KGUARDED_MUTEX CcLockedVacbsMutex; +LIST_ENTRY CcLockedVacbsList; +#endif + /* FUNCTIONS *****************************************************************/ VOID @@ -40,6 +45,10 @@ INIT_FUNCTION CcInitializeCacheManager(VOID) { +#if CC_MUTEX_DEBUGGING + KeInitializeGuardedMutex(&CcLockedVacbsMutex); + InitializeListHead(&CcLockedVacbsList); +#endif CcInitView(); return TRUE; } Index: cc/pin.c =================================================================== --- ntoskrnl/cc/pin.c (revision 71963) +++ ntoskrnl/cc/pin.c (working copy) @@ -187,7 +187,7 @@ iBcb->Pinned = TRUE; if (InterlockedIncrement(&iBcb->Vacb->PinCount) == 1) { - KeReleaseMutex(&iBcb->Vacb->Mutex, FALSE); + CcReleaseVacbLock(iBcb->Vacb); } if (Flags & PIN_EXCLUSIVE) @@ -264,6 +264,38 @@ CcUnpinDataForThread(Bcb, (ERESOURCE_THREAD)PsGetCurrentThread()); } +#if CC_MUTEX_DEBUGGING +VOID +CcDumpLockedVacbs(VOID) +{ + PLIST_ENTRY Entry; + PROS_VACB Vacb; + ULONG i; + + DPRINT1("*** Dumping Locked VACBs ***\n"); + KeAcquireGuardedMutex(&CcLockedVacbsMutex); + Entry = CcLockedVacbsList.Flink; + while (Entry != &CcLockedVacbsList) + { + Vacb = CONTAINING_RECORD(Entry, ROS_VACB, LockedVacbsEntry); + Entry = Entry->Flink; + + DPRINT1("VACB %p locked by thread %p with backtrace:\n", Vacb, Vacb->OwnerThread); + for (i = 0; i < 16; i++) + { + if (Vacb->Backtrace[i] == NULL) + { + break; + } + DPRINT1("%p\n", Vacb->Backtrace[i]); + } + DPRINT1("---end---\n"); + } + KeReleaseGuardedMutex(&CcLockedVacbsMutex); + DPRINT1("*** End of Locked VACB Dump ***\n"); +} +#endif + /* * @unimplemented */ @@ -283,11 +315,7 @@ iBcb->Pinned = FALSE; if (InterlockedDecrement(&iBcb->Vacb->PinCount) == 0) { - KeWaitForSingleObject(&iBcb->Vacb->Mutex, - Executive, - KernelMode, - FALSE, - NULL); + CcAcquireVacbLock(iBcb->Vacb, NULL); } } @@ -339,11 +367,7 @@ IoStatus->Information = 0; if (WriteThrough) { - KeWaitForSingleObject(&iBcb->Vacb->Mutex, - Executive, - KernelMode, - FALSE, - NULL); + CcAcquireVacbLock(iBcb->Vacb, NULL); if (iBcb->Vacb->Dirty) { IoStatus->Status = CcRosFlushVacb(iBcb->Vacb); @@ -352,7 +376,7 @@ { IoStatus->Status = STATUS_SUCCESS; } - KeReleaseMutex(&iBcb->Vacb->Mutex, FALSE); + CcReleaseVacbLock(iBcb->Vacb); } else { @@ -365,11 +389,7 @@ iBcb->Pinned = FALSE; if (InterlockedDecrement(&iBcb->Vacb->PinCount) == 0) { - KeWaitForSingleObject(&iBcb->Vacb->Mutex, - Executive, - KernelMode, - FALSE, - NULL); + CcAcquireVacbLock(iBcb->Vacb, NULL); } } ExDeleteResourceLite(&iBcb->Lock); Index: cc/view.c =================================================================== --- ntoskrnl/cc/view.c (revision 71963) +++ ntoskrnl/cc/view.c (working copy) @@ -199,11 +199,8 @@ continue; } - Status = KeWaitForSingleObject(¤t->Mutex, - Executive, - KernelMode, - FALSE, - Wait ? NULL : &ZeroTimeout); + Status = CcAcquireVacbLock(current, + Wait ? NULL : &ZeroTimeout); if (Status != STATUS_SUCCESS) { current->SharedCacheMap->Callbacks->ReleaseFromLazyWrite( @@ -217,7 +214,7 @@ /* One reference is added above */ if (current->ReferenceCount > 2) { - KeReleaseMutex(¤t->Mutex, FALSE); + CcReleaseVacbLock(current); current->SharedCacheMap->Callbacks->ReleaseFromLazyWrite( current->SharedCacheMap->LazyWriteContext); CcRosVacbDecRefCount(current); @@ -228,7 +225,7 @@ Status = CcRosFlushVacb(current); - KeReleaseMutex(¤t->Mutex, FALSE); + CcReleaseVacbLock(current); current->SharedCacheMap->Callbacks->ReleaseFromLazyWrite( current->SharedCacheMap->LazyWriteContext); @@ -427,7 +424,7 @@ KeReleaseGuardedMutex(&ViewLock); if (InterlockedCompareExchange(&Vacb->PinCount, 0, 0) == 0) { - KeReleaseMutex(&Vacb->Mutex, FALSE); + CcReleaseVacbLock(Vacb); } return STATUS_SUCCESS; @@ -467,11 +464,7 @@ KeReleaseGuardedMutex(&ViewLock); if (InterlockedCompareExchange(¤t->PinCount, 0, 0) == 0) { - KeWaitForSingleObject(¤t->Mutex, - Executive, - KernelMode, - FALSE, - NULL); + CcAcquireVacbLock(current, NULL); } return current; } @@ -527,7 +520,7 @@ KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldIrql); KeReleaseGuardedMutex(&ViewLock); - KeReleaseMutex(&Vacb->Mutex, FALSE); + CcReleaseVacbLock(Vacb); return STATUS_SUCCESS; } @@ -580,7 +573,7 @@ KeReleaseSpinLock(&SharedCacheMap->CacheMapLock, oldIrql); KeReleaseGuardedMutex(&ViewLock); - KeReleaseMutex(&Vacb->Mutex, FALSE); + CcReleaseVacbLock(Vacb); return STATUS_SUCCESS; } @@ -593,17 +586,21 @@ ULONG i; NTSTATUS Status; ULONG_PTR NumberOfPages; + PVOID BaseAddress; /* Create a memory area. */ MmLockAddressSpace(MmGetKernelAddressSpace()); + ASSERT(Vacb->BaseAddress == NULL); + BaseAddress = NULL; Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 0, // nothing checks for VACB mareas, so set to 0 - &Vacb->BaseAddress, + &BaseAddress, VACB_MAPPING_GRANULARITY, PAGE_READWRITE, (PMEMORY_AREA*)&Vacb->MemoryArea, 0, PAGE_SIZE); + Vacb->BaseAddress = BaseAddress; MmUnlockAddressSpace(MmGetKernelAddressSpace()); if (!NT_SUCCESS(Status)) { @@ -682,12 +679,14 @@ current->DirtyVacbListEntry.Blink = NULL; current->ReferenceCount = 1; current->PinCount = 0; +#if CC_MUTEX_DEBUGGING + current->LockedVacbsEntry.Flink = NULL; + current->LockedVacbsEntry.Blink = NULL; + current->OwnerThread = NULL; + RtlFillMemory(¤t->Backtrace, sizeof(current->Backtrace), 0xde); +#endif KeInitializeMutex(¤t->Mutex, 0); - KeWaitForSingleObject(¤t->Mutex, - Executive, - KernelMode, - FALSE, - NULL); + CcAcquireVacbLock(current, NULL); KeAcquireGuardedMutex(&ViewLock); *Vacb = current; @@ -719,17 +718,13 @@ current); } #endif - KeReleaseMutex(&(*Vacb)->Mutex, FALSE); + CcReleaseVacbLock(*Vacb); KeReleaseGuardedMutex(&ViewLock); ExFreeToNPagedLookasideList(&VacbLookasideList, *Vacb); *Vacb = current; if (InterlockedCompareExchange(¤t->PinCount, 0, 0) == 0) { - KeWaitForSingleObject(¤t->Mutex, - Executive, - KernelMode, - FALSE, - NULL); + CcAcquireVacbLock(current, NULL); } return STATUS_SUCCESS; } @@ -962,7 +957,7 @@ if (InterlockedCompareExchange(¤t->PinCount, 0, 0) == 0) { - KeReleaseMutex(¤t->Mutex, FALSE); + CcReleaseVacbLock(current); } KeAcquireGuardedMutex(&ViewLock); Index: include/internal/cc.h =================================================================== --- ntoskrnl/include/internal/cc.h (revision 71963) +++ ntoskrnl/include/internal/cc.h (working copy) @@ -159,6 +159,7 @@ #endif } ROS_SHARED_CACHE_MAP, *PROS_SHARED_CACHE_MAP; +#define CC_MUTEX_DEBUGGING 1 typedef struct _ROS_VACB { /* Base address of the region where the view's data is mapped. */ @@ -182,6 +183,11 @@ LARGE_INTEGER FileOffset; /* Mutex */ KMUTEX Mutex; +#if CC_MUTEX_DEBUGGING + LIST_ENTRY LockedVacbsEntry; + PKTHREAD OwnerThread; + PVOID Backtrace[16]; +#endif /* Number of references. */ ULONG ReferenceCount; /* How many times was it pinned? */ @@ -191,6 +197,57 @@ /* Pointer to the next VACB in a chain. */ } ROS_VACB, *PROS_VACB; +#if CC_MUTEX_DEBUGGING +extern KGUARDED_MUTEX CcLockedVacbsMutex; +extern LIST_ENTRY CcLockedVacbsList; +#endif + +FORCEINLINE +NTSTATUS +CcAcquireVacbLock( + _In_ PROS_VACB Vacb, + _In_ PLARGE_INTEGER Timeout) +{ + NTSTATUS Status; + Status = KeWaitForSingleObject(&Vacb->Mutex, + Executive, + KernelMode, + FALSE, + Timeout); +#if CC_MUTEX_DEBUGGING + if (Status != STATUS_SUCCESS) + { + return Status; + } + KeAcquireGuardedMutex(&CcLockedVacbsMutex); + ASSERT(Vacb->OwnerThread == NULL); + ASSERT(Vacb->LockedVacbsEntry.Flink == NULL); + ASSERT(Vacb->LockedVacbsEntry.Blink == NULL); + InsertTailList(&CcLockedVacbsList, &Vacb->LockedVacbsEntry); + RtlZeroMemory(Vacb->Backtrace, sizeof(Vacb->Backtrace)); + RtlCaptureStackBackTrace(0, 16, Vacb->Backtrace, NULL); + Vacb->OwnerThread = KeGetCurrentThread(); + KeReleaseGuardedMutex(&CcLockedVacbsMutex); +#endif + return Status; +} + +FORCEINLINE +VOID +CcReleaseVacbLock(PROS_VACB Vacb) +{ +#if CC_MUTEX_DEBUGGING + KeAcquireGuardedMutex(&CcLockedVacbsMutex); + ASSERT(Vacb->OwnerThread == KeGetCurrentThread()); + RemoveEntryList(&Vacb->LockedVacbsEntry); + Vacb->LockedVacbsEntry.Flink = NULL; + Vacb->LockedVacbsEntry.Blink = NULL; + Vacb->OwnerThread = NULL; + KeReleaseGuardedMutex(&CcLockedVacbsMutex); +#endif + KeReleaseMutex(&Vacb->Mutex, FALSE); +} + typedef struct _INTERNAL_BCB { /* Lock */