Commit in reactos/ntoskrnl/ke on MAIN
apc.c+32-151.69 -> 1.70
critical.c+9-21.10 -> 1.11
event.c+11-31.22 -> 1.23
mutex.c+3-31.18 -> 1.19
queue.c+109-521.11 -> 1.12
sem.c+2-21.15 -> 1.16
timer.c+4-41.89 -> 1.90
wait.c+51-541.61 -> 1.62
+221-135
8 modified files
fix kernel queues + misc fixes/cleanups

reactos/ntoskrnl/ke
apc.c 1.69 -> 1.70
diff -u -r1.69 -r1.70
--- apc.c	21 Nov 2004 06:51:18 -0000	1.69
+++ apc.c	21 Nov 2004 18:33:54 -0000	1.70
@@ -124,7 +124,7 @@
 	PLIST_ENTRY ApcListEntry;
 	PKAPC QueuedApc;
    
-	ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+   ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
 	DPRINT ("KeInsertQueueApc(Apc %x, SystemArgument1 %x, "
 		"SystemArgument2 %x)\n",Apc,SystemArgument1,
 		SystemArgument2);
@@ -134,7 +134,9 @@
 	/* Get the Thread specified in the APC */
 	Thread = Apc->Thread;
 	   
-	/* Make sure the thread allows APC Queues */
+	/* Make sure the thread allows APC Queues.
+    * The thread is not apc queueable, for instance, when it's (about to be) terminated.
+    */
 	if (Thread->ApcQueueable == FALSE) {
 		DPRINT("Thread doesn't allow APC Queues\n");
 		KeReleaseDispatcherDatabaseLock(OldIrql);
@@ -194,18 +196,20 @@
 			/* FIXME: Use IPI */
 			DPRINT ("Requesting APC Interrupt for Running Thread \n");
 			HalRequestSoftwareInterrupt(APC_LEVEL);
-		} else if ((Thread->WaitIrql < APC_LEVEL) && (Apc->NormalRoutine == NULL)) {
+      } else if ((Thread->State == THREAD_STATE_BLOCKED) && 
+                 (Thread->WaitIrql < APC_LEVEL) && 
+                 (Apc->NormalRoutine == NULL)) 
+      {
 			DPRINT ("Waking up Thread for Kernel-Mode APC Delivery \n");
-			KeRemoveAllWaitsThread(CONTAINING_RECORD(Thread, ETHREAD, Tcb),
-					       STATUS_KERNEL_APC,
-					       TRUE);
+			KiAbortWaitThread(Thread, STATUS_KERNEL_APC);
 		}
-	} else if ((Thread->WaitMode == UserMode) && (Thread->Alertable)) {
+   } else if ((Thread->State == THREAD_STATE_BLOCKED) && 
+              (Thread->WaitMode == UserMode) && 
+              (Thread->Alertable)) 
+   {
 		DPRINT ("Waking up Thread for User-Mode APC Delivery \n");
 		Thread->ApcState.UserApcPending = TRUE;
-		KeRemoveAllWaitsThread(CONTAINING_RECORD(Thread, ETHREAD, Tcb),
-				       STATUS_USER_APC,
-				       TRUE);
+      KiAbortWaitThread(Thread, STATUS_USER_APC);
 	}
 
 	/* Return Sucess if we are here */
@@ -227,7 +231,7 @@
 	KIRQL OldIrql;
 	PKTHREAD Thread = Apc->Thread;
 
-	ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+   ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
 	DPRINT("KeRemoveQueueApc called for APC: %x \n", Apc);
 	
 	OldIrql = KeAcquireDispatcherDatabaseLock();
@@ -270,7 +274,7 @@
 	PKTHREAD Thread = KeGetCurrentThread();
 	BOOLEAN OldState;
    
-	ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+   ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
 	
 	OldIrql = KeAcquireDispatcherDatabaseLock();
 	KiAcquireSpinLock(&Thread->ApcQueueLock);
@@ -295,7 +299,7 @@
  */
 VOID 
 STDCALL
