Implemented Guarded Mutex, a drop-in replacement for Fast Mutex (the
correct one, not the one ROS incorrectly implements) on NT 5.2. Not
fully tested yet, so nothing switched to it and probably not usable.
Also made KeGetCurrentThread/Irql become inlined, since this should
create quite a speed boost. Made KeLeaveCriticalRegion deliver APCs if
possible, and made Crit regions macros usable from outside ntoskrnl
thanks to a new NT 5.2 API (KiCheckForKernelApcDelivery). Guarded Mutex
code based on Filip Navara.
Modified: trunk/reactos/drivers/storage/diskdump/diskdump.c
Modified: trunk/reactos/hal/hal/hal.c
Modified: trunk/reactos/hal/halx86/generic/fmutex.c
Modified: trunk/reactos/hal/halx86/generic/irql.c
Modified: trunk/reactos/include/ddk/kedef.h
Modified: trunk/reactos/include/ddk/kefuncs.h
Modified: trunk/reactos/include/ddk/ketypes.h
Modified: trunk/reactos/ntoskrnl/Makefile
Modified: trunk/reactos/ntoskrnl/ex/i386/interlck.c
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ps.h
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
Modified: trunk/reactos/ntoskrnl/include/internal/ps.h
Modified: trunk/reactos/ntoskrnl/ke/apc.c
Modified: trunk/reactos/ntoskrnl/ke/gmutex.c
Modified: trunk/reactos/ntoskrnl/ntoskrnl.def
Modified: trunk/reactos/ntoskrnl/ps/thread.c
Modified: trunk/reactos/w32api/include/ddk/winddk.h
_____
Modified: trunk/reactos/drivers/storage/diskdump/diskdump.c
--- trunk/reactos/drivers/storage/diskdump/diskdump.c 2005-04-15
00:48:25 UTC (rev 14624)
+++ trunk/reactos/drivers/storage/diskdump/diskdump.c 2005-04-15
06:24:35 UTC (rev 14625)
@@ -41,6 +41,7 @@
#undef VERSION
#define VERSION "0.0.1"
+#undef KeGetCurrentIrql
/* PROTOTYPES
***************************************************************/
NTSTATUS STDCALL
_____
Modified: trunk/reactos/hal/hal/hal.c
--- trunk/reactos/hal/hal/hal.c 2005-04-15 00:48:25 UTC (rev 14624)
+++ trunk/reactos/hal/hal/hal.c 2005-04-15 06:24:35 UTC (rev 14625)
@@ -748,7 +748,7 @@
UNIMPLEMENTED;
}
-
+#undef KeGetCurrentIrql
KIRQL
STDCALL
KeGetCurrentIrql(VOID)
_____
Modified: trunk/reactos/hal/halx86/generic/fmutex.c
--- trunk/reactos/hal/halx86/generic/fmutex.c 2005-04-15 00:48:25 UTC
(rev 14624)
+++ trunk/reactos/hal/halx86/generic/fmutex.c 2005-04-15 06:24:35 UTC
(rev 14625)
@@ -18,6 +18,8 @@
/* FUNCTIONS
*****************************************************************/
+#undef KeEnterCriticalRegion
+#undef KeLeaveCriticalRegion
VOID FASTCALL
ExAcquireFastMutex (PFAST_MUTEX FastMutex)
{
_____
Modified: trunk/reactos/hal/halx86/generic/irql.c
--- trunk/reactos/hal/halx86/generic/irql.c 2005-04-15 00:48:25 UTC
(rev 14624)
+++ trunk/reactos/hal/halx86/generic/irql.c 2005-04-15 06:24:35 UTC
(rev 14625)
@@ -65,6 +65,7 @@
/* FUNCTIONS
****************************************************************/
+#undef KeGetCurrentIrql
KIRQL STDCALL KeGetCurrentIrql (VOID)
/*
* PURPOSE: Returns the current irq level
_____
Modified: trunk/reactos/include/ddk/kedef.h
--- trunk/reactos/include/ddk/kedef.h 2005-04-15 00:48:25 UTC (rev
14624)
+++ trunk/reactos/include/ddk/kedef.h 2005-04-15 06:24:35 UTC (rev
14625)
@@ -56,7 +56,7 @@
WrPageOut,
WrRendezvous,
Spare2,
- Spare3,
+ WrGuardedMutex,
Spare4,
Spare5,
Spare6,
_____
Modified: trunk/reactos/include/ddk/kefuncs.h
--- trunk/reactos/include/ddk/kefuncs.h 2005-04-15 00:48:25 UTC (rev
14624)
+++ trunk/reactos/include/ddk/kefuncs.h 2005-04-15 06:24:35 UTC (rev
14625)
@@ -809,4 +809,48 @@
IN NTSTATUS ExceptionCode
);
+VOID
+FASTCALL
+KeAcquireGuardedMutex(
+ PKGUARDED_MUTEX GuardedMutex
+);
+
+VOID
+FASTCALL
+KeAcquireGuardedMutexUnsafe(
+ PKGUARDED_MUTEX GuardedMutex
+);
+
+VOID
+STDCALL
+KeEnterGuardedRegion(VOID);
+
+VOID
+STDCALL
+KeLeaveGuardedRegion(VOID);
+
+VOID
+FASTCALL
+KeInitializeGuardedMutex(
+ PKGUARDED_MUTEX GuardedMutex
+);
+
+VOID
+FASTCALL
+KeReleaseGuardedMutexUnsafe(
+ PKGUARDED_MUTEX GuardedMutex
+);
+
+VOID
+FASTCALL
+KeReleaseGuardedMutex(
+ PKGUARDED_MUTEX GuardedMutex
+);
+
+BOOL
+FASTCALL
+KeTryToAcquireGuardedMutex(
+ PKGUARDED_MUTEX GuardedMutex
+);
+
#endif /* __INCLUDE_DDK_KEFUNCS_H */
_____
Modified: trunk/reactos/include/ddk/ketypes.h
--- trunk/reactos/include/ddk/ketypes.h 2005-04-15 00:48:25 UTC (rev
14624)
+++ trunk/reactos/include/ddk/ketypes.h 2005-04-15 06:24:35 UTC (rev
14625)
@@ -180,6 +180,21 @@
UCHAR ApcDisable;
} KMUTEX, *PKMUTEX, KMUTANT, *PKMUTANT;
+typedef struct _KGUARDED_MUTEX
+{
+ LONG Count;
+ struct _KTHREAD* Owner;
+ ULONG Contention;
+ KGATE Gate;
+ union {
+ struct {
+ SHORT KernelApcDisable;
+ SHORT SpecialApcDisable;
+ };
+ ULONG CombinedApcDisable;
+ };
+} KGUARDED_MUTEX, *PKGUARDED_MUTEX;
+
#include <pshpack1.h>
typedef struct _KSEMAPHORE
_____
Modified: trunk/reactos/ntoskrnl/Makefile
--- trunk/reactos/ntoskrnl/Makefile 2005-04-15 00:48:25 UTC (rev
14624)
+++ trunk/reactos/ntoskrnl/Makefile 2005-04-15 06:24:35 UTC (rev
14625)
@@ -100,6 +100,8 @@
ke/dpc.o \
ke/device.o \
ke/event.o \
+ ke/gate.o \
+ ke/gmutex.o \
ke/kqueue.o \
ke/kthread.o \
ke/ipi.o \
_____
Modified: trunk/reactos/ntoskrnl/ex/i386/interlck.c
--- trunk/reactos/ntoskrnl/ex/i386/interlck.c 2005-04-15 00:48:25 UTC
(rev 14624)
+++ trunk/reactos/ntoskrnl/ex/i386/interlck.c 2005-04-15 06:24:35 UTC
(rev 14625)
@@ -396,7 +396,45 @@
#error Unknown compiler for inline assembler
#endif
+/**********************************************************************
+ * FASTCALL: @InterlockedClearBit@8
+ * STDCALL: _InterlockedClearBit@8
+ */
+#if defined(__GNUC__)
+/*
+ * @implemented
+ */
+UCHAR
+FASTCALL
+InterlockedClearBit(PLONG Destination,
+ LONG Bit);
+__asm__("\n\t.global @InterlockedClearBit@8\n\t"
+ "@InterlockedClearBit@8:\n\t"
+ LOCK
+ "btr %edx,(%ecx)\n\t"
+ "setc %al\n\t"
+ "ret $8\n\t");
+
+#elif defined(_MSC_VER)
+/*
+ * @implemented
+ */
+__declspec(naked)
+UCHAR
+FASTCALL
+InterlockedClearBit(PUCHAR Destination,
+ UCHAR Bit)
+{
+ __asm LOCK btr [ecx], edx
+ __asm setc al
+ __asm ret
+}
+
+#else
+#error Unknown compiler for inline assembler
+#endif
+
/**********************************************************************
* FASTCALL: @InterlockedCompareExchange@12
* STDCALL: _InterlockedCompareExchange@12
_____
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ke.h
--- trunk/reactos/ntoskrnl/include/internal/i386/ke.h 2005-04-15
00:48:25 UTC (rev 14624)
+++ trunk/reactos/ntoskrnl/include/internal/i386/ke.h 2005-04-15
06:24:35 UTC (rev 14625)
@@ -205,6 +205,7 @@
#define LOCK ""
#endif
+#define KeGetCurrentIrql(X) (((PKPCR)KPCR_BASE)->Irql)
#if defined(__GNUC__)
#define Ke386DisableInterrupts() __asm__("cli\n\t");
_____
Modified: trunk/reactos/ntoskrnl/include/internal/i386/ps.h
--- trunk/reactos/ntoskrnl/include/internal/i386/ps.h 2005-04-15
00:48:25 UTC (rev 14624)
+++ trunk/reactos/ntoskrnl/include/internal/i386/ps.h 2005-04-15
06:24:35 UTC (rev 14625)
@@ -292,6 +292,7 @@
#define KeGetCurrentKPCR(X) ((PKPCR)KPCR_BASE)
#define KeGetCurrentPrcb() (((PKPCR)KPCR_BASE)->Prcb)
+#define KeGetCurrentThread(X)
(((PKPCR)KPCR_BASE)->PrcbData.CurrentThread)
#endif
_____
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
--- trunk/reactos/ntoskrnl/include/internal/ke.h 2005-04-15
00:48:25 UTC (rev 14624)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h 2005-04-15
06:24:35 UTC (rev 14625)
@@ -49,6 +49,26 @@
#define IPI_REQUEST_DPC 2
#define IPI_REQUEST_FREEZE 3
+/* MACROS
************************************************************************
*/
+
+#define KeEnterCriticalRegion(X) \
+{ \
+ PKTHREAD _Thread = KeGetCurrentThread(); \
+ if (_Thread) _Thread->KernelApcDisable--; \
+}
+
+#define KeLeaveCriticalRegion(X) \
+{ \
+ PKTHREAD _Thread = KeGetCurrentThread(); \
+ if((_Thread) && (++_Thread->KernelApcDisable == 0)) \
+ { \
+ if (!IsListEmpty(&_Thread->ApcState.ApcListHead[KernelMode])) \
+ { \
+ KiKernelApcDeliveryCheck(); \
+ } \
+ } \
+}
+
/* threadsch.c
********************************************************************/
/* Thread Scheduler Functions */
@@ -77,7 +97,29 @@
KiUnblockThread(PKTHREAD Thread,
PNTSTATUS WaitStatus,
KPRIORITY Increment);
+
+/* gmutex.c
********************************************************************/
+VOID
+FASTCALL
+KiAcquireGuardedMutexContented(PKGUARDED_MUTEX GuardedMutex);
+
+/* gate.c
**********************************************************************/
+
+VOID
+FASTCALL
+KeInitializeGate(PKGATE Gate);
+
+VOID
+FASTCALL
+KeSignalGateBoostPriority(PKGATE Gate);
+
+VOID
+FASTCALL
+KeWaitForGate(PKGATE Gate,
+ KWAIT_REASON WaitReason,
+ KPROCESSOR_MODE WaitMode);
+
/* ipi.c
********************************************************************/
BOOLEAN STDCALL
@@ -237,7 +279,9 @@
VOID STDCALL KiDeliverApc(KPROCESSOR_MODE PreviousMode,
PVOID Reserved,
PKTRAP_FRAME TrapFrame);
-
+VOID
+STDCALL
+KiKernelApcDeliveryCheck(VOID);
LONG
STDCALL
KiInsertQueue(IN PKQUEUE Queue,
_____
Modified: trunk/reactos/ntoskrnl/include/internal/ps.h
--- trunk/reactos/ntoskrnl/include/internal/ps.h 2005-04-15
00:48:25 UTC (rev 14624)
+++ trunk/reactos/ntoskrnl/include/internal/ps.h 2005-04-15
06:24:35 UTC (rev 14625)
@@ -97,7 +97,13 @@
CHAR Quantum; /* 6B */
KWAIT_BLOCK WaitBlock[4]; /* 6C */
PVOID LegoData; /* CC */
- ULONG KernelApcDisable; /* D0 */
+ union {
+ struct {
+ USHORT KernelApcDisable;
+ USHORT SpecialApcDisable;
+ };
+ ULONG CombinedApcDisable; /* D0 */
+ };
KAFFINITY UserAffinity; /* D4 */
UCHAR SystemAffinityActive;/* D8 */
UCHAR PowerState; /* D9 */
_____
Modified: trunk/reactos/ntoskrnl/ke/apc.c
--- trunk/reactos/ntoskrnl/ke/apc.c 2005-04-15 00:48:25 UTC (rev
14624)
+++ trunk/reactos/ntoskrnl/ke/apc.c 2005-04-15 06:24:35 UTC (rev
14625)
@@ -17,6 +17,51 @@
/* FUNCTIONS
*****************************************************************/
/*++
+ * KiKernelApcDeliveryCheck
+ * @implemented NT 5.2
+ *
+ * The KiKernelApcDeliveryCheck routine is called whenever APCs
have just
+ * been re-enabled in Kernel Mode, such as after leaving a Critical
or
+ * Guarded Region. It delivers APCs if the environment is right.
+ *
+ * Params:
+ * None.
+ *
+ * Returns:
+ * None.
+ *
+ * Remarks:
+ * This routine allows KeLeave/EnterCritical/GuardedRegion to be
used as a
+ * macro from inside WIN32K or other Drivers, which will then only
have to
+ * do an Import API call in the case where APCs are enabled again.
+ *
+ *--*/
+VOID
+STDCALL
+KiKernelApcDeliveryCheck(VOID)
+{
+ /* We should only deliver at passive */
+ if (KeGetCurrentIrql() == PASSIVE_LEVEL)
+ {
+ /* Raise to APC and Deliver APCs, then lower back to Passive */
+ KfRaiseIrql(APC_LEVEL);
+ KiDeliverApc(KernelMode, 0, 0);
+ KfLowerIrql(PASSIVE_LEVEL);
+ }
+ else
+ {
+ /*
+ * If we're not at passive level it means someone raised IRQL
+ * to APC level before the a critical or guarded section was
entered
+ * (e.g) by a fast mutex). This implies that the APCs shouldn't
+ * be delivered now, but after the IRQL is lowered to passive
+ * level again.
+ */
+ HalRequestSoftwareInterrupt(APC_LEVEL);
+ }
+}
+
+/*++
* KeEnterCriticalRegion
* @implemented NT4
*
@@ -37,6 +82,7 @@
* Callers of KeEnterCriticalRegion must be running at IRQL <=
APC_LEVEL.
*
*--*/
+#undef KeEnterCriticalRegion
VOID
STDCALL
KeEnterCriticalRegion(VOID)
@@ -47,6 +93,45 @@
}
/*++
+ * KeLeaveCriticalRegion
+ * @implemented NT4
+ *
+ * The KeLeaveCriticalRegion routine reenables the delivery of
normal
+ * kernel-mode APCs that were disabled by a call to
KeEnterCriticalRegion.
+ *
+ * Params:
+ * None.
+ *
+ * Returns:
+ * None.
+ *
+ * Remarks:
+ * Highest-level drivers can call this routine while running in the
context
+ * of the thread that requested the current I/O operation.
+ *
+ * Callers of KeLeaveCriticalRegion must be running at IRQL <=
DISPATCH_LEVEL.
+ *
+ *--*/
+#undef KeLeaveCriticalRegion
+VOID
+STDCALL
+KeLeaveCriticalRegion (VOID)
+{
+ PKTHREAD Thread = KeGetCurrentThread();
+
+ /* Check if Kernel APCs are now enabled */
+ if((Thread) && (++Thread->KernelApcDisable == 0))
+ {
+ /* Check if we need to request an APC Delivery */
+ if (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode]))
+ {
+ /* Check for the right environment */
+ KiKernelApcDeliveryCheck();
+ }
+ }
+}
+
+/*++
* KeInitializeApc
* @implemented NT4
*
@@ -326,45 +411,6 @@
}
/*++
- * KeLeaveCriticalRegion
- * @implemented NT4
- *
- * The KeLeaveCriticalRegion routine reenables the delivery of
normal
- * kernel-mode APCs that were disabled by a call to
KeEnterCriticalRegion.
- *
- * Params:
- * None.
- *
- * Returns:
- * None.
- *
- * Remarks:
- * Highest-level drivers can call this routine while running in the
context
- * of the thread that requested the current I/O operation.
- *
- * Callers of KeLeaveCriticalRegion must be running at IRQL <=
DISPATCH_LEVEL.
- *
- *--*/
-VOID
-STDCALL
-KeLeaveCriticalRegion (VOID)
-{
- PKTHREAD Thread = KeGetCurrentThread();
-
- /* Check if Kernel APCs are now enabled */
- if((Thread) && (++Thread->KernelApcDisable == 0)) {
-
- /* Check if we need to request an APC Delivery */
- if (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) {
-
- /* Set APC Pending */
- Thread->ApcState.KernelApcPending = TRUE;
- HalRequestSoftwareInterrupt(APC_LEVEL);
- }
- }
-}
-
-/*++
* KeRemoveQueueApc
*
* The KeRemoveQueueApc routine removes a given APC object from the
system
_____
Modified: trunk/reactos/ntoskrnl/ke/gmutex.c
--- trunk/reactos/ntoskrnl/ke/gmutex.c 2005-04-15 00:48:25 UTC (rev
14624)
+++ trunk/reactos/ntoskrnl/ke/gmutex.c 2005-04-15 06:24:35 UTC (rev
14625)
@@ -1,11 +1,11 @@
-/* $Id$
- *
+/*
* COPYRIGHT: See COPYING in the top level directory
- * PROJECT: ReactOS kernel
+ * PROJECT: ReactOS Kernel
* FILE: ntoskrnl/ke/gmutex.c
- * PURPOSE: Implements guarded mutex (w2k3+/64)
+ * PURPOSE: Implements Guarded Mutex
*
- * PROGRAMMERS: No programmer listed.
+ * PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net) and
+ * Filip Navara (xnavara(a)volny.cz)
*/
/* INCLUDES
*****************************************************************/
@@ -13,17 +13,209 @@
#include <ntoskrnl.h>
#include <internal/debug.h>
+UCHAR
+FASTCALL
+InterlockedClearBit(PLONG Destination,
+ LONG Bit);
+
+typedef enum _KGUARDED_MUTEX_BITS
+{
+ GM_LOCK_BIT = 1,
+ GM_LOCK_WAITER_WOKEN = 2,
+ GM_LOCK_WAITER_INC = 4
+} KGUARDED_MUTEX_BITS;
+
/* FUNCTIONS
*****************************************************************/
-/*
-KeAcquireGuardedMutex
-KeAcquireGuardedMutexUnsafe
-KeEnterGuardedRegion
-KeInitializeGuardedMutex
-KeReleaseGuardedMutexUnsafe
-KeTryToAcquireGuardedMutex
-KeReleaseGuardedMutex
-KeLeaveGuardedRegion
-*/
+/**
+ * @name KeEnterGuardedRegion
+ *
+ * Enters a guarded region. This causes all (incl. special kernel) APCs
+ * to be disabled.
+ */
+VOID
+STDCALL
+KeEnterGuardedRegion(VOID)
+{
+ /* Disable Special APCs */
+ KeGetCurrentThread()->SpecialApcDisable--;
+}
+/**
+ * @name KeLeaveGuardedRegion
+ *
+ * Leaves a guarded region and delivers pending APCs if possible.
+ */
+VOID
+STDCALL
+KeLeaveGuardedRegion(VOID)
+{
+ PKTHREAD Thread = KeGetCurrentThread();
+
+ /* Boost the enable count and check if Special APCs are enabled */
+ if (++Thread->SpecialApcDisable == 0)
+ {
+ /* Check if there are Kernel APCs on the list */
+ if (!IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode]))
+ {
+ /* Check for APC Delivery */
+ KiKernelApcDeliveryCheck();
+ }
+ }
+}
+
+VOID
+FASTCALL
+KeInitializeGuardedMutex(PKGUARDED_MUTEX GuardedMutex)
+{
+ /* Setup the Initial Data */
+ GuardedMutex->Count = GM_LOCK_BIT;
+ GuardedMutex->Owner = NULL;
+ GuardedMutex->Contention = 0;
+
+ /* Initialize the Wait Gate */
+ KeInitializeGate(&GuardedMutex->Gate);
+}
+
+VOID
+FASTCALL
+KiAcquireGuardedMutexContented(PKGUARDED_MUTEX GuardedMutex)
+{
+ ULONG BitsToRemove;
+ ULONG BitsToAdd;
+ LONG OldValue;
+
+ /* Increase the contention count */
+ InterlockedIncrement(&GuardedMutex->Contention);
+
+ /* Start by unlocking the Guarded Mutex */
+ BitsToRemove = GM_LOCK_BIT;
+ BitsToAdd = GM_LOCK_WAITER_INC;
+
+ while (1)
+ {
+ /* Get the Count Bits */
+ OldValue = (volatile LONG)GuardedMutex->Count;
+
+ /* Check if the Guarded Mutex is locked */
+ if (OldValue & GM_LOCK_BIT)
+ {
+ /* Unlock it by removing the Lock Bit */
+ if (InterlockedCompareExchange(&GuardedMutex->Count,
+ OldValue &~ BitsToRemove,
+ OldValue) == OldValue)
+ {
+ /* The Guarded Mutex is now unlocked */
+ break;
+ }
+ }
+ else
+ {
+ /* The Guarded Mutex isn't locked, so simply set the bits
*/
+ if (InterlockedCompareExchange(&GuardedMutex->Count,
+ OldValue | BitsToAdd,
+ OldValue) != OldValue)
+ {
+ /* The Guarded Mutex value changed behind our back,
start over */
+ continue;
+ }
+
+ /* Now we have to wait for it */
+ KeWaitForGate(&GuardedMutex->Gate, WrGuardedMutex,
KernelMode);
+
+ /* Ok, the wait is done, so set the new bits */
+ BitsToRemove = GM_LOCK_BIT | GM_LOCK_WAITER_WOKEN;
+ BitsToAdd = GM_LOCK_WAITER_WOKEN;
+ }
+ }
+}
+
+VOID
+FASTCALL
+KeAcquireGuardedMutex(PKGUARDED_MUTEX GuardedMutex)
+{
+ /* Disable Special APCs */
+ KeEnterGuardedRegion();
+
+ /* Do the Unsafe Acquire */
+ KeAcquireGuardedMutexUnsafe(GuardedMutex);
+}
+
+VOID
+FASTCALL
+KeAcquireGuardedMutexUnsafe(PKGUARDED_MUTEX GuardedMutex)
+{
+ /* Remove the lock */
+ if (!InterlockedClearBit(&GuardedMutex->Count, 0))
+ {
+ /* The Guarded Mutex was already locked, enter contented case
*/
+ KiAcquireGuardedMutexContented(GuardedMutex);
+ }
+
+ /* Set the Owner */
+ GuardedMutex->Owner = KeGetCurrentThread();
+}
+
+VOID
+FASTCALL
+KeReleaseGuardedMutexUnsafe(PKGUARDED_MUTEX GuardedMutex)
+{
+ LONG OldValue;
+
+ /* Destroy the Owner */
+ GuardedMutex->Owner = NULL;
+
+ /* Add the Lock Bit */
+ OldValue = InterlockedExchangeAdd(&GuardedMutex->Count, 1);
+
+ /* Check if it was already locked, but not woken */
+ if (OldValue && !(OldValue & GM_LOCK_WAITER_WOKEN))
+ {
+ /* Update the Oldvalue to what it should be now */
+ OldValue |= GM_LOCK_BIT;
+
+ /* Remove the Woken bit */
+ if (InterlockedCompareExchange(&GuardedMutex->Count,
+ OldValue &~
GM_LOCK_WAITER_WOKEN,
+ OldValue) == OldValue)
+ {
+ /* Signal the Gate */
+ KeSignalGateBoostPriority(&GuardedMutex->Gate);
+ }
+ }
+}
+
+VOID
+FASTCALL
+KeReleaseGuardedMutex(PKGUARDED_MUTEX GuardedMutex)
+{
+ /* Do the actual release */
+ KeReleaseGuardedMutexUnsafe(GuardedMutex);
+
+ /* Re-enable APCs */
+ KeLeaveGuardedRegion();
+}
+
+BOOL
+FASTCALL
+KeTryToAcquireGuardedMutex(PKGUARDED_MUTEX GuardedMutex)
+{
+ /* Block APCs */
+ KeEnterGuardedRegion();
+
+ /* Remove the lock */
+ if (InterlockedClearBit(&GuardedMutex->Count, 0))
+ {
+ /* Re-enable APCs */
+ KeLeaveGuardedRegion();
+
+ /* Return failure */
+ return FALSE;
+ }
+
+ /* Set the Owner */
+ GuardedMutex->Owner = KeGetCurrentThread();
+ return TRUE;
+}
+
/* EOF */
_____
Modified: trunk/reactos/ntoskrnl/ntoskrnl.def
--- trunk/reactos/ntoskrnl/ntoskrnl.def 2005-04-15 00:48:25 UTC (rev
14624)
+++ trunk/reactos/ntoskrnl/ntoskrnl.def 2005-04-15 06:24:35 UTC (rev
14625)
@@ -649,6 +649,7 @@
;KiBugCheckData DATA
KiCoprocessorError@0
KiDeliverApc@12
+KiKernelApcDeliveryCheck@0
KiDispatchInterrupt@0
KiEnableTimerWatchdog
KiInterruptDispatch2@8
_____
Modified: trunk/reactos/ntoskrnl/ps/thread.c
--- trunk/reactos/ntoskrnl/ps/thread.c 2005-04-15 00:48:25 UTC (rev
14624)
+++ trunk/reactos/ntoskrnl/ps/thread.c 2005-04-15 06:24:35 UTC (rev
14625)
@@ -44,10 +44,15 @@
/* FUNCTIONS
***************************************************************/
+#ifdef KeGetCurrentThread
+#undef KeGetCurrentThread
+#endif
/*
* @implemented
*/
-PKTHREAD STDCALL KeGetCurrentThread(VOID)
+PKTHREAD
+STDCALL
+KeGetCurrentThread(VOID)
{
#ifdef CONFIG_SMP
ULONG Flags;
_____
Modified: trunk/reactos/w32api/include/ddk/winddk.h
--- trunk/reactos/w32api/include/ddk/winddk.h 2005-04-15 00:48:25 UTC
(rev 14624)
+++ trunk/reactos/w32api/include/ddk/winddk.h 2005-04-15 06:24:35 UTC
(rev 14625)
@@ -929,6 +929,21 @@
ULONG OldIrql;
} FAST_MUTEX, *PFAST_MUTEX;
+typedef struct _KGUARDED_MUTEX
+{
+ LONG Count;
+ struct _KTHREAD* Owner;
+ ULONG Contention;
+ struct _KGATE* Gate;
+ union {
+ struct {
+ SHORT KernelApcDisable;
+ SHORT SpecialApcDisable;
+ };
+ ULONG CombinedApcDisable;
+ };
+} KGUARDED_MUTEX, *PKGUARDED_MUTEX, *RESTRICTED_POINTER
PRKGUARDED_MUTEX;
+
typedef struct _KTIMER {
DISPATCHER_HEADER Header;
ULARGE_INTEGER DueTime;