- Fixed ExTimerRundown.  
- Fixed adding and removing of timers to the wake list.  
- Fixed the reinserting of the timer apc.  
- Don't unlock the timer twice in NtSetTimer.
Modified: trunk/reactos/ntoskrnl/ex/timer.c

Modified: trunk/reactos/ntoskrnl/ex/timer.c
--- trunk/reactos/ntoskrnl/ex/timer.c	2005-04-02 15:11:36 UTC (rev 14442)
+++ trunk/reactos/ntoskrnl/ex/timer.c	2005-04-02 15:55:15 UTC (rev 14443)
@@ -11,6 +11,8 @@
 /* INCLUDES *****************************************************************/
 
 #include <ntoskrnl.h>
+
+#define NDEBUG
 #include <internal/debug.h>
 
 /* TYPES ********************************************************************/
@@ -22,7 +24,6 @@
     KDPC TimerDpc;
     LIST_ENTRY ActiveTimerListEntry;
     KSPIN_LOCK Lock;
-    LONG Period;
     BOOLEAN ApcAssociated;
     BOOLEAN WakeTimer;
     LIST_ENTRY WakeTimerListEntry;
@@ -60,54 +61,46 @@
     PETHREAD Thread = PsGetCurrentThread();
     KIRQL OldIrql;
     PLIST_ENTRY CurrentEntry;
-    BOOLEAN KillTimer = FALSE;
     PETIMER Timer;
     
     /* Lock the Thread's Active Timer List*/
     KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql);
     
-    /* Loop through all the timers */
-    CurrentEntry = Thread->ActiveTimerListHead.Flink;
-    while (CurrentEntry != &Thread->ActiveTimerListHead) {
-    
+    while (!IsListEmpty(&Thread->ActiveTimerListHead)) 
+    {
+        
+        /* Remove a Timer */
+	CurrentEntry = RemoveTailList(&Thread->ActiveTimerListHead);
+
         /* Get the Timer */
-        Timer = CONTAINING_RECORD(CurrentEntry, ETIMER, ActiveTimerListEntry);
+        Timer = CONTAINING_RECORD(CurrentEntry, ETIMER, ActiveTimerListEntry);
+        
+        ASSERT (Timer->ApcAssociated);
+	Timer->ApcAssociated = FALSE;      
+	
         DPRINT("Timer, ThreadList: %x, %x\n", Timer, Thread);
         
         /* Unlock the list */
-        KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql);
+        KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
             
         /* Lock the Timer */
-        KeAcquireSpinLock(&Timer->Lock, &OldIrql);
+        KeAcquireSpinLockAtDpcLevel(&Timer->Lock);
         
-        /* Relock the active list */
-        KeAcquireSpinLockAtDpcLevel(&Thread->ActiveTimerListLock);
+        ASSERT (&Thread->Tcb == Timer->TimerApc.Thread);
         
-        /* Make sure it's associated to us */
-        if ((Timer->ApcAssociated) && (&Thread->Tcb == Timer->TimerApc.Thread)) {
-        
-            /* Remove it */
-            DPRINT("Removing from Thread: %x\n", Thread);
-            RemoveEntryList(&Thread->ActiveTimerListHead); 
-            KeCancelTimer(&Timer->KeTimer);
-            KeRemoveQueueDpc(&Timer->TimerDpc);
-            KeRemoveQueueApc(&Timer->TimerApc);   
-            Timer->ApcAssociated = FALSE;      
-            KillTimer = TRUE;
-        }
+        KeCancelTimer(&Timer->KeTimer);
+        KeRemoveQueueDpc(&Timer->TimerDpc);
+        KeRemoveQueueApc(&Timer->TimerApc);   
                        
-        /* Unlock the list */
-        KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
         
         /* Unlock the Timer */
         KeReleaseSpinLock(&Timer->Lock, OldIrql);
         
         /* Dereference it, if needed */
-        if (KillTimer) ObDereferenceObject(Timer);
+        ObDereferenceObject(Timer);
         
         /* Loop again */
         KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql);
-        CurrentEntry = CurrentEntry->Flink;
     }       
     
     KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql);
@@ -126,11 +119,12 @@
     KeAcquireSpinLock(&ExpWakeListLock, &OldIrql);
     
     /* Check if it has a Wait List */
-    if (!IsListEmpty(&Timer->WakeTimerListEntry)) {
+    if (Timer->WakeTimer) {
     
         /* Remove it from the Wait List */
         DPRINT("Removing wake list\n");
         RemoveEntryList(&Timer->WakeTimerListEntry);
+	Timer->WakeTimer = FALSE;
     }
     
     /* Release the Wake List */
@@ -202,8 +196,8 @@
      */
     if ((Timer->ApcAssociated) && 
         (&CurrentThread->Tcb == Timer->TimerApc.Thread) && 
-        (!Timer->Period)) {
-    
+        (!Timer->KeTimer.Period)) {
+
         /* Remove it from the Active Timers List */
         DPRINT("Removing Timer\n");
         RemoveEntryList(&Timer->ActiveTimerListEntry);
@@ -433,7 +427,6 @@
 
         /* Set Initial State */
         Timer->ApcAssociated = FALSE;
-        InitializeListHead(&Timer->WakeTimerListEntry);
         Timer->WakeTimer = FALSE;
         
         /* Insert the Timer */
@@ -691,16 +684,16 @@
         /* Handle Wake Timers */
         DPRINT("Doing Wake Semantics\n");
         KeAcquireSpinLockAtDpcLevel(&ExpWakeListLock);
-        if (WakeTimer) {
+        if (WakeTimer && !Timer->WakeTimer) {
         
             /* Insert it into the list */
+            Timer->WakeTimer = TRUE;
             InsertTailList(&ExpWakeList, &Timer->WakeTimerListEntry);
-        
-        } else {
+        } else if (!WakeTimer && Timer->WakeTimer) {
             
             /* Remove it from the list */
             RemoveEntryList(&Timer->WakeTimerListEntry);
-            Timer->WakeTimerListEntry.Flink = NULL;
+            Timer->WakeTimer = FALSE;
         }
         KeReleaseSpinLockFromDpcLevel(&ExpWakeListLock);
         
@@ -740,9 +733,6 @@
         /* Dereference the Object */
         ObDereferenceObject(Timer);
         
-        /* Unlock the Timer */
-        KeReleaseSpinLock(&Timer->Lock, OldIrql);
-                
         /* Dereference if it was previously enabled */
         if (!TimerApcRoutine) ObDereferenceObject(Timer);
         if (KillTimer) ObDereferenceObject(Timer);