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(a)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>