- KeRundownThread:
 - Optimize to reduce contention
 - Add bugcheck instead of ASSERT
 - Add debug message to simplify finding errors like Bug 821 (type/size show 0xCC, which means the mutant has been already freed).
Modified: trunk/reactos/ntoskrnl/ke/kthread.c

Modified: trunk/reactos/ntoskrnl/ke/kthread.c
--- trunk/reactos/ntoskrnl/ke/kthread.c	2005-10-01 00:36:17 UTC (rev 18182)
+++ trunk/reactos/ntoskrnl/ke/kthread.c	2005-10-01 07:37:13 UTC (rev 18183)
@@ -456,22 +456,40 @@
 {
     KIRQL OldIrql;
     PKTHREAD Thread = KeGetCurrentThread();
-    PLIST_ENTRY CurrentEntry;
+    PLIST_ENTRY NextEntry, ListHead;
     PKMUTANT Mutant;
-
     DPRINT("KeRundownThread: %x\n", Thread);
 
+    /* Optimized path if nothing is on the list at the moment */
+    if (IsListEmpty(&Thread->MutantListHead)) return;
+
     /* Lock the Dispatcher Database */
     OldIrql = KeAcquireDispatcherDatabaseLock();
 
-    while (!IsListEmpty(&Thread->MutantListHead)) {
-
+    /* Get the List Pointers */
+    ListHead = &Thread->MutantListHead;
+    NextEntry = ListHead->Flink;
+    while (NextEntry != ListHead)
+    {
         /* Get the Mutant */
-        CurrentEntry = RemoveHeadList(&Thread->MutantListHead);
-        Mutant = CONTAINING_RECORD(CurrentEntry, KMUTANT, MutantListEntry);
-        ASSERT(Mutant->ApcDisable == 0);
+        Mutant = CONTAINING_RECORD(NextEntry, KMUTANT, MutantListEntry);
+        DPRINT1("Mutant: %p. Type, Size %x %x\n", Mutant, Mutant->Header.Type, Mutant->Header.Size);
 
-        /* Uncondtionally abandon it */
+        /* Make sure it's not terminating with APCs off */
+        if (Mutant->ApcDisable)
+        {
+            /* Bugcheck the system */
+            KEBUGCHECKEX(0,//THREAD_TERMINATE_HELD_MUTEX,
+                         (ULONG_PTR)Thread,
+                         (ULONG_PTR)Mutant,
+                         0,
+                         0);
+        }
+
+        /* Now we can remove it */
+        RemoveEntryList(&Mutant->MutantListEntry);
+
+        /* Unconditionally abandon it */
         DPRINT("Abandonning the Mutant\n");
         Mutant->Header.SignalState = 1;
         Mutant->Abandoned = TRUE;
@@ -479,12 +497,15 @@
 
         /* Check if the Wait List isn't empty */
         DPRINT("Checking whether to wake the Mutant\n");
-        if (!IsListEmpty(&Mutant->Header.WaitListHead)) {
-
+        if (!IsListEmpty(&Mutant->Header.WaitListHead))
+        {
             /* Wake the Mutant */
             DPRINT("Waking the Mutant\n");
             KiWaitTest(&Mutant->Header, MUTANT_INCREMENT);
         }
+
+        /* Move on */
+        NextEntry = NextEntry->Flink;
     }
 
     /* Release the Lock */