-KiDeliverApc(KPROCESSOR_MODE PreviousMode,
+KiDeliverApc(KPROCESSOR_MODE DeliveryMode,
              PVOID Reserved,
              PKTRAP_FRAME TrapFrame)
 /*
@@ -317,6 +321,8 @@
 	PKNORMAL_ROUTINE NormalRoutine;
 	PVOID SystemArgument1;
 	PVOID SystemArgument2;
+   
+   ASSERT_IRQL_EQUAL(APC_LEVEL);
 
 	/* Lock the APC Queue and Raise IRQL to Synch */
 	KeAcquireSpinLock(&Thread->ApcQueueLock, &OldIrql);
@@ -339,7 +345,7 @@
 		SystemArgument2 = Apc->SystemArgument2;
        
 		/* Special APC */
-		if (NormalRoutine == NULL) {
+   	if (NormalRoutine == NULL) {
 			/* Remove the APC from the list */
 			Apc->Inserted = FALSE;
 			RemoveEntryList(ApcListEntry);
@@ -360,6 +366,15 @@
 		} else {
 			 /* Normal Kernel APC */
 			if (Thread->ApcState.KernelApcInProgress || Thread->KernelApcDisable) {
+            
+            /*
+             * DeliveryMode must be KernelMode in this case, since one may not
+             * return to umode while being inside a critical section or while 
+             * a regular kmode apc is running (the latter should be impossible btw).
+             * -Gunnar
+             */
+            ASSERT(DeliveryMode == KernelMode);
+
 				KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
 				return;
 			}
@@ -399,7 +414,7 @@
 	
 	/* Now we do the User APCs */
 	if ((!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])) &&
-			 (PreviousMode == UserMode) &&
+          (DeliveryMode == UserMode) &&
 			 (Thread->ApcState.UserApcPending == TRUE)) {
 			 
 		/* It's not pending anymore */
@@ -418,6 +433,8 @@
 		
 		/* Remove the APC from Queue, restore IRQL and call the APC */
 		RemoveEntryList(ApcListEntry);
+      Apc->Inserted = FALSE;
+      
 		KeReleaseSpinLock(&Thread->ApcQueueLock, OldIrql);
 		DPRINT("Calling the Kernel Routine for for a User APC: %x\n", Apc);
 		KernelRoutine(Apc,

reactos/ntoskrnl/ke
critical.c 1.10 -> 1.11
diff -u -r1.10 -r1.11
--- critical.c	15 Aug 2004 16:39:05 -0000	1.10
+++ critical.c	21 Nov 2004 18:33:54 -0000	1.11
@@ -1,4 +1,4 @@
-/* $Id: critical.c,v 1.10 2004/08/15 16:39:05 chorns Exp $
+/* $Id: critical.c,v 1.11 2004/11/21 18:33:54 gdalsnes Exp $
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -22,8 +22,13 @@
  */
 VOID STDCALL KeEnterCriticalRegion (VOID)
 {
+   PKTHREAD Thread = KeGetCurrentThread(); 
+   
    DPRINT("KeEnterCriticalRegion()\n");
-   KeGetCurrentThread()->KernelApcDisable--;
+   
+   if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
+
+   Thread->KernelApcDisable--;
 }
 
 /*
@@ -34,6 +39,8 @@
   PKTHREAD Thread = KeGetCurrentThread(); 
 
   DPRINT("KeLeaveCriticalRegion()\n");
+  
+  if (!Thread) return; /* <-Early in the boot process the current thread is obseved to be NULL */
 
   /* Reference: http://www.ntfsd.org/archive/ntfsd0104/msg0203.html */
   if(++Thread->KernelApcDisable == 0) 

reactos/ntoskrnl/ke
event.c 1.22 -> 1.23
diff -u -r1.22 -r1.23
--- event.c	22 Oct 2004 20:30:47 -0000	1.22
+++ event.c	21 Nov 2004 18:33:54 -0000	1.23
@@ -67,6 +67,9 @@
  */
 LONG STDCALL KeResetEvent (PKEVENT Event)
 {
+  /* FIXME: must use interlocked func. everywhere! (wait.c)
+   * or use dispather lock instead
+   * -Gunnar */
    return(InterlockedExchange(&(Event->Header.SignalState),0));
 }
 
@@ -86,7 +89,7 @@
 
   ret = InterlockedExchange(&(Event->Header.SignalState),1);
 
-  KeDispatcherObjectWake((DISPATCHER_HEADER *)Event);
+  KiDispatcherObjectWake((DISPATCHER_HEADER *)Event);
 
   if (Wait == FALSE)
     {
@@ -115,7 +118,7 @@
    DPRINT("KePulseEvent(Event %x, Wait %x)\n",Event,Wait);
    OldIrql = KeAcquireDispatcherDatabaseLock();
    ret = InterlockedExchange(&(Event->Header.SignalState),1);
-   KeDispatcherObjectWake((DISPATCHER_HEADER *)Event);
+   KiDispatcherObjectWake((DISPATCHER_HEADER *)Event);
    InterlockedExchange(&(Event->Header.SignalState),0);
 
   if (Wait == FALSE)
@@ -143,7 +146,10 @@
 )
 {
 	PKTHREAD WaitingThread;
+   KIRQL OldIrql;
 	
+   OldIrql = KeAcquireDispatcherDatabaseLock();
+   
 	/* Get Thread that is currently waiting. First get the Wait Block, then the Thread */
 	WaitingThread = CONTAINING_RECORD(Event->Header.WaitListHead.Flink, KWAIT_BLOCK, WaitListEntry)->Thread;
 	
@@ -152,7 +158,9 @@
 	
 	/* Reset the Quantum and Unwait the Thread */
 	WaitingThread->Quantum = WaitingThread->ApcState.Process->ThreadQuantum;
-	KeRemoveAllWaitsThread((PETHREAD)WaitingThread, STATUS_SUCCESS, TRUE);
+	KiAbortWaitThread(WaitingThread, STATUS_SUCCESS);
+   
+   KeReleaseDispatcherDatabaseLock(OldIrql);
 }
 
 /* EOF */

reactos/ntoskrnl/ke
mutex.c 1.18 -> 1.19
diff -u -r1.18 -r1.19
--- mutex.c	22 Oct 2004 20:30:48 -0000	1.18
+++ mutex.c	21 Nov 2004 18:33:54 -0000	1.19
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: mutex.c,v 1.18 2004/10/22 20:30:48 ekohl Exp $
+/* $Id: mutex.c,v 1.19 2004/11/21 18:33:54 gdalsnes Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/mutex.c
@@ -82,7 +82,7 @@
       Mutex->OwnerThread = NULL;
       if (Mutex->MutantListEntry.Flink && Mutex->MutantListEntry.Blink)
 	RemoveEntryList(&Mutex->MutantListEntry);
-      KeDispatcherObjectWake(&Mutex->Header);
+      KiDispatcherObjectWake(&Mutex->Header);
     }
 
   if (Wait == FALSE)
@@ -191,7 +191,7 @@
       Mutant->OwnerThread = NULL;
       if (Mutant->MutantListEntry.Flink && Mutant->MutantListEntry.Blink)
 	RemoveEntryList(&Mutant->MutantListEntry);
-      KeDispatcherObjectWake(&Mutant->Header);
+      KiDispatcherObjectWake(&Mutant->Header);
     }
 
   if (Wait == FALSE)

reactos/ntoskrnl/ke
queue.c 1.11 -> 1.12
diff -u -r1.11 -r1.12
--- queue.c	15 Aug 2004 16:39:05 -0000	1.11
+++ queue.c	21 Nov 2004 18:33:54 -0000	1.12
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: queue.c,v 1.11 2004/08/15 16:39:05 chorns Exp $
+/* $Id: queue.c,v 1.12 2004/11/21 18:33:54 gdalsnes Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/queue.c
@@ -34,6 +34,7 @@
 
 /* FUNCTIONS *****************************************************************/
 
+
 /*
  * @implemented
  */
@@ -54,6 +55,8 @@
 
 /*
  * @implemented
+ *
+ * Returns number of entries in the queue
  */
 LONG STDCALL
 KeReadStateQueue(IN PKQUEUE Queue)
@@ -61,7 +64,9 @@
   return(Queue->Header.SignalState);
 }
 
-
+/*
+ * Returns the previous number of entries in the queue
+ */
 LONG STDCALL
 KiInsertQueue(
    IN PKQUEUE Queue,
@@ -70,15 +75,11 @@
    )
 {
    ULONG InitialState;
-   KIRQL OldIrql;
   
    DPRINT("KiInsertQueue(Queue %x, Entry %x)\n", Queue, Entry);
    
-   OldIrql = KeAcquireDispatcherDatabaseLock ();
-   
    InitialState = Queue->Header.SignalState;
-   Queue->Header.SignalState++;
-   
+
    if (Head)
    {
       InsertHeadList(&Queue->EntryListHead, Entry);
@@ -87,13 +88,21 @@
    {
       InsertTailList(&Queue->EntryListHead, Entry);
    }
-
-   if (Queue->CurrentCount < Queue->MaximumCount && InitialState == 0)
+   
+   //inc. num entries in queue
+   Queue->Header.SignalState++;
+   
+   /* Why the KeGetCurrentThread()->Queue != Queue?
+    * KiInsertQueue might be called from an APC for the current thread. 
+    * -Gunnar
+    */
+   if (Queue->CurrentCount < Queue->MaximumCount &&
+       !IsListEmpty(&Queue->Header.WaitListHead) &&
+       KeGetCurrentThread()->Queue != Queue)
    {
-      KeDispatcherObjectWake(&Queue->Header);
+      KiDispatcherObjectWake(&Queue->Header);
    }
 
-   KeReleaseDispatcherDatabaseLock(OldIrql);
    return InitialState;
 }
 
@@ -106,7 +115,14 @@
 KeInsertHeadQueue(IN PKQUEUE Queue,
 		  IN PLIST_ENTRY Entry)
 {
-   return KiInsertQueue(Queue,Entry,TRUE);
+   LONG Result;
+   KIRQL OldIrql;
+   
+   OldIrql = KeAcquireDispatcherDatabaseLock();
+   Result = KiInsertQueue(Queue,Entry,TRUE);
+   KeReleaseDispatcherDatabaseLock(OldIrql);
+   
+   return Result;
 }
 
 
@@ -117,7 +133,14 @@
 KeInsertQueue(IN PKQUEUE Queue,
 	      IN PLIST_ENTRY Entry)
 {
-   return KiInsertQueue(Queue,Entry,FALSE);
+   LONG Result;
+   KIRQL OldIrql;
+   
+   OldIrql = KeAcquireDispatcherDatabaseLock();
+   Result = KiInsertQueue(Queue,Entry,FALSE);
+   KeReleaseDispatcherDatabaseLock(OldIrql);
+   
+   return Result;
 }
 
 
@@ -129,6 +152,7 @@
 	      IN KPROCESSOR_MODE WaitMode,
 	      IN PLARGE_INTEGER Timeout OPTIONAL)
 {
+   
    PLIST_ENTRY ListEntry;
    NTSTATUS Status;
    PKTHREAD Thread = KeGetCurrentThread();
@@ -136,50 +160,75 @@
 
    OldIrql = KeAcquireDispatcherDatabaseLock ();
 
-   //assiciate new thread with queue?
    if (Thread->Queue != Queue)
    {
-      //remove association from other queue
-      if (!IsListEmpty(&Thread->QueueListEntry))
+      /*
+       * INVESTIGATE: What is the Thread->QueueListEntry used for? It's linked it into the
+       * Queue->ThreadListHead when the thread registers with the queue and unlinked when
+       * the thread registers with a new queue. The Thread->Queue already tells us what
+       * queue the thread is registered with.
+       * -Gunnar
+       */
+
+      //unregister thread from previous queue (if any)
+      if (Thread->Queue)
       {
          RemoveEntryList(&Thread->QueueListEntry);
+         Thread->Queue->CurrentCount--;
+         
+         if (Thread->Queue->CurrentCount < Thread->Queue->MaximumCount && 
+             !IsListEmpty(&Thread->Queue->EntryListHead))
+         {
+            KiDispatcherObjectWake(&Thread->Queue->Header);
+         }
       }
 
-      //associate with this queue
-      InsertHeadList(&Queue->ThreadListHead, &Thread->QueueListEntry);
-      Queue->CurrentCount++;
+      // register thread with this queue
+      InsertTailList(&Queue->ThreadListHead, &Thread->QueueListEntry);
       Thread->Queue = Queue;
    }
-   
-   if (Queue->CurrentCount <= Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
+   else /* if (Thread->Queue == Queue) */
    {
-      ListEntry = RemoveHeadList(&Queue->EntryListHead);
-      Queue->Header.SignalState--;
-      KeReleaseDispatcherDatabaseLock (OldIrql);
-      return ListEntry;
+      //dec. num running threads
+      Queue->CurrentCount--;
    }
-
-   //need to wait for it...
-   KeReleaseDispatcherDatabaseLock (OldIrql);
-
-   Status = KeWaitForSingleObject(Queue,
-                                  WrQueue,
-                                  WaitMode,
-                                  TRUE,//Alertable,
-                                  Timeout);
-
-   if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
-   {
-      return (PVOID)Status;
-   }
-   else
+   
+   
+   
+   
+   while (TRUE)
    {
-      OldIrql = KeAcquireDispatcherDatabaseLock ();
-      ListEntry = RemoveHeadList(&Queue->EntryListHead);
-      KeReleaseDispatcherDatabaseLock (OldIrql);
-      return ListEntry;
+      if (Queue->CurrentCount < Queue->MaximumCount && !IsListEmpty(&Queue->EntryListHead))
+      {
+         ListEntry = RemoveHeadList(&Queue->EntryListHead);
+         //dec. num entries in queue
+         Queue->Header.SignalState--;
+         //inc. num running threads
+         Queue->CurrentCount++;
+         
+         KeReleaseDispatcherDatabaseLock(OldIrql);
+         return ListEntry;
+      }
+      else
+      {
+         //inform KeWaitXxx that we are holding disp. lock
+         Thread->WaitNext = TRUE;
+         Thread->WaitIrql = OldIrql;
+
+         Status = KeWaitForSingleObject(Queue,
+                                        WrQueue,
+                                        WaitMode,
+                                        TRUE, //bAlertable
+                                        Timeout);
+
+         if (Status == STATUS_TIMEOUT || Status == STATUS_USER_APC)
+         {
+            return (PVOID)Status;
+         }
+         
+         OldIrql = KeAcquireDispatcherDatabaseLock ();
+      }
    }
-
 }
 
 
@@ -195,23 +244,31 @@
 
    DPRINT("KeRundownQueue(Queue %x)\n", Queue);
 
-   //FIXME: should we wake thread waiting on a queue? 
-
+   /* I'm just guessing how this should work:-/
+    * -Gunnar 
+    */
+     
    OldIrql = KeAcquireDispatcherDatabaseLock ();
 
-   // Clear Queue and QueueListEntry members of all threads associated with this queue
+   //no thread must wait on queue at rundown
+   ASSERT(IsListEmpty(&Queue->Header.WaitListHead));
+   
+   // unlink threads and clear their Thread->Queue
    while (!IsListEmpty(&Queue->ThreadListHead))
    {
       EnumEntry = RemoveHeadList(&Queue->ThreadListHead);
-      InitializeListHead(EnumEntry);
       Thread = CONTAINING_RECORD(EnumEntry, KTHREAD, QueueListEntry);
       Thread->Queue = NULL;
    }
 
-   if (!IsListEmpty(&Queue->EntryListHead))
-      EnumEntry = Queue->EntryListHead.Flink;
-   else
+   if (IsListEmpty(&Queue->EntryListHead))
+   {
       EnumEntry = NULL;
+   }
+   else
+   {
+      EnumEntry = Queue->EntryListHead.Flink;
+   }
 
    KeReleaseDispatcherDatabaseLock (OldIrql);
 

reactos/ntoskrnl/ke
sem.c 1.15 -> 1.16
diff -u -r1.15 -r1.16
--- sem.c	15 Aug 2004 16:39:05 -0000	1.15
+++ sem.c	21 Nov 2004 18:33:54 -0000	1.16
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: sem.c,v 1.15 2004/08/15 16:39:05 chorns Exp $
+/* $Id: sem.c,v 1.16 2004/11/21 18:33:54 gdalsnes Exp $
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/sem.c
@@ -105,7 +105,7 @@
   Semaphore->Header.SignalState += Adjustment;
   if (InitialState == 0)
     {
-      KeDispatcherObjectWake(&Semaphore->Header);
+      KiDispatcherObjectWake(&Semaphore->Header);
     }
 
   if (Wait == FALSE)

reactos/ntoskrnl/ke
timer.c 1.89 -> 1.90
diff -u -r1.89 -r1.90
--- timer.c	21 Nov 2004 06:51:18 -0000	1.89
+++ timer.c	21 Nov 2004 18:33:54 -0000	1.90
@@ -1,4 +1,4 @@
-/* $Id: timer.c,v 1.89 2004/11/21 06:51:18 ion Exp $
+/* $Id: timer.c,v 1.90 2004/11/21 18:33:54 gdalsnes Exp $
  *
  * COPYRIGHT:      See COPYING in the top level directory
  * PROJECT:        ReactOS kernel
@@ -526,11 +526,11 @@
 	DPRINT("Finished dpc routine\n");
      }
 
-   ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+   ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
 
    KeAcquireDispatcherDatabaseLockAtDpcLevel();
    Timer->Header.SignalState = TRUE;
-   KeDispatcherObjectWake(&Timer->Header);
+   KiDispatcherObjectWake(&Timer->Header);
    KeReleaseDispatcherDatabaseLockFromDpcLevel();
 
    if (Timer->Period != 0)
@@ -571,7 +571,7 @@
 
    DPRINT("KeExpireTimers()\n");
 
-   ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+   ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
 
    InitializeListHead(&TimerList);
 

reactos/ntoskrnl/ke
wait.c 1.61 -> 1.62
diff -u -r1.61 -r1.62
--- wait.c	11 Nov 2004 22:23:52 -0000	1.61
+++ wait.c	21 Nov 2004 18:33:54 -0000	1.62
@@ -110,6 +110,8 @@
          break;
       
       case InternalQueueType:
+         break;
+         
       case InternalSemaphoreType:
          hdr->SignalState--;
          break;
@@ -193,33 +195,31 @@
    }
 }
 
-VOID KeRemoveAllWaitsThread(PETHREAD Thread, NTSTATUS WaitStatus, BOOL Unblock)
+/* Must be called with the dispatcher lock held */
+BOOLEAN KiAbortWaitThread(PKTHREAD Thread, NTSTATUS WaitStatus)
 {
-   PKWAIT_BLOCK WaitBlock, PrevWaitBlock;
-   BOOLEAN WasWaiting = FALSE;
+   PKWAIT_BLOCK WaitBlock;
+   BOOLEAN WasWaiting;
 
-   WaitBlock = (PKWAIT_BLOCK)Thread->Tcb.WaitBlockList;
-   if (WaitBlock != NULL)
-     {
-	WasWaiting = TRUE;
-     }
-   while (WaitBlock != NULL)
-     {
-	if (WaitBlock->WaitListEntry.Flink != NULL && WaitBlock->WaitListEntry.Blink != NULL)
-	  { 
-	    RemoveEntryList (&WaitBlock->WaitListEntry);
-            WaitBlock->WaitListEntry.Flink = WaitBlock->WaitListEntry.Blink = NULL;
-	  }
-	PrevWaitBlock = WaitBlock;
-	WaitBlock = WaitBlock->NextWaitBlock;
-	PrevWaitBlock->NextWaitBlock = NULL;
-     }
-   Thread->Tcb.WaitBlockList = NULL;
+   /* if we are blocked, we must be waiting on something also */
+   ASSERT((Thread->State == THREAD_STATE_BLOCKED) == (Thread->WaitBlockList != NULL));
 
-   if (WasWaiting && Unblock)
-     {
-	PsUnblockThread(Thread, &WaitStatus);
-     }
+   WaitBlock = (PKWAIT_BLOCK)Thread->WaitBlockList;
+   WasWaiting = (WaitBlock != NULL);
+   
+   while (WaitBlock)
+   {
+      RemoveEntryList(&WaitBlock->WaitListEntry);
+      WaitBlock = WaitBlock->NextWaitBlock;
+   }
+   
+   Thread->WaitBlockList = NULL;
+
+   if (WasWaiting)
+   {
+	   PsUnblockThread((PETHREAD)Thread, &WaitStatus);
+   }
+   return WasWaiting;
 }
 
 static BOOLEAN
@@ -260,11 +260,7 @@
          DPRINT("WaitAny: Remove all wait blocks.\n");
          for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
          {
-            if (Waiter->WaitListEntry.Flink != NULL && Waiter->WaitListEntry.Blink != NULL)
-	      {
-		RemoveEntryList(&Waiter->WaitListEntry);
-		Waiter->WaitListEntry.Flink = Waiter->WaitListEntry.Blink = NULL;
-	      }
+            RemoveEntryList(&Waiter->WaitListEntry);
          }
 
          WaiterHead->Thread->WaitBlockList = NULL;
@@ -273,7 +269,7 @@
           * If a WakeAll KiSideEffectsBeforeWake(hdr,.. will be called several times,
           * but thats ok since WakeAll objects has no sideeffects.
           */
-         Abandoned = KiSideEffectsBeforeWake(hdr, WaiterHead->Thread) ? TRUE : Abandoned;
+         Abandoned |= KiSideEffectsBeforeWake(hdr, WaiterHead->Thread);
       }
       else
       {
@@ -299,16 +295,11 @@
          {
             for (Waiter = WaiterHead->Thread->WaitBlockList; Waiter; Waiter = Waiter->NextWaitBlock)
             {
-               if (Waiter->WaitListEntry.Flink != NULL && Waiter->WaitListEntry.Blink != NULL)
-	       {
-		  RemoveEntryList(&Waiter->WaitListEntry);
-		  Waiter->WaitListEntry.Flink = Waiter->WaitListEntry.Blink = NULL;
-	       }
+               RemoveEntryList(&Waiter->WaitListEntry);
          
                if (Waiter->WaitType == WaitAll)
                {
-                  Abandoned = KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread)
-                     ? TRUE : Abandoned;
+                  Abandoned |= KiSideEffectsBeforeWake(Waiter->Object, Waiter->Thread);
                }
 
                //no WaitAny objects can possibly be signaled since we are here
@@ -339,7 +330,7 @@
 }
 
 
-BOOLEAN KeDispatcherObjectWake(DISPATCHER_HEADER* hdr)
+BOOLEAN KiDispatcherObjectWake(DISPATCHER_HEADER* hdr)
 /*
  * FUNCTION: Wake threads waiting on a dispatcher object
  * NOTE: The exact semantics of waking are dependant on the type of object
@@ -366,6 +357,8 @@
 	return(KeDispatcherObjectWakeOne(hdr));
 
       case InternalQueueType:
+   return(KeDispatcherObjectWakeOne(hdr));      
+      
       case InternalSemaphoreType:
 	DPRINT("hdr->SignalState %d\n", hdr->SignalState);
 	if(hdr->SignalState>0)
@@ -483,7 +476,6 @@
    ULONG CountSignaled;
    ULONG i;
    NTSTATUS Status;
-   KIRQL WaitIrql;
    KIRQL OldIrql;
    BOOLEAN Abandoned;
 
@@ -493,7 +485,6 @@
    ASSERT(0 < Count && Count <= EX_MAXIMUM_WAIT_OBJECTS);
 
    CurrentThread = KeGetCurrentThread();
-   WaitIrql = KeGetCurrentIrql();
 
    /*
     * Work out where we are going to put the wait blocks
@@ -516,6 +507,8 @@
       }
    }
 
+
+
    /*
     * Set up the timeout if required
     */
@@ -528,9 +521,8 @@
    {
       if (CurrentThread->WaitNext)
       {
+         CurrentThread->WaitNext = FALSE;
          OldIrql = CurrentThread->WaitIrql;
-         CurrentThread->WaitNext = 0;
-         CurrentThread->WaitIrql = PASSIVE_LEVEL;
       }
       else
       {
@@ -711,28 +703,33 @@
                         &CurrentThread->WaitBlock[3].WaitListEntry);
       }
 
-      //io completion
-      if (CurrentThread->Queue)
+      //kernel queues
+      if (CurrentThread->Queue && WaitReason != WrQueue)
       {
-         CurrentThread->Queue->CurrentCount--;   
-         if (WaitReason != WrQueue && CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount &&
+         DPRINT("queue: sleep on something else\n");
+         CurrentThread->Queue->CurrentCount--;  
+         
+         //wake another thread
+         if (CurrentThread->Queue->CurrentCount < CurrentThread->Queue->MaximumCount &&
              !IsListEmpty(&CurrentThread->Queue->EntryListHead))
          {
-            KeDispatcherObjectWake(&CurrentThread->Queue->Header);
+            KiDispatcherObjectWake(&CurrentThread->Queue->Header);
          }
       }
 
-      PsBlockThread(&Status, Alertable, WaitMode, TRUE, WaitIrql, (UCHAR)WaitReason);
+      PsBlockThread(&Status, Alertable, WaitMode, TRUE, OldIrql, (UCHAR)WaitReason);
 
-      //io completion
-      if (CurrentThread->Queue)
+      //kernel queues
+      //FIXME: dispatcher lock not held here!
+      if (CurrentThread->Queue && WaitReason != WrQueue)
       {
+         DPRINT("queue: wake from something else\n");
          CurrentThread->Queue->CurrentCount++;
       }
-
-
-   }
-   while (Status == STATUS_KERNEL_APC);
+      
+      
+   } while (Status == STATUS_KERNEL_APC);
+   
 
    if (Timeout != NULL)
    {
CVSspam 0.2.8