/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ex/fmutex.c
* PURPOSE: Implements fast mutexes
- * PROGRAMMER: David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- * Created 22/05/98
+ * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
*/
/* INCLUDES *****************************************************************/
-#include <ddk/ntddk.h>
-
+#include <ntoskrnl.h>
#include <internal/debug.h>
+VOID
+FASTCALL
+KiAcquireFastMutex(IN PFAST_MUTEX FastMutex);
+
/* FUNCTIONS *****************************************************************/
-VOID ExAcquireFastMutex(PFAST_MUTEX FastMutex)
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+ExEnterCriticalRegionAndAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
{
- KeEnterCriticalRegion();
- ExAcquireFastMutexUnsafe(FastMutex);
+ 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;
}
-VOID ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(PFAST_MUTEX FastMutex)
{
- if (InterlockedDecrement(&(FastMutex->Count))==0)
- {
- return;
- }
- FastMutex->Contention++;
- KeWaitForSingleObject(&(FastMutex->Event),
- Executive,
- KernelMode,
- FALSE,
- NULL);
- FastMutex->Owner=KeGetCurrentThread();
+ ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
+ (KeGetCurrentThread() == NULL) ||
+ (KeGetCurrentThread()->CombinedApcDisable != 0) ||
+ (KeGetCurrentThread()->Teb == NULL) ||
+ (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
+ ASSERT(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();
}
-VOID ExInitializeFastMutex(PFAST_MUTEX FastMutex)
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+ExAcquireFastMutex(PFAST_MUTEX FastMutex)
{
- FastMutex->Count=1;
- FastMutex->Owner=NULL;
- FastMutex->Contention=0;
- KeInitializeEvent(&(FastMutex->Event),
- SynchronizationEvent,
- FALSE);
+ KIRQL OldIrql;
+ ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
+
+ /* 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;
}
-VOID ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex)
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+ExReleaseFastMutex (PFAST_MUTEX FastMutex)
{
- assert(FastMutex->Owner == KeGetCurrentThread());
- FastMutex->Owner=NULL;
- if (InterlockedIncrement(&(FastMutex->Count))<=0)
- {
- return;
- }
- KeSetEvent(&(FastMutex->Event),0,FALSE);
+ 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);
}
-VOID ExReleaseFastMutex(PFAST_MUTEX FastMutex)
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+ExAcquireFastMutexUnsafe(PFAST_MUTEX FastMutex)
{
- ExReleaseFastMutexUnsafe(FastMutex);
- KeLeaveCriticalRegion();
+ 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;
}
-BOOLEAN ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex)
+/*
+ * @implemented
+ */
+VOID
+FASTCALL
+ExReleaseFastMutexUnsafe(PFAST_MUTEX FastMutex)
{
- UNIMPLEMENTED;
+ ASSERT((KeGetCurrentIrql() == APC_LEVEL) ||
+ (KeGetCurrentThread() == NULL) ||
+ (KeGetCurrentThread()->CombinedApcDisable != 0) ||
+ (KeGetCurrentThread()->Teb == NULL) ||
+ (KeGetCurrentThread()->Teb >= (PTEB)MM_SYSTEM_RANGE_START));
+ ASSERT(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);
+ }
}
+/*
+ * @implemented
+ */
+BOOLEAN
+FASTCALL
+ExTryToAcquireFastMutex(PFAST_MUTEX FastMutex)
+{
+ KIRQL OldIrql;
+ ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
+
+ /* 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();
+ FastMutex->OldIrql = OldIrql;
+ return TRUE;
+ }
+ else
+ {
+ /* Acquire attempt failed */
+ KfLowerIrql(OldIrql);
+ return FALSE;
+ }
+}
+/* EOF */