- 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]