Due to CcRos's abusive usage and dependency on our broken Fast Mutex implementation, Fast Mutex can't be fixed until the Cc Rewrite is complete. Since that seems to take longer and we've identified drivers which need the correct Fast Mutex implementation committed, I've isolated the old implementation as "CcBrokenMutex" and replaced the calls related to "ExFastMutex" inside CC, so that our fast mutex implementation can be fixed without affecting Cc. Added: trunk/reactos/ntoskrnl/cc/ccmutex.c Modified: trunk/reactos/ntoskrnl/cc/fs.c Modified: trunk/reactos/ntoskrnl/cc/pin.c Modified: trunk/reactos/ntoskrnl/cc/view.c Modified: trunk/reactos/ntoskrnl/include/internal/cc.h Modified: trunk/reactos/ntoskrnl/ntoskrnl.xml _____
Added: trunk/reactos/ntoskrnl/cc/ccmutex.c --- trunk/reactos/ntoskrnl/cc/ccmutex.c 2005-11-18 18:48:14 UTC (rev 19326) +++ trunk/reactos/ntoskrnl/cc/ccmutex.c 2005-11-18 18:51:31 UTC (rev 19327) @@ -0,0 +1,89 @@
+/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/cc/ccmutex.c + * PURPOSE: Implements the Broken Mutex Implementation for the broken Cc + * PROGRAMMERS: Alex Ionescu (alex@relsoft.net) + */ + +/* INCLUDES *****************************************************************/ + +#include <ntoskrnl.h> +#include <internal/debug.h> + +/* FUNCTIONS *****************************************************************/ + +VOID +FASTCALL +CcAcquireBrokenMutexUnsafe(PFAST_MUTEX FastMutex) +{ + ASSERT(KeGetCurrentThread() == NULL || + FastMutex->Owner != KeGetCurrentThread()); + ASSERT(KeGetCurrentIrql() == APC_LEVEL || + KeGetCurrentThread() == NULL || + KeGetCurrentThread()->KernelApcDisable); + + InterlockedIncrementUL(&FastMutex->Contention); + while (InterlockedExchange(&FastMutex->Count, 0) == 0) + { + KeWaitForSingleObject(&FastMutex->Event, + Executive, + KernelMode, + FALSE, + NULL); + } + InterlockedDecrementUL(&FastMutex->Contention); + FastMutex->Owner = KeGetCurrentThread(); +} + +VOID +FASTCALL +CcReleaseBrokenMutexUnsafe(PFAST_MUTEX FastMutex) +{ + ASSERT(KeGetCurrentThread() == NULL || + FastMutex->Owner == KeGetCurrentThread()); + ASSERT(KeGetCurrentIrql() == APC_LEVEL || + KeGetCurrentThread() == NULL || + KeGetCurrentThread()->KernelApcDisable); + + FastMutex->Owner = NULL; + InterlockedExchange(&FastMutex->Count, 1); + if (FastMutex->Contention > 0) + { + KeSetEvent(&FastMutex->Event, 0, FALSE); + } +} + +VOID +FASTCALL +CcAcquireBrokenMutex(PFAST_MUTEX FastMutex) +{ + KeEnterCriticalRegion(); + CcAcquireBrokenMutexUnsafe(FastMutex); +} + + +VOID +FASTCALL +CcReleaseBrokenMutex(PFAST_MUTEX FastMutex) +{ + CcReleaseBrokenMutexUnsafe(FastMutex); + KeLeaveCriticalRegion(); +} + +BOOLEAN +FASTCALL +CcTryToAcquireBrokenMutex(PFAST_MUTEX FastMutex) +{ + KeEnterCriticalRegion(); + if (InterlockedExchange(&FastMutex->Count, 0) == 1) + { + FastMutex->Owner = KeGetCurrentThread(); + return(TRUE); + } + else + { + KeLeaveCriticalRegion(); + return(FALSE); + } +} _____
Modified: trunk/reactos/ntoskrnl/cc/fs.c --- trunk/reactos/ntoskrnl/cc/fs.c 2005-11-18 18:48:14 UTC (rev 19326) +++ trunk/reactos/ntoskrnl/cc/fs.c 2005-11-18 18:51:31 UTC (rev 19327) @@ -153,7 +153,7 @@
if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart) { InitializeListHead(&FreeListHead); - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
current_entry = Bcb->BcbSegmentListHead.Flink; @@ -186,7 +186,7 @@ Bcb->AllocationSize = FileSizes->AllocationSize; Bcb->FileSize = FileSizes->FileSize; KeReleaseSpinLock(&Bcb->BcbLock, oldirql); - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock);
current_entry = FreeListHead.Flink; while(current_entry != &FreeListHead) _____
Modified: trunk/reactos/ntoskrnl/cc/pin.c --- trunk/reactos/ntoskrnl/cc/pin.c 2005-11-18 18:48:14 UTC (rev 19326) +++ trunk/reactos/ntoskrnl/cc/pin.c 2005-11-18 18:51:31 UTC (rev 19327) @@ -236,7 +236,7 @@
IoStatus->Information = 0; if (WriteThrough) { - ExAcquireFastMutex(&iBcb->CacheSegment->Lock); + CcAcquireBrokenMutex(&iBcb->CacheSegment->Lock); if (iBcb->CacheSegment->Dirty) { IoStatus->Status = CcRosFlushCacheSegment(iBcb->CacheSegment); @@ -245,7 +245,7 @@ { IoStatus->Status = STATUS_SUCCESS; } - ExReleaseFastMutex(&iBcb->CacheSegment->Lock); + CcReleaseBrokenMutex(&iBcb->CacheSegment->Lock); } else { _____
Modified: trunk/reactos/ntoskrnl/cc/view.c --- trunk/reactos/ntoskrnl/cc/view.c 2005-11-18 18:48:14 UTC (rev 19326) +++ trunk/reactos/ntoskrnl/cc/view.c 2005-11-18 18:51:31 UTC (rev 19327) @@ -132,7 +132,7 @@
{ DPRINT1("Enabling Tracing for CacheMap 0x%p:\n", Bcb );
- ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
current_entry = Bcb->BcbSegmentListHead.Flink; @@ -145,7 +145,7 @@ current, current->ReferenceCount, current->Dirty, current->PageOut ); } KeReleaseSpinLock(&Bcb->BcbLock, oldirql); - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); } else { @@ -167,14 +167,14 @@ Status = WriteCacheSegment(CacheSegment); if (NT_SUCCESS(Status)) { - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); KeAcquireSpinLock(&CacheSegment->Bcb->BcbLock, &oldIrql); CacheSegment->Dirty = FALSE; RemoveEntryList(&CacheSegment->DirtySegmentListEntry); DirtyPageCount -= CacheSegment->Bcb->CacheSegmentSize / PAGE_SIZE; CcRosCacheSegmentDecRefCount ( CacheSegment ); KeReleaseSpinLock(&CacheSegment->Bcb->BcbLock, oldIrql); - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); } return(Status); } @@ -195,7 +195,7 @@
(*Count) = 0;
- ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock);
WriteCount[0] = WriteCount[1]; WriteCount[1] = WriteCount[2]; @@ -227,7 +227,7 @@ current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, DirtySegmentListEntry); current_entry = current_entry->Flink; - Locked = ExTryToAcquireFastMutex(¤t->Lock); + Locked = CcTryToAcquireBrokenMutex(¤t->Lock); if (!Locked) { continue; @@ -235,13 +235,13 @@ ASSERT(current->Dirty); if (current->ReferenceCount > 1) { - ExReleaseFastMutex(¤t->Lock); + CcReleaseBrokenMutex(¤t->Lock); continue; } - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE; Status = CcRosFlushCacheSegment(current); - ExReleaseFastMutex(¤t->Lock); + CcReleaseBrokenMutex(¤t->Lock); if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE)) { DPRINT1("CC: Failed to flush cache segment.\n"); @@ -251,14 +251,14 @@ (*Count) += PagesPerSegment; Target -= PagesPerSegment; } - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); current_entry = DirtySegmentListHead.Flink; } if (*Count < NewTarget) { WriteCount[1] += (NewTarget - *Count); } - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); DPRINT("CcRosFlushDirtyPages() finished\n");
return(STATUS_SUCCESS); @@ -288,7 +288,7 @@
InitializeListHead(&FreeList);
- ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); current_entry = CacheSegmentLRUListHead.Flink; while (current_entry != &CacheSegmentLRUListHead && Target > 0) { @@ -320,7 +320,7 @@ last = current; current->PageOut = TRUE; KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql); - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); for (i = 0; i < current->Bcb->CacheSegmentSize / PAGE_SIZE; i++) { PFN_TYPE Page; @@ -331,7 +331,7 @@ break; } } - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql); CcRosCacheSegmentDecRefCount(current); current->PageOut = FALSE; @@ -342,7 +342,7 @@ KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql); } } - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock);
while (!IsListEmpty(&FreeList)) { @@ -375,7 +375,7 @@ CacheSeg->Valid = Valid; CacheSeg->Dirty = CacheSeg->Dirty || Dirty;
- ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); if (!WasDirty && CacheSeg->Dirty) { InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry); @@ -399,8 +399,8 @@ CcRosCacheSegmentIncRefCount(CacheSeg); } KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); - ExReleaseFastMutex(&ViewLock); - ExReleaseFastMutex(&CacheSeg->Lock); + CcReleaseBrokenMutex(&ViewLock); + CcReleaseBrokenMutex(&CacheSeg->Lock);
return(STATUS_SUCCESS); } @@ -428,7 +428,7 @@ { CcRosCacheSegmentIncRefCount(current); KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); - ExAcquireFastMutex(¤t->Lock); + CcAcquireBrokenMutex(¤t->Lock); return(current); } current_entry = current_entry->Flink; @@ -455,10 +455,10 @@ } if (!CacheSeg->Dirty) { - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry); DirtyPageCount += Bcb->CacheSegmentSize / PAGE_SIZE; - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); } else { @@ -469,7 +469,7 @@
CacheSeg->Dirty = TRUE; - ExReleaseFastMutex(&CacheSeg->Lock); + CcReleaseBrokenMutex(&CacheSeg->Lock);
return(STATUS_SUCCESS); } @@ -500,10 +500,10 @@
if (!WasDirty && NowDirty) { - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry); DirtyPageCount += Bcb->CacheSegmentSize / PAGE_SIZE; - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); }
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); @@ -518,7 +518,7 @@ } KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
- ExReleaseFastMutex(&CacheSeg->Lock); + CcReleaseBrokenMutex(&CacheSeg->Lock); return(STATUS_SUCCESS); }
@@ -568,8 +568,8 @@ current->DirtySegmentListEntry.Blink = NULL; current->ReferenceCount = 1; ExInitializeFastMutex(¤t->Lock); - ExAcquireFastMutex(¤t->Lock); - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(¤t->Lock); + CcAcquireBrokenMutex(&ViewLock);
*CacheSeg = current; /* There is window between the call to CcRosLookupCacheSegment @@ -598,11 +598,11 @@ current ); } #endif - ExReleaseFastMutex(&(*CacheSeg)->Lock); - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&(*CacheSeg)->Lock); + CcReleaseBrokenMutex(&ViewLock); ExFreeToNPagedLookasideList(&CacheSegLookasideList, *CacheSeg); *CacheSeg = current; - ExAcquireFastMutex(¤t->Lock); + CcAcquireBrokenMutex(¤t->Lock); return STATUS_SUCCESS; } if (current->FileOffset < FileOffset) @@ -634,7 +634,7 @@ KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry); InsertTailList(&CacheSegmentLRUListHead, ¤t->CacheSegmentLRUListEntry); - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); #ifdef CACHE_BITMAP KeAcquireSpinLock(&CiCacheSegMappingRegionLock, &oldIrql);
@@ -907,7 +907,7 @@ DPRINT("CcRosFreeCacheSegment(Bcb 0x%p, CacheSeg 0x%p)\n", Bcb, CacheSeg);
- ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); RemoveEntryList(&CacheSeg->BcbSegmentListEntry); RemoveEntryList(&CacheSeg->CacheSegmentListEntry); @@ -919,7 +919,7 @@
} KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock);
Status = CcRosInternalFreeCacheSegment(CacheSeg); return(Status); @@ -977,7 +977,7 @@ } } KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); - ExReleaseFastMutex(¤t->Lock); + CcReleaseBrokenMutex(¤t->Lock); CcRosCacheSegmentDecRefCount(current); KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); } @@ -1018,11 +1018,11 @@ ASSERT(Bcb);
Bcb->RefCount++; - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock);
CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, NULL);
- ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); Bcb->RefCount--; if (Bcb->RefCount == 0) { @@ -1059,7 +1059,7 @@ #endif KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
- ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); ObDereferenceObject (Bcb->FileObject);
while (!IsListEmpty(&FreeList)) @@ -1069,7 +1069,7 @@ Status = CcRosInternalFreeCacheSegment(current); } ExFreeToNPagedLookasideList(&BcbLookasideList, Bcb); - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); } return(STATUS_SUCCESS); } @@ -1079,7 +1079,7 @@ CcRosReferenceCache(PFILE_OBJECT FileObject) { PBCB Bcb; - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); Bcb = (PBCB)FileObject->SectionObjectPointer->SharedCacheMap; ASSERT(Bcb); if (Bcb->RefCount == 0) @@ -1094,7 +1094,7 @@ ASSERT(Bcb->BcbRemoveListEntry.Flink == NULL); } Bcb->RefCount++; - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); }
VOID @@ -1103,7 +1103,7 @@ { PBCB Bcb; DPRINT("CcRosSetRemoveOnClose()\n"); - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); Bcb = (PBCB)SectionObjectPointer->SharedCacheMap; if (Bcb) { @@ -1113,7 +1113,7 @@ CcRosDeleteFileCache(Bcb->FileObject, Bcb); } } - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); }
@@ -1122,7 +1122,7 @@ CcRosDereferenceCache(PFILE_OBJECT FileObject) { PBCB Bcb; - ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); Bcb = (PBCB)FileObject->SectionObjectPointer->SharedCacheMap; ASSERT(Bcb); if (Bcb->RefCount > 0) @@ -1142,7 +1142,7 @@ } } } - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); }
NTSTATUS STDCALL @@ -1154,7 +1154,7 @@ { PBCB Bcb;
- ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock);
if (FileObject->SectionObjectPointer->SharedCacheMap != NULL) { @@ -1181,7 +1181,7 @@ } } } - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); return(STATUS_SUCCESS); }
@@ -1192,7 +1192,7 @@ PBCB Bcb; NTSTATUS Status;
- ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock);
Bcb = FileObject->SectionObjectPointer->SharedCacheMap; if (Bcb == NULL) @@ -1213,7 +1213,7 @@ } Status = STATUS_SUCCESS; } - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock);
return Status; } @@ -1232,13 +1232,13 @@ DPRINT("CcRosInitializeFileCache(FileObject 0x%p, Bcb 0x%p, CacheSegmentSize %d)\n", FileObject, Bcb, CacheSegmentSize);
- ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); if (Bcb == NULL) { Bcb = ExAllocateFromNPagedLookasideList(&BcbLookasideList); if (Bcb == NULL) { - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); return(STATUS_UNSUCCESSFUL); } memset(Bcb, 0, sizeof(BCB)); @@ -1269,7 +1269,7 @@ RemoveEntryList(&Bcb->BcbRemoveListEntry); Bcb->BcbRemoveListEntry.Flink = NULL; } - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock);
return(STATUS_SUCCESS); } @@ -1324,7 +1324,7 @@ break; }
- ExAcquireFastMutex(&ViewLock); + CcAcquireBrokenMutex(&ViewLock); CcTimeStamp++; if (CcTimeStamp >= 30) { @@ -1340,7 +1340,7 @@ CcRosDeleteFileCache(current->FileObject, current); } } - ExReleaseFastMutex(&ViewLock); + CcReleaseBrokenMutex(&ViewLock); } }
_____
Modified: trunk/reactos/ntoskrnl/include/internal/cc.h --- trunk/reactos/ntoskrnl/include/internal/cc.h 2005-11-18 18:48:14 UTC (rev 19326) +++ trunk/reactos/ntoskrnl/include/internal/cc.h 2005-11-18 18:51:31 UTC (rev 19327) @@ -1,6 +1,18 @@
#ifndef __INCLUDE_INTERNAL_CC_H #define __INCLUDE_INTERNAL_CC_H
+VOID +FASTCALL +CcAcquireBrokenMutex(PFAST_MUTEX FastMutex); + +VOID +FASTCALL +CcReleaseBrokenMutex(PFAST_MUTEX FastMutex); + +BOOLEAN +FASTCALL +CcTryToAcquireBrokenMutex(PFAST_MUTEX FastMutex); + typedef struct _BCB { LIST_ENTRY BcbSegmentListHead; _____
Modified: trunk/reactos/ntoskrnl/ntoskrnl.xml --- trunk/reactos/ntoskrnl/ntoskrnl.xml 2005-11-18 18:48:14 UTC (rev 19326) +++ trunk/reactos/ntoskrnl/ntoskrnl.xml 2005-11-18 18:51:31 UTC (rev 19327) @@ -73,6 +73,7 @@
</directory> <directory name="cc"> <file>cacheman.c</file> + <file>ccmutex.c</file> <file>copy.c</file> <file>fs.c</file> <file>mdl.c</file>