- 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 _____
Modified: trunk/reactos/hal/halx86/generic/fmutex.c --- 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; } }
_____
Modified: trunk/reactos/include/ndk/arch/mmtypes.h --- 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 _____
Added: trunk/reactos/include/ndk/exfuncs.h --- 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 _____
Modified: trunk/reactos/include/ndk/ntndk.h --- 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 */ _____
Modified: trunk/reactos/include/ndk/rtltypes.h --- 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 _____
Modified: trunk/reactos/include/win32k/bitmaps.h --- 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); _____
Modified: trunk/reactos/ntoskrnl/cc/ccmutex.c --- 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); } }
_____
Modified: trunk/reactos/ntoskrnl/cc/fs.c --- 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) _____
Modified: trunk/reactos/ntoskrnl/cc/pin.c --- 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 { _____
Modified: trunk/reactos/ntoskrnl/cc/view.c --- 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); } }
_____
Modified: trunk/reactos/ntoskrnl/ex/fmutex.c --- 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 */ _____
Modified: trunk/reactos/ntoskrnl/include/internal/cc.h --- 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; _____
Modified: trunk/reactos/ntoskrnl/ke/wait.c --- 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]