- Optimized the dispatcher lock. It is now gone on non-SMP systems and IRQL is raised...
authorAlex Ionescu <aionescu@gmail.com>
Thu, 5 Jan 2006 04:26:55 +0000 (04:26 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Thu, 5 Jan 2006 04:26:55 +0000 (04:26 +0000)
- Made inlined functions in ke/wait.c macros, because they weren't being inlined.
- Created separate cases for satisfying mutant, non-mutant and generic objects, to optimize wait satisfaction.
- Fixed some places which werne't setting the dispatcher header's size member correctly.
- Fixed formatting in ke/wait.c
- Fixed a case in KiCheckAlertability: we also need to check if the thread is alerted in Kernel-Mode, even if the wait mode given was user and user-mode is not alerted.
- Fixed signaling checks across the wait code and removed KiCheckIfObjectSignaled. We must not consider the mutant as signaled if SignalState is = 1.
- Fix code to check if the wait blocks' status is STATUS_TIMEOUT, because we do not need to check for signal state in that case.
- Removed the exports for internal dispatcher lock routines.

** Thanks to Waxdragon for stress-testing this for an hour :)

svn path=/trunk/; revision=20568

reactos/ntoskrnl/include/internal/ke.h
reactos/ntoskrnl/ke/i386/ctxswitch.S
reactos/ntoskrnl/ke/kthread.c
reactos/ntoskrnl/ke/wait.c
reactos/ntoskrnl/ntoskrnl.def
reactos/ntoskrnl/ps/psmgr.c

index 9e0370e..30bf212 100644 (file)
@@ -44,30 +44,173 @@ extern ULONG_PTR KERNEL_BASE;
 
 /* MACROS *************************************************************************/
 
 
 /* MACROS *************************************************************************/
 
-#define KeEnterCriticalRegion() \
-{ \
-    PKTHREAD _Thread = KeGetCurrentThread(); \
-    if (_Thread) _Thread->KernelApcDisable--; \
+/*
+ * On UP machines, we don't actually have a spinlock, we merely raise
+ * IRQL to DPC level.
+ */
+#ifndef CONFIG_SMP
+#define KeInitializeDispatcher()
+#define KeAcquireDispatcherDatabaseLock() KeRaiseIrqlToDpcLevel();
+#define KeAcquireDispatcherDatabaseLockAtDpcLevel()
+#define KeReleaseDispatcherDatabaseLockFromDpcLevel()
+#else
+#define KeInitializeDispatcher() KeInitializeSpinLock(&DispatcherDatabaseLock);
+#define KeAcquireDispatcherDatabaseLock() KfAcquireSpinLock(&DispatcherDatabaseLock);
+#define KeAcquireDispatcherDatabaseLockAtDpcLevel() \
+    KeAcquireSpinLockAtDpcLevel (&DispatcherDatabaseLock);
+#define KeReleaseDispatcherDatabaseLockFromDpcLevel() \
+    KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock);
+#endif
+
+/* The following macro initializes a dispatcher object's header */
+#define KeInitializeDispatcherHeader(Header, t, s, State)                   \
+{                                                                           \
+    (Header)->Type = t;                                                     \
+    (Header)->Absolute = 0;                                                 \
+    (Header)->Inserted = 0;                                                 \
+    (Header)->Size = s;                                                     \
+    (Header)->SignalState = State;                                          \
+    InitializeListHead(&((Header)->WaitListHead));                          \
 }
 
 }
 
-#define KeLeaveCriticalRegion() \
-{ \
-    PKTHREAD _Thread = KeGetCurrentThread(); \
-    if((_Thread) && (++_Thread->KernelApcDisable == 0)) \
-    { \
-        if (!IsListEmpty(&_Thread->ApcState.ApcListHead[KernelMode]) && \
-            (_Thread->SpecialApcDisable == 0)) \
-        { \
-            KiCheckForKernelApcDelivery(); \
-        } \
-    } \
+/* The following macro satisfies the wait of any dispatcher object */
+#define KiSatisfyObjectWait(Object, Thread)                                 \
+{                                                                           \
+    /* Special case for Mutants */                                          \
+    if ((Object)->Header.Type == MutantObject)                              \
+    {                                                                       \
+        /* Decrease the Signal State */                                     \
+        (Object)->Header.SignalState--;                                     \
+                                                                            \
+        /* Check if it's now non-signaled */                                \
+        if (!(Object)->Header.SignalState)                                  \
+        {                                                                   \
+            /* Set the Owner Thread */                                      \
+            (Object)->OwnerThread = Thread;                                 \
+                                                                            \
+            /* Disable APCs if needed */                                    \
+            Thread->KernelApcDisable -= (Object)->ApcDisable;               \
+                                                                            \
+            /* Check if it's abandoned */                                   \
+            if ((Object)->Abandoned)                                        \
+            {                                                               \
+                /* Unabandon it */                                          \
+                (Object)->Abandoned = FALSE;                                \
+                                                                            \
+                /* Return Status */                                         \
+                Thread->WaitStatus = STATUS_ABANDONED;                      \
+            }                                                               \
+                                                                            \
+            /* Insert it into the Mutant List */                            \
+            InsertHeadList(&Thread->MutantListHead,                         \
+                           &(Object)->MutantListEntry);                     \
+        }                                                                   \
+    }                                                                       \
+    else if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) ==               \
+             EventSynchronizationObject)                                    \
+    {                                                                       \
+        /* Synchronization Timers and Events just get un-signaled */        \
+        (Object)->Header.SignalState = 0;                                   \
+    }                                                                       \
+    else if ((Object)->Header.Type == SemaphoreObject)                      \
+    {                                                                       \
+        /* These ones can have multiple states, so we only decrease it */   \
+        (Object)->Header.SignalState--;                                     \
+    }                                                                       \
 }
 
 }
 
-#define KEBUGCHECKWITHTF(a,b,c,d,e,f) \
-    DbgPrint("KeBugCheckWithTf at %s:%i\n",__FILE__,__LINE__), KeBugCheckWithTf(a,b,c,d,e,f)
+/* The following macro satisfies the wait of a mutant dispatcher object */
+#define KiSatisfyMutantWait(Object, Thread)                                 \
+{                                                                           \
+    /* Decrease the Signal State */                                         \
+    (Object)->Header.SignalState--;                                         \
+                                                                            \
+    /* Check if it's now non-signaled */                                    \
+    if (!(Object)->Header.SignalState)                                      \
+    {                                                                       \
+        /* Set the Owner Thread */                                          \
+        (Object)->OwnerThread = Thread;                                     \
+                                                                            \
+        /* Disable APCs if needed */                                        \
+        Thread->KernelApcDisable -= (Object)->ApcDisable;                   \
+                                                                            \
+        /* Check if it's abandoned */                                       \
+        if ((Object)->Abandoned)                                            \
+        {                                                                   \
+            /* Unabandon it */                                              \
+            (Object)->Abandoned = FALSE;                                    \
+                                                                            \
+            /* Return Status */                                             \
+            Thread->WaitStatus = STATUS_ABANDONED;                          \
+        }                                                                   \
+                                                                            \
+        /* Insert it into the Mutant List */                                \
+        InsertHeadList(&Thread->MutantListHead,                             \
+                       &(Object)->MutantListEntry);                         \
+    }                                                                       \
+}
+
+/* The following macro satisfies the wait of any nonmutant dispatcher object */
+#define KiSatisfyNonMutantWait(Object, Thread)                              \
+{                                                                           \
+    if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) ==                    \
+             EventSynchronizationObject)                                    \
+    {                                                                       \
+        /* Synchronization Timers and Events just get un-signaled */        \
+        (Object)->Header.SignalState = 0;                                   \
+    }                                                                       \
+    else if ((Object)->Header.Type == SemaphoreObject)                      \
+    {                                                                       \
+        /* These ones can have multiple states, so we only decrease it */   \
+        (Object)->Header.SignalState--;                                     \
+    }                                                                       \
+}
+
+/* The following macro satisfies multiple objects in a wait state */
+#define KiSatisifyMultipleObjectWaits(FirstBlock)                           \
+{                                                                           \
+    PKWAIT_BLOCK WaitBlock = FirstBlock;                                    \
+    PKTHREAD WaitThread = WaitBlock->Thread;                                \
+                                                                            \
+    /* Loop through all the Wait Blocks, and wake each Object */            \
+    do                                                                      \
+    {                                                                       \
+        /* Make sure it hasn't timed out */                                 \
+        if (WaitBlock->WaitKey != STATUS_TIMEOUT)                           \
+        {                                                                   \
+            /* Wake the Object */                                           \
+            KiSatisfyObjectWait((PKMUTANT)WaitBlock->Object, WaitThread);   \
+        }                                                                   \
+                                                                            \
+        /* Move to the next block */                                        \
+        WaitBlock = WaitBlock->NextWaitBlock;                               \
+    } while (WaitBlock != FirstBlock);                                      \
+}
 
 
-#define MAXIMUM_PROCESSORS      32
+extern KSPIN_LOCK DispatcherDatabaseLock;
 
 
+#define KeEnterCriticalRegion()                                             \
+{                                                                           \
+    PKTHREAD _Thread = KeGetCurrentThread();                                \
+    if (_Thread) _Thread->KernelApcDisable--;                               \
+}
+
+#define KeLeaveCriticalRegion()                                             \
+{                                                                           \
+    PKTHREAD _Thread = KeGetCurrentThread();                                \
+    if((_Thread) && (++_Thread->KernelApcDisable == 0))                     \
+    {                                                                       \
+        if (!IsListEmpty(&_Thread->ApcState.ApcListHead[KernelMode]) &&     \
+            (_Thread->SpecialApcDisable == 0))                              \
+        {                                                                   \
+            KiCheckForKernelApcDelivery();                                  \
+        }                                                                   \
+    }                                                                       \
+}
+
+#define KEBUGCHECKWITHTF(a,b,c,d,e,f) \
+    DbgPrint("KeBugCheckWithTf at %s:%i\n",__FILE__,__LINE__), \
+             KeBugCheckWithTf(a,b,c,d,e,f)
 
 /* INTERNAL KERNEL FUNCTIONS ************************************************/
 
 
 /* INTERNAL KERNEL FUNCTIONS ************************************************/
 
