- Reimplement Fast Mutex implementation in HAL/NT to be compatible with the real implementation. (Fast Mutex needs to raise IRQL). - Implement ExEnterCriticalRegionAndAcquireFastMutexUnsafe and ExReleaseFastMutexUnsafeAndLeaveCriticalRegion. - Make win32k use those two new functions so that it can continue running at PASSIVE_LEVEL. - Remove CcBrokenMutex and use the new APIs instead. - Implement and export ntoskrnl version of Fast Mutex - Update headers for new fast-mutex definition and API exports. - Fix RemoveEntryList in NDK. - Add exfuncs.h to NDK. - Fix path in mmtypes.h in NDK to be compatible to how it shoudl be included.
Modified: trunk/reactos/hal/halx86/generic/fmutex.c Modified: trunk/reactos/include/ndk/arch/mmtypes.h
Added: trunk/reactos/include/ndk/exfuncs.h
Modified: trunk/reactos/include/ndk/ntndk.h Modified: trunk/reactos/include/ndk/rtltypes.h Modified: trunk/reactos/include/win32k/bitmaps.h Modified: 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/ex/fmutex.c Modified: trunk/reactos/ntoskrnl/include/internal/cc.h Modified: trunk/reactos/ntoskrnl/ke/wait.c Modified: trunk/reactos/ntoskrnl/ntoskrnl.def Modified: trunk/reactos/ntoskrnl/ntoskrnl.xml Modified: trunk/reactos/subsys/win32k/eng/driverobj.c Modified: trunk/reactos/subsys/win32k/include/inteng.h Modified: trunk/reactos/subsys/win32k/include/text.h Modified: trunk/reactos/subsys/win32k/ntuser/guicheck.c Modified: trunk/reactos/subsys/win32k/ntuser/monitor.c Modified: trunk/reactos/subsys/win32k/ntuser/ntuser.c Modified: trunk/reactos/subsys/win32k/ntuser/ssec.c Modified: trunk/reactos/subsys/win32k/ntuser/timer.c Modified: trunk/reactos/w32api/include/ddk/winddk.h
--- trunk/reactos/hal/halx86/generic/fmutex.c 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/hal/halx86/generic/fmutex.c 2005-11-19 22:13:35 UTC (rev 19352) @@ -1,54 +1,96 @@
-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS HAL
* FILE: ntoskrnl/hal/x86/fmutex.c
- * PURPOSE: Implements fast mutexes
- * PROGRAMMER: David Welch (welch@cwcom.net)
- * Eric Kohl (ekohl@rz-online.de)
- * UPDATE HISTORY:
- * Created 09/06/2000
+ * PURPOSE: Deprecated HAL Fast Mutex
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/
+/* + * NOTE: Even HAL itself has #defines to use the Exi* APIs inside NTOSKRNL. + * These are only exported here for compatibility with really old + * drivers. Also note that in theory, these can be made much faster + * by using assembly and inlining all the operations, including + * raising and lowering irql. + */ +
/* INCLUDES *****************************************************************/ #include <hal.h> #define NDEBUG #include <debug.h>
+#undef ExAcquireFastMutex +#undef ExReleaseFastMutex +#undef ExTryToAcquireFastMutex +
/* FUNCTIONS *****************************************************************/
-#undef KeEnterCriticalRegion -#undef KeLeaveCriticalRegion -VOID FASTCALL -ExAcquireFastMutex (PFAST_MUTEX FastMutex)
+VOID +FASTCALL +ExAcquireFastMutex(PFAST_MUTEX FastMutex)
{
- KeEnterCriticalRegion();
- ExAcquireFastMutexUnsafe(FastMutex);
+ KIRQL OldIrql;
+
+ /* Raise IRQL to APC */
+ OldIrql = KfRaiseIrql(APC_LEVEL);
+
+ /* Decrease the count */
+ if (InterlockedDecrement(&FastMutex->Count))
+ {
+ /* Someone is still holding it, use slow path */
+ FastMutex->Contention++;
+ KeWaitForSingleObject(&FastMutex->Gate,
+ WrExecutive,
+ WaitAny,
+ FALSE,
+ NULL);
+ }
+
+ /* Set the owner and IRQL */
+ FastMutex->Owner = KeGetCurrentThread();
+ FastMutex->OldIrql = OldIrql;
}
+VOID
+FASTCALL
+ExReleaseFastMutex(PFAST_MUTEX FastMutex)
+{
+ /* Erase the owner */
+ FastMutex->Owner = (PVOID)1;
-VOID FASTCALL
-ExReleaseFastMutex (PFAST_MUTEX FastMutex)
-{
- ExReleaseFastMutexUnsafe(FastMutex);
- KeLeaveCriticalRegion();
+ /* Increase the count */
+ if (InterlockedIncrement(&FastMutex->Count) <= 0)
+ {
+ /* Someone was waiting for it, signal the waiter */
+ KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
+ }
+
+ /* Lower IRQL back */
+ KfLowerIrql(FastMutex->OldIrql);
}
+BOOLEAN
+FASTCALL
+ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex)
+{
+ KIRQL OldIrql;
-BOOLEAN FASTCALL
-ExTryToAcquireFastMutex (PFAST_MUTEX FastMutex)
-{
- KeEnterCriticalRegion();
- if (InterlockedExchange(&FastMutex->Count, 0) == 1)
+ /* Raise to APC_LEVEL */
+ OldIrql = KfRaiseIrql(APC_LEVEL);
+
+ /* Check if we can quickly acquire it */
+ if (InterlockedCompareExchange(&FastMutex->Count, 0, 1) == 1)
{
- FastMutex->Owner = KeGetCurrentThread();
- return(TRUE);
+ /* We have, set us as owners */
+ FastMutex->Owner = KeGetCurrentThread();
+ return TRUE;
}
- else
+ else
{
- KeLeaveCriticalRegion();
- return(FALSE);
+ /* Acquire attempt failed */
+ KfLowerIrql(OldIrql);
+ return FALSE;
} }
--- trunk/reactos/include/ndk/arch/mmtypes.h 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/include/ndk/arch/mmtypes.h 2005-11-19 22:13:35 UTC (rev 19352) @@ -10,7 +10,7 @@
#define _ARCH_MMTYPES_H #ifdef _M_IX86
-#include <ndk/i386/mmtypes.h>
+#include "./../i386/mmtypes.h"
#else #error "Unknown processor" #endif
--- trunk/reactos/include/ndk/exfuncs.h 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/include/ndk/exfuncs.h 2005-11-19 22:13:35 UTC (rev 19352) @@ -0,0 +1,26 @@
+/* + * PROJECT: ReactOS Native Headers + * FILE: include/ndk/exfuncs.h + * PURPOSE: Prototypes for exported Executive Functions not defined in DDK/IFS + * PROGRAMMER: Alex Ionescu (alex@relsoft.net) + * UPDATE HISTORY: + * Created 06/10/04 + */ +#ifndef _EXFUNCS_H +#define _EXFUNCS_H + +/* DEPENDENCIES **************************************************************/ + +/* FUNCTION TYPES ************************************************************/ + +/* PROTOTYPES ****************************************************************/ + +VOID +FASTCALL +ExEnterCriticalRegionAndAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex); + +VOID +FASTCALL +ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex); + +#endif
--- trunk/reactos/include/ndk/ntndk.h 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/include/ndk/ntndk.h 2005-11-19 22:13:35 UTC (rev 19352) @@ -27,6 +27,7 @@
#include "haltypes.h" /* Hardware Abstraction Layer Types */ #include "halfuncs.h" /* Hardware Abstraction Layer Functions */ #include "inbvfuncs.h" /* Initialization Boot Video Functions */
+#include "exfuncs.h" /* Executive Functions */
#include "iofuncs.h" /* Input/Output Manager Functions */ #include "kefuncs.h" /* Kernel Functions */ #include "mmfuncs.h" /* Memory Manager Functions */
--- trunk/reactos/include/ndk/rtltypes.h 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/include/ndk/rtltypes.h 2005-11-19 22:13:35 UTC (rev 19352) @@ -175,7 +175,7 @@
OldBlink = Entry->Blink; OldFlink->Blink = OldBlink; OldBlink->Flink = OldFlink;
- return (OldFlink == OldBlink);
+ return (BOOLEAN)(OldFlink == OldBlink);
} static __inline
--- trunk/reactos/include/win32k/bitmaps.h 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/include/win32k/bitmaps.h 2005-11-19 22:13:35 UTC (rev 19352) @@ -1,4 +1,3 @@
-
#ifndef __WIN32K_BITMAPS_H #define __WIN32K_BITMAPS_H @@ -38,8 +37,8 @@
BOOL INTERNAL_CALL BITMAP_Cleanup(PVOID ObjectBody); BOOL INTERNAL_CALL BITMAPOBJ_InitBitsLock(BITMAPOBJ *pBMObj);
-#define BITMAPOBJ_LockBitmapBits(pBMObj) ExAcquireFastMutex((pBMObj)->BitsLock)
-#define BITMAPOBJ_UnlockBitmapBits(pBMObj) ExReleaseFastMutex((pBMObj)->BitsLock)
+#define BITMAPOBJ_LockBitmapBits(pBMObj) ExEnterCriticalRegionAndAcquireFastMutexUnsafe((pBMObj)->BitsLock)
+#define BITMAPOBJ_UnlockBitmapBits(pBMObj) ExReleaseFastMutexUnsafeAndLeaveCriticalRegion((pBMObj)->BitsLock)
void INTERNAL_CALL BITMAPOBJ_CleanupBitsLock(BITMAPOBJ *pBMObj); INT FASTCALL BITMAPOBJ_GetWidthBytes (INT bmWidth, INT bpp);
--- trunk/reactos/ntoskrnl/cc/ccmutex.c 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/ntoskrnl/cc/ccmutex.c 2005-11-19 22:13:35 UTC (rev 19352) @@ -26,7 +26,7 @@
InterlockedIncrementUL(&FastMutex->Contention);
while (InterlockedExchange(&FastMutex->Count, 0) == 0)
{
- KeWaitForSingleObject(&FastMutex->Event,
+ KeWaitForSingleObject(&FastMutex->Gate,
Executive, KernelMode, FALSE, @@ -50,7 +50,7 @@
InterlockedExchange(&FastMutex->Count, 1);
if (FastMutex->Contention > 0)
{
- KeSetEvent(&FastMutex->Event, 0, FALSE);
+ KeSetEvent(&FastMutex->Gate, 0, FALSE);
} }
--- trunk/reactos/ntoskrnl/cc/fs.c 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/ntoskrnl/cc/fs.c 2005-11-19 22:13:35 UTC (rev 19352) @@ -153,7 +153,7 @@
if (FileSizes->AllocationSize.QuadPart < Bcb->AllocationSize.QuadPart)
{
InitializeListHead(&FreeListHead);
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&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);
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
current_entry = FreeListHead.Flink; while(current_entry != &FreeListHead)
--- trunk/reactos/ntoskrnl/cc/pin.c 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/ntoskrnl/cc/pin.c 2005-11-19 22:13:35 UTC (rev 19352) @@ -236,7 +236,7 @@
IoStatus->Information = 0;
if (WriteThrough)
{
- CcAcquireBrokenMutex(&iBcb->CacheSegment->Lock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&iBcb->CacheSegment->Lock);
if (iBcb->CacheSegment->Dirty)
{
IoStatus->Status = CcRosFlushCacheSegment(iBcb->CacheSegment);
@@ -245,7 +245,7 @@
{
IoStatus->Status = STATUS_SUCCESS;
}
- CcReleaseBrokenMutex(&iBcb->CacheSegment->Lock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&iBcb->CacheSegment->Lock);
}
else
{
--- trunk/reactos/ntoskrnl/cc/view.c 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/ntoskrnl/cc/view.c 2005-11-19 22:13:35 UTC (rev 19352) @@ -110,6 +110,23 @@
NTSTATUS CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg);
+BOOLEAN
+FASTCALL
+CcTryToAcquireBrokenMutex(PFAST_MUTEX FastMutex)
+{
+ KeEnterCriticalRegion();
+ if (InterlockedExchange(&FastMutex->Count, 0) == 1)
+ {
+ FastMutex->Owner = KeGetCurrentThread();
+ return(TRUE);
+ }
+ else
+ {
+ KeLeaveCriticalRegion();
+ return(FALSE);
+ }
+}
+
/* FUNCTIONS *****************************************************************/ VOID @@ -132,7 +149,7 @@
{
DPRINT1("Enabling Tracing for CacheMap 0x%p:\n", Bcb );
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
KeAcquireSpinLock(&Bcb->BcbLock, &oldirql); current_entry = Bcb->BcbSegmentListHead.Flink; @@ -145,7 +162,7 @@
current, current->ReferenceCount, current->Dirty, current->PageOut ); } KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
}
else
{
@@ -167,14 +184,14 @@
Status = WriteCacheSegment(CacheSegment);
if (NT_SUCCESS(Status))
{
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&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);
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
} return(Status); } @@ -195,7 +212,7 @@
(*Count) = 0;
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
WriteCount[0] = WriteCount[1]; WriteCount[1] = WriteCount[2]; @@ -235,13 +252,13 @@
ASSERT(current->Dirty);
if (current->ReferenceCount > 1)
{
- CcReleaseBrokenMutex(¤t->Lock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(¤t->Lock);
continue; }
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE; Status = CcRosFlushCacheSegment(current);
- CcReleaseBrokenMutex(¤t->Lock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(¤t->Lock);
if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
{
DPRINT1("CC: Failed to flush cache segment.\n");
@@ -251,14 +268,14 @@
(*Count) += PagesPerSegment; Target -= PagesPerSegment; }
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
current_entry = DirtySegmentListHead.Flink;
}
if (*Count < NewTarget)
{
WriteCount[1] += (NewTarget - *Count);
}
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
DPRINT("CcRosFlushDirtyPages() finished\n");
return(STATUS_SUCCESS);
@@ -288,7 +305,7 @@
InitializeListHead(&FreeList);
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
current_entry = CacheSegmentLRUListHead.Flink;
while (current_entry != &CacheSegmentLRUListHead && Target > 0)
{
@@ -320,7 +337,7 @@
last = current; current->PageOut = TRUE; KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql);
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
for (i = 0; i < current->Bcb->CacheSegmentSize / PAGE_SIZE; i++)
{
PFN_TYPE Page;
@@ -331,7 +348,7 @@
break; } }
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
KeAcquireSpinLock(¤t->Bcb->BcbLock, &oldIrql); CcRosCacheSegmentDecRefCount(current); current->PageOut = FALSE; @@ -342,7 +359,7 @@
KeReleaseSpinLock(¤t->Bcb->BcbLock, oldIrql); } }
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
while (!IsListEmpty(&FreeList))
{
@@ -375,7 +392,7 @@
CacheSeg->Valid = Valid; CacheSeg->Dirty = CacheSeg->Dirty || Dirty;
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
if (!WasDirty && CacheSeg->Dirty)
{
InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry);
@@ -399,8 +416,8 @@
CcRosCacheSegmentIncRefCount(CacheSeg); } KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
- CcReleaseBrokenMutex(&ViewLock);
- CcReleaseBrokenMutex(&CacheSeg->Lock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&CacheSeg->Lock);
return(STATUS_SUCCESS); } @@ -428,7 +445,7 @@
{
CcRosCacheSegmentIncRefCount(current);
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
- CcAcquireBrokenMutex(¤t->Lock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(¤t->Lock);
return(current); } current_entry = current_entry->Flink; @@ -455,10 +472,10 @@
}
if (!CacheSeg->Dirty)
{
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry); DirtyPageCount += Bcb->CacheSegmentSize / PAGE_SIZE;
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
}
else
{
@@ -469,7 +486,7 @@
CacheSeg->Dirty = TRUE;
- CcReleaseBrokenMutex(&CacheSeg->Lock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&CacheSeg->Lock);
return(STATUS_SUCCESS); } @@ -500,10 +517,10 @@
if (!WasDirty && NowDirty)
{
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
InsertTailList(&DirtySegmentListHead, &CacheSeg->DirtySegmentListEntry); DirtyPageCount += Bcb->CacheSegmentSize / PAGE_SIZE;
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
} KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); @@ -518,7 +535,7 @@
} KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
- CcReleaseBrokenMutex(&CacheSeg->Lock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&CacheSeg->Lock);
return(STATUS_SUCCESS); } @@ -568,8 +585,8 @@
current->DirtySegmentListEntry.Blink = NULL; current->ReferenceCount = 1; ExInitializeFastMutex(¤t->Lock);
- CcAcquireBrokenMutex(¤t->Lock);
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(¤t->Lock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
*CacheSeg = current; /* There is window between the call to CcRosLookupCacheSegment @@ -598,11 +615,11 @@
current ); } #endif
- CcReleaseBrokenMutex(&(*CacheSeg)->Lock);
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&(*CacheSeg)->Lock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
ExFreeToNPagedLookasideList(&CacheSegLookasideList, *CacheSeg); *CacheSeg = current;
- CcAcquireBrokenMutex(¤t->Lock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(¤t->Lock);
return STATUS_SUCCESS; } if (current->FileOffset < FileOffset) @@ -634,7 +651,7 @@
KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); InsertTailList(&CacheSegmentListHead, ¤t->CacheSegmentListEntry); InsertTailList(&CacheSegmentLRUListHead, ¤t->CacheSegmentLRUListEntry);
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
#ifdef CACHE_BITMAP KeAcquireSpinLock(&CiCacheSegMappingRegionLock, &oldIrql); @@ -907,7 +924,7 @@
DPRINT("CcRosFreeCacheSegment(Bcb 0x%p, CacheSeg 0x%p)\n",
Bcb, CacheSeg);
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql); RemoveEntryList(&CacheSeg->BcbSegmentListEntry); RemoveEntryList(&CacheSeg->CacheSegmentListEntry); @@ -919,7 +936,7 @@
} KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
Status = CcRosInternalFreeCacheSegment(CacheSeg); return(Status); @@ -977,7 +994,7 @@
} } KeAcquireSpinLock(&Bcb->BcbLock, &oldIrql);
- CcReleaseBrokenMutex(¤t->Lock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(¤t->Lock);
CcRosCacheSegmentDecRefCount(current); KeReleaseSpinLock(&Bcb->BcbLock, oldIrql); } @@ -1018,11 +1035,11 @@
ASSERT(Bcb); Bcb->RefCount++;
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
CcFlushCache(FileObject->SectionObjectPointer, NULL, 0, NULL);
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
Bcb->RefCount--;
if (Bcb->RefCount == 0)
{
@@ -1059,7 +1076,7 @@
#endif KeReleaseSpinLock(&Bcb->BcbLock, oldIrql);
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
ObDereferenceObject (Bcb->FileObject); while (!IsListEmpty(&FreeList)) @@ -1069,7 +1086,7 @@
Status = CcRosInternalFreeCacheSegment(current); } ExFreeToNPagedLookasideList(&BcbLookasideList, Bcb);
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
} return(STATUS_SUCCESS); } @@ -1079,7 +1096,7 @@
CcRosReferenceCache(PFILE_OBJECT FileObject)
{
PBCB Bcb;
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
Bcb = (PBCB)FileObject->SectionObjectPointer->SharedCacheMap; ASSERT(Bcb); if (Bcb->RefCount == 0) @@ -1094,7 +1111,7 @@
ASSERT(Bcb->BcbRemoveListEntry.Flink == NULL); } Bcb->RefCount++;
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
} VOID @@ -1103,7 +1120,7 @@
{
PBCB Bcb;
DPRINT("CcRosSetRemoveOnClose()\n");
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
Bcb = (PBCB)SectionObjectPointer->SharedCacheMap;
if (Bcb)
{
@@ -1113,7 +1130,7 @@
CcRosDeleteFileCache(Bcb->FileObject, Bcb); } }
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
} @@ -1122,7 +1139,7 @@
CcRosDereferenceCache(PFILE_OBJECT FileObject)
{
PBCB Bcb;
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
Bcb = (PBCB)FileObject->SectionObjectPointer->SharedCacheMap; ASSERT(Bcb); if (Bcb->RefCount > 0) @@ -1142,7 +1159,7 @@
} } }
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
} NTSTATUS STDCALL @@ -1154,7 +1171,7 @@
{
PBCB Bcb;
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
if (FileObject->SectionObjectPointer->SharedCacheMap != NULL)
{
@@ -1181,7 +1198,7 @@
} } }
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
return(STATUS_SUCCESS); } @@ -1192,7 +1209,7 @@
PBCB Bcb; NTSTATUS Status;
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
Bcb = FileObject->SectionObjectPointer->SharedCacheMap; if (Bcb == NULL) @@ -1213,7 +1230,7 @@
} Status = STATUS_SUCCESS; }
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
return Status; } @@ -1232,13 +1249,13 @@
DPRINT("CcRosInitializeFileCache(FileObject 0x%p, Bcb 0x%p, CacheSegmentSize %d)\n",
FileObject, Bcb, CacheSegmentSize);
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
if (Bcb == NULL)
{
Bcb = ExAllocateFromNPagedLookasideList(&BcbLookasideList);
if (Bcb == NULL)
{
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
return(STATUS_UNSUCCESSFUL); } memset(Bcb, 0, sizeof(BCB)); @@ -1269,7 +1286,7 @@
RemoveEntryList(&Bcb->BcbRemoveListEntry); Bcb->BcbRemoveListEntry.Flink = NULL; }
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
return(STATUS_SUCCESS); } @@ -1324,7 +1341,7 @@
break; }
- CcAcquireBrokenMutex(&ViewLock);
+ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&ViewLock);
CcTimeStamp++;
if (CcTimeStamp >= 30)
{
@@ -1340,7 +1357,7 @@
CcRosDeleteFileCache(current->FileObject, current); } }
- CcReleaseBrokenMutex(&ViewLock);
+ ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&ViewLock);
} }
--- trunk/reactos/ntoskrnl/ex/fmutex.c 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/ntoskrnl/ex/fmutex.c 2005-11-19 22:13:35 UTC (rev 19352) @@ -1,11 +1,9 @@
-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ex/fmutex.c * PURPOSE: Implements fast mutexes
- *
- * PROGRAMMERS: David Welch (welch@cwcom.net)
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/ /* INCLUDES *****************************************************************/ @@ -13,49 +11,194 @@
#include <ntoskrnl.h> #include <internal/debug.h>
+VOID +FASTCALL +KiAcquireFastMutex(IN PFAST_MUTEX FastMutex); +
/* FUNCTIONS *****************************************************************/ /* * @implemented */
-VOID FASTCALL -ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
+VOID +FASTCALL +ExEnterCriticalRegionAndAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
{
- ASSERT(KeGetCurrentThread() == NULL || FastMutex->Owner != KeGetCurrentThread());
- ASSERT(KeGetCurrentIrql() == APC_LEVEL ||
- KeGetCurrentThread() == NULL ||
- KeGetCurrentThread()->KernelApcDisable);
+ PKTHREAD Thread = KeGetCurrentThread();
+
+ /* Enter the Critical Region */
+ KeEnterCriticalRegion();
+ ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
+ (Thread == NULL) ||
+ (Thread->CombinedApcDisable != 0) ||
+ (Thread->Teb == NULL) ||
+ (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
+ ASSERT((Thread == NULL) || (FastMutex->Owner != Thread));
+
+ /* Decrease the count */
+ if (InterlockedDecrement(&FastMutex->Count))
+ {
+ /* Someone is still holding it, use slow path */
+ KiAcquireFastMutex(FastMutex);
+ }
+
+ /* Set the owner */
+ FastMutex->Owner = Thread;
+}
+
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex)
+{
+ ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
+ (KeGetCurrentThread() == NULL) ||
+ (KeGetCurrentThread()->CombinedApcDisable != 0) ||
+ (KeGetCurrentThread()->Teb == NULL) ||
+ (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
+ ASSERT(FastMutex->Owner == KeGetCurrentThread());
- InterlockedIncrementUL(&FastMutex->Contention);
- while (InterlockedExchange(&FastMutex->Count, 0) == 0)
- {
- KeWaitForSingleObject(&FastMutex->Event,
- Executive,
- KernelMode,
- FALSE,
- NULL);
- }
- InterlockedDecrementUL(&FastMutex->Contention);
- FastMutex->Owner = KeGetCurrentThread();
+ /* Erase the owner */
+ FastMutex->Owner = NULL;
+
+ /* Increase the count */
+ if (InterlockedIncrement(&FastMutex->Count) <= 0)
+ {
+ /* Someone was waiting for it, signal the waiter */
+ KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
+ }
+
+ /* Leave the critical region */
+ KeLeaveCriticalRegion();
} /* * @implemented */
-VOID FASTCALL
+VOID
+FASTCALL
+ExAcquireFastMutex(PFAST_MUTEX FastMutex)
+{
+ ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
+ KIRQL OldIrql;
+
+ /* Raise IRQL to APC */
+ OldIrql = KfRaiseIrql(APC_LEVEL);
+
+ /* Decrease the count */
+ if (InterlockedDecrement(&FastMutex->Count))
+ {
+ /* Someone is still holding it, use slow path */
+ KiAcquireFastMutex(FastMutex);
+ }
+
+ /* Set the owner and IRQL */
+ FastMutex->Owner = KeGetCurrentThread();
+ FastMutex->OldIrql = OldIrql;
+}
+
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+ExReleaseFastMutex (PFAST_MUTEX FastMutex)
+{
+ ASSERT_IRQL(APC_LEVEL);
+
+ /* Erase the owner */
+ FastMutex->Owner = NULL;
+
+ /* Increase the count */
+ if (InterlockedIncrement(&FastMutex->Count) <= 0)
+ {
+ /* Someone was waiting for it, signal the waiter */
+ KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
+ }
+
+ /* Lower IRQL back */
+ KfLowerIrql(FastMutex->OldIrql);
+}
+
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
+{
+ PKTHREAD Thread = KeGetCurrentThread();
+ ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
+ (Thread == NULL) ||
+ (Thread->CombinedApcDisable != 0) ||
+ (Thread->Teb == NULL) ||
+ (Thread->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
+ ASSERT((Thread == NULL) || (FastMutex->Owner != Thread));
+
+ /* Decrease the count */
+ if (InterlockedDecrement(&FastMutex->Count))
+ {
+ /* Someone is still holding it, use slow path */
+ KiAcquireFastMutex(FastMutex);
+ }
+
+ /* Set the owner */
+ FastMutex->Owner = Thread;
+}
+
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex)
{
- ASSERT(KeGetCurrentThread() == NULL || FastMutex->Owner == KeGetCurrentThread());
- ASSERT(KeGetCurrentIrql() == APC_LEVEL ||
- KeGetCurrentThread() == NULL ||
- KeGetCurrentThread()->KernelApcDisable);
+ ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
+ (KeGetCurrentThread() == NULL) ||
+ (KeGetCurrentThread()->CombinedApcDisable != 0) ||
+ (KeGetCurrentThread()->Teb == NULL) ||
+ (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
+ ASSERT(FastMutex->Owner == KeGetCurrentThread());
- FastMutex->Owner = NULL;
- InterlockedExchange(&FastMutex->Count, 1);
- if (FastMutex->Contention > 0)
+ /* Erase the owner */
+ FastMutex->Owner = NULL;
+
+ /* Increase the count */
+ if (InterlockedIncrement(&FastMutex->Count) <= 0)
{
- KeSetEvent(&FastMutex->Event, 0, FALSE);
+ /* Someone was waiting for it, signal the waiter */
+ KeSetEventBoostPriority(&FastMutex->Gate, IO_NO_INCREMENT);
} }
+/*
+ * @implemented
+ */
+BOOLEAN
+FASTCALL
+ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex)
+{
+ ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
+ KIRQL OldIrql;
+
+ /* Raise to APC_LEVEL */
+ OldIrql = KfRaiseIrql(APC_LEVEL);
+
+ /* Check if we can quickly acquire it */
+ if (InterlockedCompareExchange(&FastMutex->Count, 0, 1) == 1)
+ {
+ /* We have, set us as owners */
+ FastMutex->Owner = KeGetCurrentThread();
+ return TRUE;
+ }
+ else
+ {
+ /* Acquire attempt failed */
+ KfLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+
/* EOF */
--- trunk/reactos/ntoskrnl/include/internal/cc.h 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/ntoskrnl/include/internal/cc.h 2005-11-19 22:13:35 UTC (rev 19352) @@ -1,18 +1,6 @@
#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;
--- trunk/reactos/ntoskrnl/ke/wait.c 2005-11-19 21:07:25 UTC (rev 19351) +++ trunk/reactos/ntoskrnl/ke/wait.c 2005-11-19 22:13:35 UTC (rev 19352) @@ -1,11 +1,10 @@
/* * COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS project
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ke/wait.c[truncated at 1000 lines; 539 more skipped]