@@ -243,26 +386,10 @@ KiExpireTimers(
     PVOID SystemArgument2
 );
 
     PVOID SystemArgument2
 );
 
-KIRQL
-__inline
-FASTCALL
-KeAcquireDispatcherDatabaseLock(VOID);
-
 VOID
 VOID
-__inline
-FASTCALL
-KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID);
-
-VOID
-__inline
 FASTCALL
 KeReleaseDispatcherDatabaseLock(KIRQL Irql);
 
 FASTCALL
 KeReleaseDispatcherDatabaseLock(KIRQL Irql);
 
-VOID
-__inline
-FASTCALL
-KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID);
-
 VOID
 STDCALL
 KeInitializeThread(
 VOID
 STDCALL
 KeInitializeThread(
@@ -312,16 +439,6 @@ KeExpireTimers(
     PVOID Arg3
 );
 
     PVOID Arg3
 );
 
-VOID
-__inline
-FASTCALL
-KeInitializeDispatcherHeader(
-    DISPATCHER_HEADER* Header,
-    ULONG Type,
-    ULONG Size,
-    ULONG SignalState
-);
-
 VOID
 NTAPI
 KeDumpStackFrames(PULONG Frame);
 VOID
 NTAPI
 KeDumpStackFrames(PULONG Frame);
@@ -362,14 +479,6 @@ KiInsertTimer(
     LARGE_INTEGER DueTime
 );
 
     LARGE_INTEGER DueTime
 );
 
-VOID
-__inline
-FASTCALL
-KiSatisfyObjectWait(
-    PDISPATCHER_HEADER Object,
-    PKTHREAD Thread
-);
-
 BOOLEAN
 __inline
 FASTCALL
 BOOLEAN
 __inline
 FASTCALL
@@ -378,15 +487,10 @@ KiIsObjectSignaled(
     PKTHREAD Thread
 );
 
     PKTHREAD Thread
 );
 
-VOID
-__inline
-FASTCALL
-KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock);
-
 VOID
 FASTCALL
 KiWaitTest(
 VOID
 FASTCALL
 KiWaitTest(
-    PDISPATCHER_HEADER Object,
+    PVOID Object,
     KPRIORITY Increment
 );
 
     KPRIORITY Increment
 );
 
@@ -506,11 +610,6 @@ VOID
 NTAPI
 KeInitDispatcher(VOID);
 
 NTAPI
 KeInitDispatcher(VOID);
 
-VOID
-__inline
-FASTCALL
-KeInitializeDispatcher(VOID);
-
 VOID
 NTAPI
 KiInitializeSystemClock(VOID);
 VOID
 NTAPI
 KiInitializeSystemClock(VOID);
index f8de2f0..3192531 100644 (file)
@@ -21,6 +21,8 @@
 
 /* GLOBALS ****************************************************************/  
 
 
 /* GLOBALS ****************************************************************/  
 
+.extern _DispatcherDatabaseLock
+
 /* FUNCTIONS ****************************************************************/
 
 /*++
 /* FUNCTIONS ****************************************************************/
 
 /*++
@@ -244,7 +246,10 @@ SameProcess:
     pop [ebx+KPCR_EXCEPTION_LIST]
 
     /* Return */
     pop [ebx+KPCR_EXCEPTION_LIST]
 
     /* Return */
-    call @KeReleaseDispatcherDatabaseLockFromDpcLevel@0
+//#ifdef CONFIG_SMP
+    mov ecx, _DispatcherDatabaseLock
+    call @KefReleaseSpinLockFromDpcLevel@4
+//#endif
     ret 
 
 /*++
     ret 
 
 /*++
index 0914c09..b473e47 100644 (file)
@@ -819,7 +819,7 @@ KeInitializeThread(PKPROCESS Process,
     DPRINT("Initializing Dispatcher Header for New Thread: %x in Process: %x\n", Thread, Process);
     KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
                                  ThreadObject,
     DPRINT("Initializing Dispatcher Header for New Thread: %x in Process: %x\n", Thread, Process);
     KeInitializeDispatcherHeader(&Thread->DispatcherHeader,
                                  ThreadObject,
-                                 sizeof(KTHREAD),
+                                 sizeof(KTHREAD) / sizeof(LONG),
                                  FALSE);
 
     DPRINT("Thread Header Created. SystemRoutine: %x, StartRoutine: %x with Context: %x\n",
                                  FALSE);
 
     DPRINT("Thread Header Created. SystemRoutine: %x, StartRoutine: %x with Context: %x\n",
index 2bc9db9..79b18f6 100644 (file)
@@ -2,7 +2,7 @@
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS Kernel
  * FILE:            ntoskrnl/ke/wait.c
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS Kernel
  * FILE:            ntoskrnl/ke/wait.c
- * PURPOSE:         Manages dispatch level wait-related code
+ * PURPOSE:         Manages waiting for Dispatcher Objects
  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  *                  Gunnar Dalsnes
  */
  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
  *                  Gunnar Dalsnes
  */
@@ -16,7 +16,7 @@
 
 /* GLOBALS ******************************************************************/
 
 
 /* GLOBALS ******************************************************************/
 
-static KSPIN_LOCK DispatcherDatabaseLock;
+KSPIN_LOCK DispatcherDatabaseLock;
 
 /* Tells us if the Timer or Event is a Syncronization or Notification Object */
 #define TIMER_OR_EVENT_TYPE 0x7L
 
 /* Tells us if the Timer or Event is a Syncronization or Notification Object */
 #define TIMER_OR_EVENT_TYPE 0x7L
@@ -30,38 +30,58 @@ BOOLEAN
 __inline
 FASTCALL
 KiCheckAlertability(BOOLEAN Alertable,
 __inline
 FASTCALL
 KiCheckAlertability(BOOLEAN Alertable,
-                    PKTHREAD CurrentThread,
+                    PKTHREAD Thread,
                     KPROCESSOR_MODE WaitMode,
                     PNTSTATUS Status)
 {
                     KPROCESSOR_MODE WaitMode,
                     PNTSTATUS Status)
 {
-    /* At this point, we have to do a wait, so make sure we can make the thread Alertable if requested */
-    if (Alertable) {
-
+    /*
+     * At this point, we have to do a wait, so make sure we can make
+     * the thread Alertable if requested.
+     */
+    if (Alertable)
+    {
         /* If the Thread is Alerted, set the Wait Status accordingly */
         /* If the Thread is Alerted, set the Wait Status accordingly */
-        if (CurrentThread->Alerted[(int)WaitMode]) {
-
-            CurrentThread->Alerted[(int)WaitMode] = FALSE;
-            DPRINT("Thread was Alerted\n");
+        if (Thread->Alerted[(int)WaitMode])
+        {
+            Thread->Alerted[(int)WaitMode] = FALSE;
+            DPRINT("Thread was Alerted in the specified Mode\n");
             *Status = STATUS_ALERTED;
             return TRUE;
             *Status = STATUS_ALERTED;
             return TRUE;
-
-        /* If there are User APCs Pending, then we can't really be alertable */
-        } else if ((!IsListEmpty(&CurrentThread->ApcState.ApcListHead[UserMode])) &&
-                    (WaitMode != KernelMode)) {
-
+        }
+        else if ((WaitMode != KernelMode) &&
+                (!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
+        {
+            /* If there are User APCs Pending, then we can't really be alertable */
             DPRINT("APCs are Pending\n");
             DPRINT("APCs are Pending\n");
-            CurrentThread->ApcState.UserApcPending = TRUE;
+            Thread->ApcState.UserApcPending = TRUE;
             *Status = STATUS_USER_APC;
             return TRUE;
         }
             *Status = STATUS_USER_APC;
             return TRUE;
         }
-
-    /* If there are User APCs Pending and we are waiting in usermode, then we must notify the caller */
-    } else if ((CurrentThread->ApcState.UserApcPending) && (WaitMode != KernelMode)) {
-            DPRINT("APCs are Pending\n");
-            *Status = STATUS_USER_APC;
+        else if (Thread->Alerted[KernelMode])
+        {
+            /* 
+             * The thread is not alerted in the mode given, but it is alerted
+             * in kernel-mode.
+             */
+            Thread->Alerted[KernelMode] = FALSE;
+            DPRINT("Thread was Alerted in Kernel-Mode\n");
+            *Status = STATUS_ALERTED;
             return TRUE;
             return TRUE;
+        }
+    }
+    else if ((WaitMode != KernelMode) &&
+             (Thread->ApcState.UserApcPending))
+    {
+        /*
+         * If there are User APCs Pending and we are waiting in usermode,
+         * then we must notify the caller
+         */
+        DPRINT("APCs are Pending\n");
+        *Status = STATUS_USER_APC;
+        return TRUE;
     }
 
     }
 
+    /* Stay in the loop */
     return FALSE;
 }
 
     return FALSE;
 }
 
@@ -90,14 +110,14 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
     DPRINT("Entering KeDelayExecutionThread\n");
 
     /* Check if the lock is already held */
     DPRINT("Entering KeDelayExecutionThread\n");
 
     /* Check if the lock is already held */
-    if (CurrentThread->WaitNext)  {
-
+    if (CurrentThread->WaitNext)
+    {
         /* Lock is held, disable Wait Next */
         DPRINT("Lock is held\n");
         CurrentThread->WaitNext = FALSE;
         /* Lock is held, disable Wait Next */
         DPRINT("Lock is held\n");
         CurrentThread->WaitNext = FALSE;
-
-    } else {
-
+    }
+    else
+    {
         /* Lock not held, acquire it */
         DPRINT("Lock is not held, acquiring\n");
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
         /* Lock not held, acquire it */
         DPRINT("Lock is not held, acquiring\n");
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
@@ -107,11 +127,10 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
     TimerWaitBlock = &CurrentThread->WaitBlock[TIMER_WAIT_BLOCK];
 
     /* Start Wait Loop */
     TimerWaitBlock = &CurrentThread->WaitBlock[TIMER_WAIT_BLOCK];
 
     /* Start Wait Loop */
-    do {
-
-        /* We are going to wait no matter what (that's the point), so test Alertability */
-        if (KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status))
-            break;
+    do
+    {
+        /* Chceck if we can do an alertable wait, if requested */
+        if (KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status)) break;
 
         /* Set Timer */
         ThreadTimer = &CurrentThread->Timer;
 
         /* Set Timer */
         ThreadTimer = &CurrentThread->Timer;
@@ -129,30 +148,31 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
         InsertTailList(&ThreadTimer->Header.WaitListHead, &TimerWaitBlock->WaitListEntry);
 
         /* Insert the Timer into the Timer Lists and enable it */
         InsertTailList(&ThreadTimer->Header.WaitListHead, &TimerWaitBlock->WaitListEntry);
 
         /* Insert the Timer into the Timer Lists and enable it */
-        if (!KiInsertTimer(ThreadTimer, *Interval)) {
-
+        if (!KiInsertTimer(ThreadTimer, *Interval))
+        {
             /* FIXME: The timer already expired, we should find a new ready thread */
             Status = STATUS_SUCCESS;
             break;
         }
 
         /* Handle Kernel Queues */
             /* FIXME: The timer already expired, we should find a new ready thread */
             Status = STATUS_SUCCESS;
             break;
         }
 
         /* Handle Kernel Queues */
-        if (CurrentThread->Queue) {
-
+        if (CurrentThread->Queue)
+        {
             DPRINT("Waking Queue\n");
             KiWakeQueue(CurrentThread->Queue);
         }
 
         /* Block the Thread */
             DPRINT("Waking Queue\n");
             KiWakeQueue(CurrentThread->Queue);
         }
 
         /* Block the Thread */
-        DPRINT("Blocking the Thread: %d, %d, %x\n", Alertable, WaitMode, KeGetCurrentThread());
+        DPRINT("Blocking the Thread: %d, %d, %x\n",
+                Alertable, WaitMode, KeGetCurrentThread());
         KiBlockThread(&Status,
                       Alertable,
                       WaitMode,
                       DelayExecution);
 
         /* Check if we were executing an APC or if we timed out */
         KiBlockThread(&Status,
                       Alertable,
                       WaitMode,
                       DelayExecution);
 
         /* Check if we were executing an APC or if we timed out */
-        if (Status != STATUS_KERNEL_APC) {
-
+        if (Status != STATUS_KERNEL_APC)
+        {
             /* This is a good thing */
             if (Status == STATUS_TIMEOUT) Status = STATUS_SUCCESS;
 
             /* This is a good thing */
             if (Status == STATUS_TIMEOUT) Status = STATUS_SUCCESS;
 
@@ -160,13 +180,14 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode,
             return Status;
         }
 
             return Status;
         }
 
-        DPRINT("Looping Again\n");
+        DPRINT("Looping Again\n"); // FIXME: Need to modify interval
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-
-    while (TRUE);
+    }
+    while (TRUE);
 
     /* Release the Lock, we are done */
 
     /* Release the Lock, we are done */
-    DPRINT("Returning from KeDelayExecutionThread(), %x. Status: %d\n", KeGetCurrentThread(), Status);
+    DPRINT("Returning from KeDelayExecutionThread(), %x. Status: %d\n",
+            KeGetCurrentThread(), Status);
     KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
     return Status;
 }
     KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
     return Status;
 }
@@ -194,33 +215,32 @@ KeWaitForSingleObject(PVOID Object,
                       BOOLEAN Alertable,
                       PLARGE_INTEGER Timeout)
 {
                       BOOLEAN Alertable,
                       PLARGE_INTEGER Timeout)
 {
-    PDISPATCHER_HEADER CurrentObject;
+    PKMUTANT CurrentObject;
     PKWAIT_BLOCK WaitBlock;
     PKWAIT_BLOCK TimerWaitBlock;
     PKTIMER ThreadTimer;
     PKTHREAD CurrentThread = KeGetCurrentThread();
     NTSTATUS Status;
     NTSTATUS WaitStatus;
     PKWAIT_BLOCK WaitBlock;
     PKWAIT_BLOCK TimerWaitBlock;
     PKTIMER ThreadTimer;
     PKTHREAD CurrentThread = KeGetCurrentThread();
     NTSTATUS Status;
     NTSTATUS WaitStatus;
-
     DPRINT("Entering KeWaitForSingleObject\n");
 
     /* Check if the lock is already held */
     DPRINT("Entering KeWaitForSingleObject\n");
 
     /* Check if the lock is already held */
-    if (CurrentThread->WaitNext)  {
-
+    if (CurrentThread->WaitNext)
+    {
         /* Lock is held, disable Wait Next */
         DPRINT("Lock is held\n");
         CurrentThread->WaitNext = FALSE;
         /* Lock is held, disable Wait Next */
         DPRINT("Lock is held\n");
         CurrentThread->WaitNext = FALSE;
-
-    } else {
-
+    }
+    else
+    {
         /* Lock not held, acquire it */
         DPRINT("Lock is not held, acquiring\n");
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
     }
 
     /* Start the actual Loop */
         /* Lock not held, acquire it */
         DPRINT("Lock is not held, acquiring\n");
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
     }
 
     /* Start the actual Loop */
-    do {
-
+    do
+    {
         /* Get the current Wait Status */
         WaitStatus = CurrentThread->WaitStatus;
 
         /* Get the current Wait Status */
         WaitStatus = CurrentThread->WaitStatus;
 
@@ -228,30 +248,38 @@ KeWaitForSingleObject(PVOID Object,
         CurrentThread->WaitBlockList = WaitBlock = &CurrentThread->WaitBlock[0];
 
         /* Get the Current Object */
         CurrentThread->WaitBlockList = WaitBlock = &CurrentThread->WaitBlock[0];
 
         /* Get the Current Object */
-        CurrentObject = (PDISPATCHER_HEADER)Object;
-
-        /* Check if the Object is Signaled */
-        if (KiIsObjectSignaled(CurrentObject, CurrentThread)) {
-
-            /* Just unwait this guy and exit */
-            if (CurrentObject->SignalState != (LONG)MINLONG) {
-
-                /* It has a normal signal state, so unwait it and return */
-                KiSatisfyObjectWait(CurrentObject, CurrentThread);
-                Status = STATUS_WAIT_0;
-                goto DontWait;
-
-            } else {
-
-                /* Is this a Mutant? */
-                if (CurrentObject->Type == MutantObject) {
-
+        CurrentObject = (PKMUTANT)Object;
+
+        /* Check if it's a mutant */
+        if (CurrentObject->Header.Type == MutantObject)
+        {
+            /* Check its signal state or if we own it */
+            if ((CurrentObject->Header.SignalState > 0) ||
+                (CurrentThread == CurrentObject->OwnerThread))
+            {
+                /* Just unwait this guy and exit */
+                if (CurrentObject->Header.SignalState != (LONG)MINLONG)
+                {
+                    /* It has a normal signal state, so unwait it and return */
+                    KiSatisfyMutantWait(CurrentObject, CurrentThread);
+                    Status = STATUS_WAIT_0;
+                    goto DontWait;
+                }
+                else
+                {
                     /* According to wasm.ru, we must raise this exception (tested and true) */
                     KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
                     ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
                 }
             }
         }
                     /* According to wasm.ru, we must raise this exception (tested and true) */
                     KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
                     ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
                 }
             }
         }
+        else if (CurrentObject->Header.SignalState > 0)
+        {
+            /* Another satisfied object */
+            KiSatisfyNonMutantWait(CurrentObject, CurrentThread);
+            Status = STATUS_WAIT_0;
+            goto DontWait;
+        }
 
         /* Set up the Wait Block */
         WaitBlock->Object = CurrentObject;
 
         /* Set up the Wait Block */
         WaitBlock->Object = CurrentObject;
@@ -261,18 +289,17 @@ KeWaitForSingleObject(PVOID Object,
         WaitBlock->NextWaitBlock = WaitBlock;
 
         /* Make sure we can satisfy the Alertable request */
         WaitBlock->NextWaitBlock = WaitBlock;
 
         /* Make sure we can satisfy the Alertable request */
-        if (KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status))
-            break;
+        if (KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status)) break;
 
         /* Set the Wait Status */
         CurrentThread->WaitStatus = Status;
 
         /* Enable the Timeout Timer if there was any specified */
 
         /* Set the Wait Status */
         CurrentThread->WaitStatus = Status;
 
         /* Enable the Timeout Timer if there was any specified */
-        if (Timeout != NULL) {
-
-            /* However if 0 timeout was specified, then we must fail since we need to peform a wait */
-            if (!Timeout->QuadPart) {
-
+        if (Timeout)
+        {
+            /* Fail if the timeout interval is actually 0 */
+            if (!Timeout->QuadPart)
+            {
                 /* Return a timeout */
                 Status = STATUS_TIMEOUT;
                 goto DontWait;
                 /* Return a timeout */
                 Status = STATUS_TIMEOUT;
                 goto DontWait;
@@ -294,48 +321,53 @@ KeWaitForSingleObject(PVOID Object,
 
             /* Link the timer to this Wait Block */
             InitializeListHead(&ThreadTimer->Header.WaitListHead);
 
             /* Link the timer to this Wait Block */
             InitializeListHead(&ThreadTimer->Header.WaitListHead);
-            InsertTailList(&ThreadTimer->Header.WaitListHead, &TimerWaitBlock->WaitListEntry);
+            InsertTailList(&ThreadTimer->Header.WaitListHead,
+                           &TimerWaitBlock->WaitListEntry);
 
             /* Insert the Timer into the Timer Lists and enable it */
 
             /* Insert the Timer into the Timer Lists and enable it */
-            if (!KiInsertTimer(ThreadTimer, *Timeout)) {
-
-                /* Return a timeout if we couldn't insert the timer for some reason */
+            if (!KiInsertTimer(ThreadTimer, *Timeout))
+            {
+                /* Return a timeout if we couldn't insert the timer */
                 Status = STATUS_TIMEOUT;
                 goto DontWait;
             }
         }
 
         /* Link the Object to this Wait Block */
                 Status = STATUS_TIMEOUT;
                 goto DontWait;
             }
         }
 
         /* Link the Object to this Wait Block */
-        InsertTailList(&CurrentObject->WaitListHead, &WaitBlock->WaitListEntry);
+        InsertTailList(&CurrentObject->Header.WaitListHead,
+                       &WaitBlock->WaitListEntry);
 
         /* Handle Kernel Queues */
 
         /* Handle Kernel Queues */
-        if (CurrentThread->Queue) {
-
+        if (CurrentThread->Queue)
+        {
             DPRINT("Waking Queue\n");
             KiWakeQueue(CurrentThread->Queue);
         }
 
         /* Block the Thread */
             DPRINT("Waking Queue\n");
             KiWakeQueue(CurrentThread->Queue);
         }
 
         /* Block the Thread */
-        DPRINT("Blocking the Thread: %d, %d, %d, %x\n", Alertable, WaitMode, WaitReason, KeGetCurrentThread());
+        DPRINT("Blocking the Thread: %d, %d, %d, %x\n",
+                Alertable, WaitMode, WaitReason, KeGetCurrentThread());
         KiBlockThread(&Status,
                       Alertable,
                       WaitMode,
                       (UCHAR)WaitReason);
 
         /* Check if we were executing an APC */
         KiBlockThread(&Status,
                       Alertable,
                       WaitMode,
                       (UCHAR)WaitReason);
 
         /* Check if we were executing an APC */
-        if (Status != STATUS_KERNEL_APC) {
-
+        if (Status != STATUS_KERNEL_APC)
+        {
             /* Return Status */
             return Status;
         }
 
             /* Return Status */
             return Status;
         }
 
-        DPRINT("Looping Again\n");
+        /* Loop again and acquire the dispatcher lock */
+        DPRINT("Looping Again\n"); // FIXME: Change interval
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-
-    while (TRUE);
+    }
+    while (TRUE);
 
     /* Release the Lock, we are done */
 
     /* Release the Lock, we are done */
-    DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n", KeGetCurrentThread(), Status);
+    DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n",
+            KeGetCurrentThread(), Status);
     KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
     return Status;
 
     KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
     return Status;
 
@@ -344,7 +376,8 @@ DontWait:
     KiAdjustQuantumThread(CurrentThread);
 
     /* Release & Return */
     KiAdjustQuantumThread(CurrentThread);
 
     /* Release & Return */
-    DPRINT("Returning from KeWaitForMultipleObjects(), %x. Status: %d\n. We did not wait.", KeGetCurrentThread(), Status);
+    DPRINT("Quick-return from KeWaitForMultipleObjects(), %x. Status: %d\n.",
+            KeGetCurrentThread(), Status);
     KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
     return Status;
 }
     KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
     return Status;
 }
@@ -362,7 +395,7 @@ KeWaitForMultipleObjects(ULONG Count,
                          PLARGE_INTEGER Timeout,
                          PKWAIT_BLOCK WaitBlockArray)
 {
                          PLARGE_INTEGER Timeout,
                          PKWAIT_BLOCK WaitBlockArray)
 {
-    PDISPATCHER_HEADER CurrentObject;
+    PKMUTANT CurrentObject;
     PKWAIT_BLOCK WaitBlock;
     PKWAIT_BLOCK TimerWaitBlock;
     PKTIMER ThreadTimer;
     PKWAIT_BLOCK WaitBlock;
     PKWAIT_BLOCK TimerWaitBlock;
     PKTIMER ThreadTimer;
@@ -371,51 +404,45 @@ KeWaitForMultipleObjects(ULONG Count,
     ULONG WaitIndex;
     NTSTATUS Status;
     NTSTATUS WaitStatus;
     ULONG WaitIndex;
     NTSTATUS Status;
     NTSTATUS WaitStatus;
-
     DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
     DPRINT("Entering KeWaitForMultipleObjects(Count %lu Object[] %p) "
-            "PsGetCurrentThread() %x, Timeout %x\n", Count, Object, PsGetCurrentThread(), Timeout);
+           "PsGetCurrentThread() %x, Timeout %x\n",
+           Count, Object, PsGetCurrentThread(), Timeout);
 
     /* Set the Current Thread */
     CurrentThread = KeGetCurrentThread();
 
     /* Check if the lock is already held */
 
     /* Set the Current Thread */
     CurrentThread = KeGetCurrentThread();
 
     /* Check if the lock is already held */
-    if (CurrentThread->WaitNext)  {
-
+    if (CurrentThread->WaitNext)
+    {
         /* Lock is held, disable Wait Next */
         DPRINT("Lock is held\n");
         CurrentThread->WaitNext = FALSE;
         /* Lock is held, disable Wait Next */
         DPRINT("Lock is held\n");
         CurrentThread->WaitNext = FALSE;
-
-    } else {
-
+    }
+    else
+    {
         /* Lock not held, acquire it */
         DPRINT("Lock is not held, acquiring\n");
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
     }
 
     /* Make sure the Wait Count is valid for the Thread and Maximum Wait Objects */
         /* Lock not held, acquire it */
         DPRINT("Lock is not held, acquiring\n");
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
     }
 
     /* Make sure the Wait Count is valid for the Thread and Maximum Wait Objects */
-    if (!WaitBlockArray) {
-
+    if (!WaitBlockArray)
+    {
         /* Check in regards to the Thread Object Limit */
         /* Check in regards to the Thread Object Limit */
-        if (Count > THREAD_WAIT_OBJECTS) {
-
-            KEBUGCHECK(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
-        }
+        if (Count > THREAD_WAIT_OBJECTS) KEBUGCHECK(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
 
         /* Use the Thread's Wait Block */
         WaitBlockArray = &CurrentThread->WaitBlock[0];
 
         /* Use the Thread's Wait Block */
         WaitBlockArray = &CurrentThread->WaitBlock[0];
-
-    } else {
-
+    }
+    else
+    {
         /* Using our own Block Array. Check in regards to System Object Limit */
         /* Using our own Block Array. Check in regards to System Object Limit */
-        if (Count > MAXIMUM_WAIT_OBJECTS) {
-
-            KEBUGCHECK(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
-        }
+        if (Count > MAXIMUM_WAIT_OBJECTS) KEBUGCHECK(MAXIMUM_WAIT_OBJECTS_EXCEEDED);
     }
 
     /* Start the actual Loop */
     }
 
     /* Start the actual Loop */
-    do {
-
+    do
+    {
         /* Get the current Wait Status */
         WaitStatus = CurrentThread->WaitStatus;
 
         /* Get the current Wait Status */
         WaitStatus = CurrentThread->WaitStatus;
 
@@ -426,47 +453,76 @@ KeWaitForMultipleObjects(ULONG Count,
         AllObjectsSignaled = TRUE;
 
         /* First, we'll try to satisfy the wait directly */
         AllObjectsSignaled = TRUE;
 
         /* First, we'll try to satisfy the wait directly */
-        for (WaitIndex = 0; WaitIndex < Count; WaitIndex++) {
-
+        for (WaitIndex = 0; WaitIndex < Count; WaitIndex++)
+        {
             /* Get the Current Object */
             /* Get the Current Object */
-            CurrentObject = (PDISPATCHER_HEADER)Object[WaitIndex];
-
-            /* Check if the Object is Signaled */
-            if (KiIsObjectSignaled(CurrentObject, CurrentThread)) {
-
-                /* Check what kind of wait this is */
-                if (WaitType == WaitAny) {
-
-                    /* This is a Wait Any, so just unwait this guy and exit */
-                    if (CurrentObject->SignalState != (LONG)MINLONG) {
-
-                        /* It has a normal signal state, so unwait it and return */
-                        KiSatisfyObjectWait(CurrentObject, CurrentThread);
-                        Status = STATUS_WAIT_0 | WaitIndex;
-                        goto DontWait;
-
-                    } else {
-
-                        /* Is this a Mutant? */
-                        if (CurrentObject->Type == MutantObject) {
-
+            CurrentObject = (PKMUTANT)Object[WaitIndex];
+
+            /* Check the type of wait */
+            if (WaitType == WaitAny)
+            {
+                /* Check if the Object is a mutant */
+                if (CurrentObject->Header.Type == MutantObject)
+                {
+                    /* Check if it's signaled */
+                    if ((CurrentObject->Header.SignalState > 0) ||
+                        (CurrentThread == CurrentObject->OwnerThread))
+                    {
+                        /* This is a Wait Any, so just unwait this and exit */
+                        if (CurrentObject->Header.SignalState != (LONG)MINLONG)
+                        {
+                            /* Normal signal state, so unwait it and return */
+                            KiSatisfyMutantWait(CurrentObject, CurrentThread);
+                            Status = STATUS_WAIT_0 | WaitIndex;
+                            goto DontWait;
+                        }
+                        else
+                        {
                             /* According to wasm.ru, we must raise this exception (tested and true) */
                             KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
                             ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
                         }
                     }
                 }
                             /* According to wasm.ru, we must raise this exception (tested and true) */
                             KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
                             ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
                         }
                     }
                 }
-
-            } else {
-
-                /* One of the objects isn't signaled... if this is a WaitAll, we will fail later */
-                AllObjectsSignaled = FALSE;
+                else if (CurrentObject->Header.SignalState > 0)
+                {
+                    /* Another signaled object, unwait and return */
+                    KiSatisfyNonMutantWait(CurrentObject, CurrentThread);
+                    Status = WaitIndex;
+                    goto DontWait;
+                }
+            }
+            else
+            {
+                /* Check if we're dealing with a mutant again */
+                if (CurrentObject->Header.Type == MutantObject)
+                {
+                    /* Check if it has an invalid count */
+                    if ((CurrentThread == CurrentObject->OwnerThread) &&
+                        (CurrentObject->Header.SignalState == MINLONG))
+                    {
+                        /* Raise an exception */
+                        KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
+                        ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
+                    }
+                    else if ((CurrentObject->Header.SignalState <= 0) &&
+                             (CurrentThread != CurrentObject->OwnerThread))
+                    {
+                        /* We don't own it, can't satisfy the wait */
+                        AllObjectsSignaled = FALSE;
+                    }
+                }
+                else if (CurrentObject->Header.SignalState <= 0)
+                {
+                    /* Not signaled, can't satisfy */
+                    AllObjectsSignaled = FALSE;
+                }
             }
 
             /* Set up a Wait Block for this Object */
             WaitBlock->Object = CurrentObject;
             WaitBlock->Thread = CurrentThread;
             }
 
             /* Set up a Wait Block for this Object */
             WaitBlock->Object = CurrentObject;
             WaitBlock->Thread = CurrentThread;
-            WaitBlock->WaitKey = (USHORT)(STATUS_WAIT_0 + WaitIndex);
+            WaitBlock->WaitKey = (USHORT)WaitIndex;
             WaitBlock->WaitType = (USHORT)WaitType;
             WaitBlock->NextWaitBlock = WaitBlock + 1;
 
             WaitBlock->WaitType = (USHORT)WaitType;
             WaitBlock->NextWaitBlock = WaitBlock + 1;
 
@@ -479,8 +535,8 @@ KeWaitForMultipleObjects(ULONG Count,
         WaitBlock->NextWaitBlock = WaitBlockArray;
 
         /* Check if this is a Wait All and all the objects are signaled */
         WaitBlock->NextWaitBlock = WaitBlockArray;
 
         /* Check if this is a Wait All and all the objects are signaled */
-        if ((WaitType == WaitAll) && (AllObjectsSignaled)) {
-
+        if ((WaitType == WaitAll) && (AllObjectsSignaled))
+        {
             /* Return to the Root Wait Block */
             WaitBlock = CurrentThread->WaitBlockList;
 
             /* Return to the Root Wait Block */
             WaitBlock = CurrentThread->WaitBlockList;
 
@@ -491,18 +547,17 @@ KeWaitForMultipleObjects(ULONG Count,
         }
 
         /* Make sure we can satisfy the Alertable request */
         }
 
         /* Make sure we can satisfy the Alertable request */
-        if (KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status))
-            break;
+        if (KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status)) break;
 
         /* Set the Wait Status */
         CurrentThread->WaitStatus = Status;
 
         /* Enable the Timeout Timer if there was any specified */
 
         /* Set the Wait Status */
         CurrentThread->WaitStatus = Status;
 
         /* Enable the Timeout Timer if there was any specified */
-        if (Timeout != NULL) {
-
-            /* However if 0 timeout was specified, then we must fail since we need to peform a wait */
-            if (!Timeout->QuadPart) {
-
+        if (Timeout)
+        {
+            /* Make sure the timeout interval isn't actually 0 */
+            if (!Timeout->QuadPart)
+            {
                 /* Return a timeout */
                 Status = STATUS_TIMEOUT;
                 goto DontWait;
                 /* Return a timeout */
                 Status = STATUS_TIMEOUT;
                 goto DontWait;
@@ -526,9 +581,9 @@ KeWaitForMultipleObjects(ULONG Count,
             InitializeListHead(&ThreadTimer->Header.WaitListHead);
 
             /* Insert the Timer into the Timer Lists and enable it */
             InitializeListHead(&ThreadTimer->Header.WaitListHead);
 
             /* Insert the Timer into the Timer Lists and enable it */
-            if (!KiInsertTimer(ThreadTimer, *Timeout)) {
-
-                /* Return a timeout if we couldn't insert the timer for some reason */
+            if (!KiInsertTimer(ThreadTimer, *Timeout))
+            {
+                /* Return a timeout if we couldn't insert the timer */
                 Status = STATUS_TIMEOUT;
                 goto DontWait;
             }
                 Status = STATUS_TIMEOUT;
                 goto DontWait;
             }
@@ -536,28 +591,30 @@ KeWaitForMultipleObjects(ULONG Count,
 
         /* Insert into Object's Wait List*/
         WaitBlock = CurrentThread->WaitBlockList;
 
         /* Insert into Object's Wait List*/
         WaitBlock = CurrentThread->WaitBlockList;
-        do {
-
+        do
+        {
             /* Get the Current Object */
             CurrentObject = WaitBlock->Object;
 
             /* Link the Object to this Wait Block */
             /* Get the Current Object */
             CurrentObject = WaitBlock->Object;
 
             /* Link the Object to this Wait Block */
-            InsertTailList(&CurrentObject->WaitListHead, &WaitBlock->WaitListEntry);
+            InsertTailList(&CurrentObject->Header.WaitListHead,
+                           &WaitBlock->WaitListEntry);
 
             /* Move to the next Wait Block */
             WaitBlock = WaitBlock->NextWaitBlock;
 
             /* Move to the next Wait Block */
             WaitBlock = WaitBlock->NextWaitBlock;
-        } while (WaitBlock != WaitBlockArray);
+        }
+        while (WaitBlock != WaitBlockArray);
 
         /* Handle Kernel Queues */
 
         /* Handle Kernel Queues */
-        if (CurrentThread->Queue) {
-
+        if (CurrentThread->Queue)
+        {
             DPRINT("Waking Queue\n");
             KiWakeQueue(CurrentThread->Queue);
         }
 
         /* Block the Thread */
             DPRINT("Waking Queue\n");
             KiWakeQueue(CurrentThread->Queue);
         }
 
         /* Block the Thread */
-        DPRINT("Blocking the Thread: %d, %d, %d, %x\n", Alertable, WaitMode, 
-                WaitReason, KeGetCurrentThread());
+        DPRINT("Blocking the Thread: %d, %d, %d, %x\n",
+                Alertable, WaitMode, WaitReason, KeGetCurrentThread());
         KiBlockThread(&Status,
                       Alertable,
                       WaitMode,
         KiBlockThread(&Status,
                       Alertable,
                       WaitMode,
@@ -565,16 +622,17 @@ KeWaitForMultipleObjects(ULONG Count,
 
         /* Check if we were executing an APC */
         DPRINT("Thread is back\n");
 
         /* Check if we were executing an APC */
         DPRINT("Thread is back\n");
-        if (Status != STATUS_KERNEL_APC) {
-
+        if (Status != STATUS_KERNEL_APC)
+        {
             /* Return Status */
             return Status;
         }
 
             /* Return Status */
             return Status;
         }
 
-        DPRINT("Looping Again\n");
+        /* Loop again and re-acquire the dispatcher lock */
+        DPRINT("Looping Again\n"); // FIXME: Fix-up the interval */
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
         CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock();
-
-    while (TRUE);
+    }
+    while (TRUE);
 
     /* Release the Lock, we are done */
     DPRINT("Returning, %x. Status: %d\n",  KeGetCurrentThread(), Status);
 
     /* Release the Lock, we are done */
     DPRINT("Returning, %x. Status: %d\n",  KeGetCurrentThread(), Status);
@@ -586,7 +644,7 @@ DontWait:
     KiAdjustQuantumThread(CurrentThread);
 
     /* Release & Return */
     KiAdjustQuantumThread(CurrentThread);
 
     /* Release & Return */
-    DPRINT("Returning, %x. Status: %d\n. We did not wait.", 
+    DPRINT("Returning, %x. Status: %d\n. We did not wait.",
             KeGetCurrentThread(), Status);
     KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
     return Status;
             KeGetCurrentThread(), Status);
     KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql);
     return Status;
@@ -594,54 +652,7 @@ DontWait:
 
 VOID
 FASTCALL
 
 VOID
 FASTCALL
-KiSatisfyObjectWait(PDISPATCHER_HEADER Object,
-                    PKTHREAD Thread)
-
-{
-    /* Special case for Mutants */
-    if (Object->Type == MutantObject) {
-
-        /* Decrease the Signal State */
-        Object->SignalState--;
-
-        /* Check if it's now non-signaled */
-        if (Object->SignalState == 0) {
-
-            /* Set the Owner Thread */
-            ((PKMUTANT)Object)->OwnerThread = Thread;
-
-            /* Disable APCs if needed */
-            Thread->KernelApcDisable -= ((PKMUTANT)Object)->ApcDisable;
-
-            /* Check if it's abandoned */
-            if (((PKMUTANT)Object)->Abandoned) {
-
-                /* Unabandon it */
-                ((PKMUTANT)Object)->Abandoned = FALSE;
-
-                /* Return Status */
-                Thread->WaitStatus = STATUS_ABANDONED;
-            }
-
-            /* Insert it into the Mutant List */
-            InsertHeadList(&Thread->MutantListHead, &((PKMUTANT)Object)->MutantListEntry);
-        }
-
-    } else if ((Object->Type & TIMER_OR_EVENT_TYPE) == EventSynchronizationObject) {
-
-        /* These guys (Syncronization Timers and Events) just get un-signaled */
-        Object->SignalState = 0;
-
-    } else if (Object->Type == SemaphoreObject) {
-
-        /* These ones can have multiple signalings, so we only decrease it */
-        Object->SignalState--;
-    }
-}
-
-VOID
-FASTCALL
-KiWaitTest(PDISPATCHER_HEADER Object,
+KiWaitTest(PVOID ObjectPointer,
            KPRIORITY Increment)
 {
     PLIST_ENTRY WaitEntry;
            KPRIORITY Increment)
 {
     PLIST_ENTRY WaitEntry;
@@ -649,41 +660,55 @@ KiWaitTest(PDISPATCHER_HEADER Object,
     PKWAIT_BLOCK CurrentWaitBlock;
     PKWAIT_BLOCK NextWaitBlock;
     PKTHREAD WaitThread;
     PKWAIT_BLOCK CurrentWaitBlock;
     PKWAIT_BLOCK NextWaitBlock;
     PKTHREAD WaitThread;
+    PKMUTANT FirstObject = ObjectPointer, Object;
 
     /* Loop the Wait Entries */
 
     /* Loop the Wait Entries */
-    DPRINT("KiWaitTest for Object: %x\n", Object);
-    WaitList = &Object->WaitListHead;
+    DPRINT("KiWaitTest for Object: %x\n", FirstObject);
+    WaitList = &FirstObject->Header.WaitListHead;
     WaitEntry = WaitList->Flink;
     WaitEntry = WaitList->Flink;
-    while ((WaitEntry != WaitList) && (Object->SignalState > 0)) {
-
+    while ((FirstObject->Header.SignalState > 0) && (WaitEntry != WaitList))
+    {
         /* Get the current wait block */
         /* Get the current wait block */
-        CurrentWaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
+        CurrentWaitBlock = CONTAINING_RECORD(WaitEntry,
+                                             KWAIT_BLOCK,
+                                             WaitListEntry);
         WaitThread = CurrentWaitBlock->Thread;
 
         /* Check the current Wait Mode */
         WaitThread = CurrentWaitBlock->Thread;
 
         /* Check the current Wait Mode */
-        if (CurrentWaitBlock->WaitType == WaitAny) {
-
+        if (CurrentWaitBlock->WaitType == WaitAny)
+        {
             /* Easy case, satisfy only this wait */
             DPRINT("Satisfiying a Wait any\n");
             WaitEntry = WaitEntry->Blink;
             /* Easy case, satisfy only this wait */
             DPRINT("Satisfiying a Wait any\n");
             WaitEntry = WaitEntry->Blink;
-            KiSatisfyObjectWait(Object, WaitThread);
-
-        } else {
-
+            KiSatisfyObjectWait(FirstObject, WaitThread);
+        }
+        else
+        {
             /* Everything must be satisfied */
             DPRINT("Checking for a Wait All\n");
             NextWaitBlock = CurrentWaitBlock->NextWaitBlock;
 
             /* Loop first to make sure they are valid */
             /* Everything must be satisfied */
             DPRINT("Checking for a Wait All\n");
             NextWaitBlock = CurrentWaitBlock->NextWaitBlock;
 
             /* Loop first to make sure they are valid */
-            while (NextWaitBlock != CurrentWaitBlock) {
-
+            while (NextWaitBlock != CurrentWaitBlock)
+            {
                 /* Check if the object is signaled */
                 /* Check if the object is signaled */
-                DPRINT("Checking: %x %d\n", NextWaitBlock->Object, Object->SignalState);
-                if (!KiIsObjectSignaled(NextWaitBlock->Object, WaitThread)) {
-
-                    /* It's not, move to the next one */
-                    DPRINT("One of the object is non-signaled, sorry.\n");
-                    goto SkipUnwait;
+                Object = NextWaitBlock->Object;
+                DPRINT("Checking: %p %d\n",
+                        Object, Object->Header.SignalState);
+                if (NextWaitBlock->WaitKey != STATUS_TIMEOUT)
+                {
+                    /* Check if this is a mutant */
+                    if ((Object->Header.Type == MutantObject) &&
+                        (Object->Header.SignalState <= 0) &&
+                        (WaitThread == Object->OwnerThread))
+                    {
+                        /* It's a signaled mutant */
+                    }
+                    else if (Object->Header.SignalState <= 0)
+                    {
+                        /* Skip the unwaiting */
+                        goto SkipUnwait;
+                    }
                 }
 
                 /* Go to the next Wait block */
                 }
 
                 /* Go to the next Wait block */
@@ -718,16 +743,17 @@ KiAbortWaitThread(PKTHREAD Thread,
     PKWAIT_BLOCK WaitBlock;
 
     /* If we are blocked, we must be waiting on something also */
     PKWAIT_BLOCK WaitBlock;
 
     /* If we are blocked, we must be waiting on something also */
-    DPRINT("KiAbortWaitThread: %x, Status: %x, %x \n", Thread, WaitStatus, Thread->WaitBlockList);
-    ASSERT((Thread->State == Waiting) == (Thread->WaitBlockList != NULL));
+    DPRINT("KiAbortWaitThread: %x, Status: %x, %x \n",
+            Thread, WaitStatus, Thread->WaitBlockList);
 
     /* Remove the Wait Blocks from the list */
     DPRINT("Removing waits\n");
     WaitBlock = Thread->WaitBlockList;
 
     /* Remove the Wait Blocks from the list */
     DPRINT("Removing waits\n");
     WaitBlock = Thread->WaitBlockList;
-    do {
-
+    do
+    {
         /* Remove it */
         /* Remove it */
-        DPRINT("Removing Waitblock: %x, %x\n", WaitBlock, WaitBlock->NextWaitBlock);
+        DPRINT("Removing Waitblock: %x, %x\n",
+                WaitBlock, WaitBlock->NextWaitBlock);
         RemoveEntryList(&WaitBlock->WaitListEntry);
 
         /* Go to the next one */
         RemoveEntryList(&WaitBlock->WaitListEntry);
 
         /* Go to the next one */
@@ -735,8 +761,8 @@ KiAbortWaitThread(PKTHREAD Thread,
     } while (WaitBlock != Thread->WaitBlockList);
 
     /* Check if there's a Thread Timer */
     } while (WaitBlock != Thread->WaitBlockList);
 
     /* Check if there's a Thread Timer */
-    if (Thread->Timer.Header.Inserted) {
-
+    if (Thread->Timer.Header.Inserted)
+    {
         /* Cancel the Thread Timer with the no-lock fastpath */
         DPRINT("Removing the Thread's Timer\n");
         Thread->Timer.Header.Inserted = FALSE;
         /* Cancel the Thread Timer with the no-lock fastpath */
         DPRINT("Removing the Thread's Timer\n");
         Thread->Timer.Header.Inserted = FALSE;
@@ -744,8 +770,8 @@ KiAbortWaitThread(PKTHREAD Thread,
     }
 
     /* Increment the Queue's active threads */
     }
 
     /* Increment the Queue's active threads */
-    if (Thread->Queue) {
-
+    if (Thread->Queue)
+    {
         DPRINT("Incrementing Queue's active threads\n");
         Thread->Queue->CurrentCount++;
     }
         DPRINT("Incrementing Queue's active threads\n");
         Thread->Queue->CurrentCount++;
     }
@@ -770,123 +796,28 @@ KiAcquireFastMutex(IN PFAST_MUTEX FastMutex)
                           NULL);
 }
 
                           NULL);
 }
 
-BOOLEAN
-__inline
-FASTCALL
-KiIsObjectSignaled(PDISPATCHER_HEADER Object,
-                   PKTHREAD Thread)
-{
-    /* Mutants are...well...mutants! */
-   if (Object->Type == MutantObject) {
-
-        /*
-         * Because Cutler hates mutants, they are actually signaled if the Signal State is <= 0
-         * Well, only if they are recursivly acquired (i.e if we own it right now).
-         * Of course, they are also signaled if their signal state is 1.
-         */
-        if ((Object->SignalState <= 0 && ((PKMUTANT)Object)->OwnerThread == Thread) ||
-            (Object->SignalState == 1)) {
-
-            /* Signaled Mutant */
-            return (TRUE);
-
-        } else {
-
-            /* Unsignaled Mutant */
-            return (FALSE);
-        }
-    }
-
-    /* Any other object is not a mutated freak, so let's use logic */
-   return (!Object->SignalState <= 0);
-}
-
-VOID
-__inline
-FASTCALL
-KiSatisifyMultipleObjectWaits(PKWAIT_BLOCK WaitBlock)
-{
-    PKWAIT_BLOCK FirstBlock = WaitBlock;
-    PKTHREAD WaitThread = WaitBlock->Thread;
-
-    /* Loop through all the Wait Blocks, and wake each Object */
-    do {
-
-        /* Wake the Object */
-        KiSatisfyObjectWait(WaitBlock->Object, WaitThread);
-        WaitBlock = WaitBlock->NextWaitBlock;
-    } while (WaitBlock != FirstBlock);
-}
-
-VOID
-__inline
-FASTCALL
-KeInitializeDispatcherHeader(DISPATCHER_HEADER* Header,
-                             ULONG Type,
-                             ULONG Size,
-                             ULONG SignalState)
-{
-    Header->Type = (UCHAR)Type;
-    Header->Absolute = 0;
-    Header->Inserted = 0;
-    Header->Size = (UCHAR)Size;
-    Header->SignalState = SignalState;
-    InitializeListHead(&(Header->WaitListHead));
-}
-
-KIRQL
-__inline
-FASTCALL
-KeAcquireDispatcherDatabaseLock(VOID)
-{
-    KIRQL OldIrql;
-
-    KeAcquireSpinLock (&DispatcherDatabaseLock, &OldIrql);
-    return OldIrql;
-}
-
-VOID
-__inline
-FASTCALL
-KeAcquireDispatcherDatabaseLockAtDpcLevel(VOID)
-{
-    KeAcquireSpinLockAtDpcLevel (&DispatcherDatabaseLock);
-}
-
-VOID
-__inline
-FASTCALL
-KeInitializeDispatcher(VOID)
-{
-    /* Initialize the Dispatcher Lock */
-    KeInitializeSpinLock(&DispatcherDatabaseLock);
-}
-
 VOID
 VOID
-__inline
 FASTCALL
 KeReleaseDispatcherDatabaseLock(KIRQL OldIrql)
 {
     /* If it's the idle thread, dispatch */
 FASTCALL
 KeReleaseDispatcherDatabaseLock(KIRQL OldIrql)
 {
     /* If it's the idle thread, dispatch */
-    if (!KeIsExecutingDpc() && OldIrql < DISPATCH_LEVEL && KeGetCurrentThread() != NULL &&
-        KeGetCurrentThread() == KeGetCurrentPrcb()->IdleThread) {
-
+    if (!(KeIsExecutingDpc()) &&
+        (OldIrql < DISPATCH_LEVEL) &&
+        (KeGetCurrentThread()) &&
+        (KeGetCurrentThread() == KeGetCurrentPrcb()->IdleThread))
+    {
         KiDispatchThreadNoLock(Ready);
         KeLowerIrql(OldIrql);
         KiDispatchThreadNoLock(Ready);
         KeLowerIrql(OldIrql);
-
-    } else {
-
+    }
+    else
+    {
         /* Just release the spin lock */
         /* Just release the spin lock */
+#ifdef CONFIG_SMP
         KeReleaseSpinLock(&DispatcherDatabaseLock, OldIrql);
         KeReleaseSpinLock(&DispatcherDatabaseLock, OldIrql);
+#else
+        KeLowerIrql(OldIrql);
+#endif
     }
 }
 
     }
 }
 
-VOID
-__inline
-FASTCALL
-KeReleaseDispatcherDatabaseLockFromDpcLevel(VOID)
-{
-    KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock);
-}
-
 /* EOF */
 /* EOF */
index aab0932..c874526 100644 (file)
@@ -84,7 +84,6 @@ ExAllocateCacheAwareRundownProtection@8
 ExFreeCacheAwareRundownProtection@4
 ExInitializeRundownProtectionCacheAware@8
 ExSizeOfRundownProtectionCacheAware@0
 ExFreeCacheAwareRundownProtection@4
 ExInitializeRundownProtectionCacheAware@8
 ExSizeOfRundownProtectionCacheAware@0
-ExAcquireResourceExclusive@8
 ExAcquireResourceExclusiveLite@8
 ExAcquireResourceSharedLite@8
 ExAcquireSharedStarveExclusive@8
 ExAcquireResourceExclusiveLite@8
 ExAcquireResourceSharedLite@8
 ExAcquireSharedStarveExclusive@8
@@ -99,7 +98,6 @@ ExConvertExclusiveToSharedLite@4
 ExCreateCallback@16
 ExDeleteNPagedLookasideList@4
 ExDeletePagedLookasideList@4
 ExCreateCallback@16
 ExDeleteNPagedLookasideList@4
 ExDeletePagedLookasideList@4
-ExDeleteResource@4
 ExDeleteResourceLite@4
 ExDesktopObjectType DATA
 ExDisableResourceBoostLite@4
 ExDeleteResourceLite@4
 ExDesktopObjectType DATA
 ExDisableResourceBoostLite@4
@@ -117,7 +115,6 @@ ExGetPreviousMode@0
 ExGetSharedWaiterCount@4
 ExInitializeNPagedLookasideList@28
 ExInitializePagedLookasideList@28
 ExGetSharedWaiterCount@4
 ExInitializeNPagedLookasideList@28
 ExInitializePagedLookasideList@28
-ExInitializeResource@4
 ExInitializeResourceLite@4
 ExInitializeZone@16
 ExInterlockedAddLargeInteger@16
 ExInitializeResourceLite@4
 ExInitializeZone@16
 ExInterlockedAddLargeInteger@16
@@ -153,7 +150,6 @@ ExReinitializeResourceLite@4
 @ExiReleaseFastMutex@4=@ExReleaseFastMutex@4
 @ExReleaseFastMutexUnsafe@4
 @ExReleaseFastMutexUnsafeAndLeaveCriticalRegion@4
 @ExiReleaseFastMutex@4=@ExReleaseFastMutex@4
 @ExReleaseFastMutexUnsafe@4
 @ExReleaseFastMutexUnsafeAndLeaveCriticalRegion@4
-ExReleaseResourceForThread@8
 ExReleaseResourceForThreadLite@8
 @ExReleaseResourceLite@4
 ExSemaphoreObjectType DATA
 ExReleaseResourceForThreadLite@8
 @ExReleaseResourceLite@4
 ExSemaphoreObjectType DATA
@@ -522,7 +518,6 @@ Ke386SetIoAccessMap@8
 @KeAcquireGuardedMutex@4
 @KeAcquireGuardedMutexUnsafe@4
 KeAcquireSpinLockAtDpcLevel@4
 @KeAcquireGuardedMutex@4
 @KeAcquireGuardedMutexUnsafe@4
 KeAcquireSpinLockAtDpcLevel@4
-@KeAcquireDispatcherDatabaseLockAtDpcLevel@0
 @KeAcquireInStackQueuedSpinLockAtDpcLevel@8
 KeAcquireInterruptSpinLock@4
 KeAddSystemServiceTable@20
 @KeAcquireInStackQueuedSpinLockAtDpcLevel@8
 KeAcquireInterruptSpinLock@4
 KeAddSystemServiceTable@20
@@ -606,7 +601,6 @@ KeReadStateSemaphore@4
 KeReadStateTimer@4
 KeRegisterBugCheckCallback@20
 KeRegisterBugCheckReasonCallback@16
 KeReadStateTimer@4
 KeRegisterBugCheckCallback@20
 KeRegisterBugCheckReasonCallback@16
-@KeReleaseDispatcherDatabaseLockFromDpcLevel@0
 @KeReleaseGuardedMutexUnsafe@4
 @KeReleaseGuardedMutex@4
 @KeReleaseInStackQueuedSpinLockFromDpcLevel@4
 @KeReleaseGuardedMutexUnsafe@4
 @KeReleaseGuardedMutex@4
 @KeReleaseInStackQueuedSpinLockFromDpcLevel@4
index 5f75325..290225a 100644 (file)
@@ -204,7 +204,7 @@ PsInitProcessManagment(VOID)
    InitializeListHead(&PsIdleProcess->ActiveProcessLinks);
    KeInitializeDispatcherHeader(&PsIdleProcess->Pcb.Header,
                                ProcessObject,
    InitializeListHead(&PsIdleProcess->ActiveProcessLinks);
    KeInitializeDispatcherHeader(&PsIdleProcess->Pcb.Header,
                                ProcessObject,
-                               sizeof(EPROCESS),
+                               sizeof(EPROCESS) / sizeof(LONG),
                                FALSE);
    PsIdleProcess->Pcb.DirectoryTableBase.QuadPart = (ULONG_PTR)MmGetPageDirectory();
    strcpy(PsIdleProcess->ImageFileName, "Idle");
                                FALSE);
    PsIdleProcess->Pcb.DirectoryTableBase.QuadPart = (ULONG_PTR)MmGetPageDirectory();
    strcpy(PsIdleProcess->ImageFileName, "Idle");
@@ -246,7 +246,7 @@ PsInitProcessManagment(VOID)
    InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
    KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.Header,
                                ProcessObject,
    InitializeListHead(&PsInitialSystemProcess->Pcb.ThreadListHead);
    KeInitializeDispatcherHeader(&PsInitialSystemProcess->Pcb.Header,
                                ProcessObject,
-                               sizeof(EPROCESS),
+                               sizeof(EPROCESS) / sizeof(LONG),
                                FALSE);
    KProcess = &PsInitialSystemProcess->Pcb;
    PspInheritQuota(PsInitialSystemProcess, NULL);
                                FALSE);
    KProcess = &PsInitialSystemProcess->Pcb;
    PspInheritQuota(PsInitialSystemProcess, NULL);