[ros-diffs] [fireball] 25731: Update ex/timer.c up to 25610.

fireball at svn.reactos.org fireball at svn.reactos.org
Mon Feb 5 21:41:01 CET 2007


Author: fireball
Date: Mon Feb  5 23:41:00 2007
New Revision: 25731

URL: http://svn.reactos.org/svn/reactos?rev=25731&view=rev
Log:
Update ex/timer.c up to 25610.

Modified:
    branches/ros-branch-0_3_1/reactos/include/ndk/kefuncs.h
    branches/ros-branch-0_3_1/reactos/ntoskrnl/ex/timer.c
    branches/ros-branch-0_3_1/reactos/ntoskrnl/include/internal/ex.h

Modified: branches/ros-branch-0_3_1/reactos/include/ndk/kefuncs.h
URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_1/reactos/include/ndk/kefuncs.h?rev=25731&r1=25730&r2=25731&view=diff
==============================================================================
--- branches/ros-branch-0_3_1/reactos/include/ndk/kefuncs.h (original)
+++ branches/ros-branch-0_3_1/reactos/include/ndk/kefuncs.h Mon Feb  5 23:41:00 2007
@@ -195,6 +195,12 @@
     VOID
 );
 
+VOID
+NTAPI
+KeFlushQueuedDpcs(
+    VOID
+);
+
 BOOLEAN
 NTAPI
 KiIpiServiceRoutine(

Modified: branches/ros-branch-0_3_1/reactos/ntoskrnl/ex/timer.c
URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_1/reactos/ntoskrnl/ex/timer.c?rev=25731&r1=25730&r2=25731&view=diff
==============================================================================
--- branches/ros-branch-0_3_1/reactos/ntoskrnl/ex/timer.c (original)
+++ branches/ros-branch-0_3_1/reactos/ntoskrnl/ex/timer.c Mon Feb  5 23:41:00 2007
@@ -1,40 +1,18 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/ex/timer.c
  * PURPOSE:         Executive Timer Implementation
- *
- * PROGRAMMERS:     Alex Ionescu (alex at relsoft.net)
- *                  David Welch (welch at mcmail.com)
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu at reactos.org)
  */
 
-/* INCLUDES *****************************************************************/
+/* INCLUDES ******************************************************************/
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
-
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, ExpInitializeTimerImplementation)
-#endif
-
-
-/* TYPES ********************************************************************/
-
-/* Executive Timer Object */
-typedef struct _ETIMER
-{
-    KTIMER KeTimer;
-    KAPC TimerApc;
-    KDPC TimerDpc;
-    LIST_ENTRY ActiveTimerListEntry;
-    KSPIN_LOCK Lock;
-    BOOLEAN ApcAssociated;
-    BOOLEAN WakeTimer;
-    LIST_ENTRY WakeTimerListEntry;
-} ETIMER, *PETIMER;
-
-/* GLOBALS ******************************************************************/
+#include <debug.h>
+
+/* GLOBALS *******************************************************************/
 
 /* Timer Object Type */
 POBJECT_TYPE ExTimerType = NULL;
@@ -55,191 +33,198 @@
 static const INFORMATION_CLASS_INFO ExTimerInfoClass[] =
 {
     /* TimerBasicInformation */
-    ICI_SQ_SAME( sizeof(TIMER_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY ),
+    ICI_SQ_SAME(sizeof(TIMER_BASIC_INFORMATION), sizeof(ULONG), ICIF_QUERY),
 };
 
-/* FUNCTIONS *****************************************************************/
+/* PRIVATE FUNCTIONS *********************************************************/
 
 VOID
-STDCALL
+NTAPI
 ExTimerRundown(VOID)
 {
     PETHREAD Thread = PsGetCurrentThread();
     KIRQL OldIrql;
     PLIST_ENTRY CurrentEntry;
     PETIMER Timer;
-
-    /* Lock the Thread's Active Timer List*/
+    ULONG DerefsToDo;
+
+    /* Lock the Thread's Active Timer List and loop it */
     KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql);
-
-    while (!IsListEmpty(&Thread->ActiveTimerListHead))
-    {
-        /* Remove a Timer */
-        CurrentEntry = RemoveTailList(&Thread->ActiveTimerListHead);
-
-        /* Get the Timer */
+    CurrentEntry = Thread->ActiveTimerListHead.Flink;
+    while (CurrentEntry != &Thread->ActiveTimerListHead)
+    {
+        /* Get the timer */
         Timer = CONTAINING_RECORD(CurrentEntry, ETIMER, ActiveTimerListEntry);
-        DPRINT("Timer, ThreadList: 0x%p, 0x%p\n", Timer, Thread);
-
-        /* Mark it as deassociated */
-        ASSERT (Timer->ApcAssociated);
-        Timer->ApcAssociated = FALSE;
+
+        /* Reference it */
+        ObReferenceObject(Timer);
+        DerefsToDo = 1;
+
+        /* Unlock the list */
+        KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql);
+
+        /* Lock the Timer */
+        KeAcquireSpinLock(&Timer->Lock, &OldIrql);
+
+        /* Lock the list again */
+        KeAcquireSpinLockAtDpcLevel(&Thread->ActiveTimerListLock);
+
+        /* Make sure that the timer is valid */
+        if ((Timer->ApcAssociated) && (&Thread->Tcb == Timer->TimerApc.Thread))
+        {
+            /* Remove it from the list */
+            RemoveEntryList(&Timer->ActiveTimerListEntry);
+            Timer->ApcAssociated = FALSE;
+
+            /* Cancel the timer and remove its DPC and APC */
+            KeCancelTimer(&Timer->KeTimer);
+            KeRemoveQueueDpc(&Timer->TimerDpc);
+            if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++;
+
+            /* Add another dereference to do */
+            DerefsToDo++;
+        }
 
         /* Unlock the list */
         KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
 
-        /* Lock the Timer */
-        KeAcquireSpinLockAtDpcLevel(&Timer->Lock);
-
-        /* Cancel the timer and remove its DPC and APC */
-        ASSERT(&Thread->Tcb == Timer->TimerApc.Thread);
-        KeCancelTimer(&Timer->KeTimer);
-        KeRemoveQueueDpc(&Timer->TimerDpc);
-        KeRemoveQueueApc(&Timer->TimerApc);
-
         /* Unlock the Timer */
         KeReleaseSpinLock(&Timer->Lock, OldIrql);
 
         /* Dereference it */
-        ObDereferenceObject(Timer);
+        ObDereferenceObjectEx(Timer, DerefsToDo);
 
         /* Loop again */
         KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql);
+        CurrentEntry = Thread->ActiveTimerListHead.Flink;
     }
 
     /* Release lock and return */
     KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql);
-    return;
 }
 
 VOID
-STDCALL
-ExpDeleteTimer(PVOID ObjectBody)
+NTAPI
+ExpDeleteTimer(IN PVOID ObjectBody)
 {
     KIRQL OldIrql;
     PETIMER Timer = ObjectBody;
-    DPRINT("ExpDeleteTimer(Timer: 0x%p)\n", Timer);
 
     /* Check if it has a Wait List */
-    if (Timer->WakeTimer)
+    if (Timer->WakeTimerListEntry.Flink)
     {
         /* Lock the Wake List */
         KeAcquireSpinLock(&ExpWakeListLock, &OldIrql);
 
         /* Check again, since it might've changed before we locked */
-        if (Timer->WakeTimer)
+        if (Timer->WakeTimerListEntry.Flink)
         {
             /* Remove it from the Wait List */
-            DPRINT("Removing wake list\n");
             RemoveEntryList(&Timer->WakeTimerListEntry);
-            Timer->WakeTimer = FALSE;
+            Timer->WakeTimerListEntry.Flink = NULL;
         }
 
         /* Release the Wake List */
         KeReleaseSpinLock(&ExpWakeListLock, OldIrql);
     }
 
-    /* Tell the Kernel to cancel the Timer */
-    DPRINT("Cancelling Timer\n");
+    /* Tell the Kernel to cancel the Timer and flush all queued DPCs */
     KeCancelTimer(&Timer->KeTimer);
+    KeFlushQueuedDpcs();
 }
 
 VOID
-STDCALL
-ExpTimerDpcRoutine(PKDPC Dpc,
-                   PVOID DeferredContext,
-                   PVOID SystemArgument1,
-                   PVOID SystemArgument2)
+NTAPI
+ExpTimerDpcRoutine(IN PKDPC Dpc,
+                   IN PVOID DeferredContext,
+                   IN PVOID SystemArgument1,
+                   IN PVOID SystemArgument2)
+{
+    PETIMER Timer = DeferredContext;
+    BOOLEAN Inserted = FALSE;
+
+    /* Reference the timer */
+    if (!ObReferenceObjectSafe(Timer)) return;
+
+    /* Lock the Timer */
+    KeAcquireSpinLockAtDpcLevel(&Timer->Lock);
+
+    /* Check if the timer is associated */
+    if (Timer->ApcAssociated)
+    {
+        /* Queue the APC */
+        Inserted = KeInsertQueueApc(&Timer->TimerApc,
+                                    SystemArgument1,
+                                    SystemArgument2,
+                                    IO_NO_INCREMENT);
+    }
+
+    /* Release the Timer */
+    KeReleaseSpinLockFromDpcLevel(&Timer->Lock);
+
+    /* Dereference it if we couldn't queue the APC */
+    if (!Inserted) ObDereferenceObject(Timer);
+}
+
+VOID
+NTAPI
+ExpTimerApcKernelRoutine(IN PKAPC Apc,
+                         IN OUT PKNORMAL_ROUTINE* NormalRoutine,
+                         IN OUT PVOID* NormalContext,
+                         IN OUT PVOID* SystemArgument1,
+                         IN OUT PVOID* SystemArguemnt2)
 {
     PETIMER Timer;
     KIRQL OldIrql;
-
-    DPRINT("ExpTimerDpcRoutine(Dpc: 0x%p)\n", Dpc);
-
-    /* Get the Timer Object */
-    Timer = (PETIMER)DeferredContext;
+    ULONG DerefsToDo = 1;
+    PETHREAD Thread = PsGetCurrentThread();
+
+    /* We need to find out which Timer we are */
+    Timer = CONTAINING_RECORD(Apc, ETIMER, TimerApc);
 
     /* Lock the Timer */
     KeAcquireSpinLock(&Timer->Lock, &OldIrql);
 
-    /* Queue the APC */
-    if(Timer->ApcAssociated)
-    {
-        DPRINT("Queuing APC\n");
-        KeInsertQueueApc(&Timer->TimerApc,
-                         SystemArgument1,
-                         SystemArgument2,
-                         IO_NO_INCREMENT);
-    }
-
-    /* Release the Timer */
+    /* Lock the Thread's Active Timer List*/
+    KeAcquireSpinLockAtDpcLevel(&Thread->ActiveTimerListLock);
+
+    /* Make sure that the Timer is valid, and that it belongs to this thread */
+    if ((Timer->ApcAssociated) && (&Thread->Tcb == Timer->TimerApc.Thread))
+    {
+        /* Check if it's not periodic */
+        if (!Timer->Period)
+        {
+            /* Remove it from the Active Timers List */
+            RemoveEntryList(&Timer->ActiveTimerListEntry);
+
+            /* Disable it */
+            Timer->ApcAssociated = FALSE;
+            DerefsToDo++;
+        }
+    }
+    else
+    {
+        /* Clear the normal routine */
+        *NormalRoutine = NULL;
+    }
+
+    /* Release locks */
+    KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
     KeReleaseSpinLock(&Timer->Lock, OldIrql);
-    return;
-}
-
-
-VOID
-STDCALL
-ExpTimerApcKernelRoutine(PKAPC Apc,
-                         PKNORMAL_ROUTINE* NormalRoutine,
-                         PVOID* NormalContext,
-                         PVOID* SystemArgument1,
-                         PVOID* SystemArguemnt2)
-{
-    PETIMER Timer;
-    KIRQL OldIrql;
-    PETHREAD CurrentThread = PsGetCurrentThread();
-
-    /* We need to find out which Timer we are */
-    Timer = CONTAINING_RECORD(Apc, ETIMER, TimerApc);
-    DPRINT("ExpTimerApcKernelRoutine(Apc: 0x%p. Timer: 0x%p)\n", Apc, Timer);
-
-    /* Lock the Timer */
-    KeAcquireSpinLock(&Timer->Lock, &OldIrql);
-
-    /* Lock the Thread's Active Timer List*/
-    KeAcquireSpinLockAtDpcLevel(&CurrentThread->ActiveTimerListLock);
-
-    /*
-     * Make sure that the Timer is still valid, and that it belongs to this thread
-     * Remove it if it's not periodic
-     */
-    if ((Timer->ApcAssociated) &&
-        (&CurrentThread->Tcb == Timer->TimerApc.Thread) &&
-        (!Timer->KeTimer.Period))
-    {
-        /* Remove it from the Active Timers List */
-        DPRINT("Removing Timer\n");
-        RemoveEntryList(&Timer->ActiveTimerListEntry);
-
-        /* Disable it */
-        Timer->ApcAssociated = FALSE;
-
-        /* Release spinlocks */
-        KeReleaseSpinLockFromDpcLevel(&CurrentThread->ActiveTimerListLock);
-        KeReleaseSpinLock(&Timer->Lock, OldIrql);
-
-        /* Dereference the Timer Object */
-        ObDereferenceObject(Timer);
-        return;
-    }
-
-    /* Release spinlocks */
-    KeReleaseSpinLockFromDpcLevel(&CurrentThread->ActiveTimerListLock);
-    KeReleaseSpinLock(&Timer->Lock, OldIrql);
+
+    /* Dereference as needed */
+    ObDereferenceObjectEx(Timer, DerefsToDo);
 }
 
 VOID
 INIT_FUNCTION
-STDCALL
+NTAPI
 ExpInitializeTimerImplementation(VOID)
 {
     OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
     UNICODE_STRING Name;
 
-    DPRINT("Creating Timer Object Type\n");
-  
-    /* Create the Event Pair Object Type */
+    /* Create the Timer Object Type */
     RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
     RtlInitUnicodeString(&Name, L"Timer");
     ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
@@ -256,8 +241,10 @@
     InitializeListHead(&ExpWakeList);
 }
 
+/* PUBLIC FUNCTIONS **********************************************************/
+
 NTSTATUS
-STDCALL
+NTAPI
 NtCancelTimer(IN HANDLE TimerHandle,
               OUT PBOOLEAN CurrentState OPTIONAL)
 {
@@ -266,13 +253,12 @@
     BOOLEAN State;
     KIRQL OldIrql;
     PETHREAD TimerThread;
-    BOOLEAN KillTimer = FALSE;
+    ULONG DerefsToDo = 1;
     NTSTATUS Status = STATUS_SUCCESS;
     PAGED_CODE();
-    DPRINT("NtCancelTimer(0x%p, 0x%x)\n", TimerHandle, CurrentState);
 
     /* Check Parameter Validity */
-    if(CurrentState && PreviousMode != KernelMode)
+    if ((CurrentState) && (PreviousMode != KernelMode))
     {
         _SEH_TRY
         {
@@ -283,7 +269,6 @@
             Status = _SEH_GetExceptionCode();
         }
         _SEH_END;
-
         if(!NT_SUCCESS(Status)) return Status;
     }
 
@@ -294,30 +279,25 @@
                                        PreviousMode,
                                        (PVOID*)&Timer,
                                        NULL);
-
-    /* Check for success */
-    if(NT_SUCCESS(Status))
-    {
-        DPRINT("Timer Referenced: 0x%p\n", Timer);
-
+    if (NT_SUCCESS(Status))
+    {
         /* Lock the Timer */
         KeAcquireSpinLock(&Timer->Lock, &OldIrql);
 
         /* Check if it's enabled */
         if (Timer->ApcAssociated)
         {
-            /*
-             * First, remove it from the Thread's Active List
-             * Get the Thread.
-             */
-            TimerThread = CONTAINING_RECORD(Timer->TimerApc.Thread, ETHREAD, Tcb);
-            DPRINT("Removing from Thread: 0x%p\n", TimerThread);
+            /* Get the Thread. */
+            TimerThread = CONTAINING_RECORD(Timer->TimerApc.Thread,
+                                            ETHREAD,
+                                            Tcb);
 
             /* Lock its active list */
             KeAcquireSpinLockAtDpcLevel(&TimerThread->ActiveTimerListLock);
 
             /* Remove it */
             RemoveEntryList(&TimerThread->ActiveTimerListHead);
+            Timer->ApcAssociated = FALSE;
 
             /* Unlock the list */
             KeReleaseSpinLockFromDpcLevel(&TimerThread->ActiveTimerListLock);
@@ -325,30 +305,27 @@
             /* Cancel the Timer */
             KeCancelTimer(&Timer->KeTimer);
             KeRemoveQueueDpc(&Timer->TimerDpc);
-            KeRemoveQueueApc(&Timer->TimerApc);
-            Timer->ApcAssociated = FALSE;
-            KillTimer = TRUE;
+            if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++;
+            DerefsToDo++;
         }
         else
         {
             /* If timer was disabled, we still need to cancel it */
-            DPRINT("APC was not Associated. Cancelling Timer\n");
             KeCancelTimer(&Timer->KeTimer);
         }
 
         /* Handle a Wake Timer */
-        if (Timer->WakeTimer)
+        if (Timer->WakeTimerListEntry.Flink)
         {
             /* Lock the Wake List */
             KeAcquireSpinLockAtDpcLevel(&ExpWakeListLock);
 
             /* Check again, since it might've changed before we locked */
-            if (Timer->WakeTimer)
+            if (Timer->WakeTimerListEntry.Flink)
             {
                 /* Remove it from the Wait List */
-                DPRINT("Removing wake list\n");
                 RemoveEntryList(&Timer->WakeTimerListEntry);
-                Timer->WakeTimer = FALSE;
+                Timer->WakeTimerListEntry.Flink = NULL;
             }
 
             /* Release the Wake List */
@@ -362,14 +339,10 @@
         State = KeReadStateTimer(&Timer->KeTimer);
 
         /* Dereference the Object */
-        ObDereferenceObject(Timer);
-
-        /* Dereference if it was previously enabled */
-        if (KillTimer) ObDereferenceObject(Timer);
-        DPRINT1("Timer disabled\n");
+        ObDereferenceObjectEx(Timer, DerefsToDo);
 
         /* Make sure it's safe to write to the handle */
-        if(CurrentState)
+        if (CurrentState)
         {
             _SEH_TRY
             {
@@ -377,7 +350,7 @@
             }
             _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
             {
-                Status = _SEH_GetExceptionCode();
+
             }
             _SEH_END;
         }
@@ -388,7 +361,7 @@
 }
 
 NTSTATUS
-STDCALL
+NTAPI
 NtCreateTimer(OUT PHANDLE TimerHandle,
               IN ACCESS_MASK DesiredAccess,
               IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
@@ -399,7 +372,14 @@
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     NTSTATUS Status = STATUS_SUCCESS;
     PAGED_CODE();
-    DPRINT("NtCreateTimer(Handle: 0x%p, Type: %d)\n", TimerHandle, TimerType);
+
+    /* Check for correct timer type */
+    if ((TimerType != NotificationTimer) &&
+        (TimerType != SynchronizationTimer))
+    {
+        /* Fail */
+        return STATUS_INVALID_PARAMETER_4;
+    }
 
     /* Check Parameter Validity */
     if (PreviousMode != KernelMode)
@@ -413,15 +393,7 @@
             Status = _SEH_GetExceptionCode();
         }
         _SEH_END;
-
         if(!NT_SUCCESS(Status)) return Status;
-    }
-
-    /* Check for correct timer type */
-    if ((TimerType != NotificationTimer) && (TimerType != SynchronizationTimer))
-    {
-        DPRINT1("Invalid Timer Type!\n");
-        return STATUS_INVALID_PARAMETER_4;
     }
 
     /* Create the Object */
@@ -434,23 +406,19 @@
                             0,
                             0,
                             (PVOID*)&Timer);
-
-    /* Check for Success */
-    if(NT_SUCCESS(Status))
-    {
-        /* Initialize the Kernel Timer */
-        DPRINT("Initializing Timer: 0x%p\n", Timer);
-        KeInitializeTimerEx(&Timer->KeTimer, TimerType);
-
-        /* Initialize the Timer Lock */
-        KeInitializeSpinLock(&Timer->Lock);
-
+    if (NT_SUCCESS(Status))
+    {
         /* Initialize the DPC */
         KeInitializeDpc(&Timer->TimerDpc, ExpTimerDpcRoutine, Timer);
 
-        /* Set Initial State */
+        /* Initialize the Kernel Timer */
+        KeInitializeTimerEx(&Timer->KeTimer, TimerType);
+
+        /* Initialize the timer fields */
+        KeInitializeSpinLock(&Timer->Lock);
         Timer->ApcAssociated = FALSE;
         Timer->WakeTimer = FALSE;
+        Timer->WakeTimerListEntry.Flink = NULL;
 
         /* Insert the Timer */
         Status = ObInsertObject((PVOID)Timer,
@@ -459,18 +427,21 @@
                                 0,
                                 NULL,
                                 &hTimer);
-        DPRINT("Timer Inserted\n");
-
-        /* Make sure it's safe to write to the handle */
-        _SEH_TRY
-        {
-            *TimerHandle = hTimer;
-        }
-        _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
-        {
-            Status = _SEH_GetExceptionCode();
-        }
-        _SEH_END;
+
+        /* Check for success */
+        if (NT_SUCCESS(Status))
+        {
+            /* Make sure it's safe to write to the handle */
+            _SEH_TRY
+            {
+                *TimerHandle = hTimer;
+            }
+            _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
+            {
+
+            }
+            _SEH_END;
+        }
     }
 
     /* Return to Caller */
@@ -478,7 +449,7 @@
 }
 
 NTSTATUS
-STDCALL
+NTAPI
 NtOpenTimer(OUT PHANDLE TimerHandle,
             IN ACCESS_MASK DesiredAccess,
             IN POBJECT_ATTRIBUTES ObjectAttributes)
@@ -487,7 +458,6 @@
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
     NTSTATUS Status = STATUS_SUCCESS;
     PAGED_CODE();
-    DPRINT("NtOpenTimer(TimerHandle: 0x%p)\n", TimerHandle);
 
     /* Check Parameter Validity */
     if (PreviousMode != KernelMode)
@@ -501,7 +471,6 @@
             Status = _SEH_GetExceptionCode();
         }
         _SEH_END;
-
         if(!NT_SUCCESS(Status)) return Status;
     }
 
@@ -513,9 +482,7 @@
                                 DesiredAccess,
                                 NULL,
                                 &hTimer);
-
-    /* Check for success */
-    if(NT_SUCCESS(Status))
+    if (NT_SUCCESS(Status))
     {
         /* Make sure it's safe to write to the handle */
         _SEH_TRY
@@ -524,7 +491,7 @@
         }
         _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
         {
-            Status = _SEH_GetExceptionCode();
+
         }
         _SEH_END;
     }
@@ -533,35 +500,30 @@
     return Status;
 }
 
-
 NTSTATUS
-STDCALL
+NTAPI
 NtQueryTimer(IN HANDLE TimerHandle,
              IN TIMER_INFORMATION_CLASS TimerInformationClass,
              OUT PVOID TimerInformation,
              IN ULONG TimerInformationLength,
-             OUT PULONG ReturnLength  OPTIONAL)
+             OUT PULONG ReturnLength OPTIONAL)
 {
     PETIMER Timer;
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    NTSTATUS Status = STATUS_SUCCESS;
-    PTIMER_BASIC_INFORMATION BasicInfo = (PTIMER_BASIC_INFORMATION)TimerInformation;
+    NTSTATUS Status;
+    PTIMER_BASIC_INFORMATION BasicInfo = TimerInformation;
     PAGED_CODE();
-    DPRINT("NtQueryTimer(TimerHandle: 0x%p, Class: %d)\n", TimerHandle, TimerInformationClass);
 
     /* Check Validity */
     Status = DefaultQueryInfoBufferCheck(TimerInformationClass,
                                          ExTimerInfoClass,
-                                         sizeof(ExTimerInfoClass) / sizeof(ExTimerInfoClass[0]),
+                                         sizeof(ExTimerInfoClass) /
+                                         sizeof(ExTimerInfoClass[0]),
                                          TimerInformation,
                                          TimerInformationLength,
                                          ReturnLength,
                                          PreviousMode);
-    if(!NT_SUCCESS(Status))
-    {
-        DPRINT1("NtQueryTimer() failed, Status: 0x%x\n", Status);
-        return Status;
-    }
+    if(!NT_SUCCESS(Status)) return Status;
 
     /* Get the Timer Object */
     Status = ObReferenceObjectByHandle(TimerHandle,
@@ -570,25 +532,21 @@
                                        PreviousMode,
                                        (PVOID*)&Timer,
                                        NULL);
-
-    /* Check for Success */
     if(NT_SUCCESS(Status))
     {
         /* Return the Basic Information */
         _SEH_TRY
         {
             /* Return the remaining time, corrected */
-            BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart -
+            BasicInfo->TimeRemaining.QuadPart = Timer->
+                                                KeTimer.DueTime.QuadPart -
                                                 KeQueryInterruptTime();
 
             /* Return the current state */
             BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
 
             /* Return the buffer length if requested */
-            if(ReturnLength != NULL) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
-
-            DPRINT("Returning Information for Timer: 0x%p. Time Remaining: %I64x\n",
-                    Timer, BasicInfo->TimeRemaining.QuadPart);
+            if (ReturnLength) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
         }
         _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
         {
@@ -605,7 +563,7 @@
 }
 
 NTSTATUS
-STDCALL
+NTAPI
 NtSetTimer(IN HANDLE TimerHandle,
            IN PLARGE_INTEGER DueTime,
            IN PTIMER_APC_ROUTINE TimerApcRoutine OPTIONAL,
@@ -618,14 +576,15 @@
     KIRQL OldIrql;
     BOOLEAN State;
     KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
-    PETHREAD CurrentThread = PsGetCurrentThread();
+    PETHREAD Thread = PsGetCurrentThread();
     LARGE_INTEGER TimerDueTime;
     PETHREAD TimerThread;
-    BOOLEAN KillTimer = FALSE;
+    ULONG DerefsToDo = 1;
     NTSTATUS Status = STATUS_SUCCESS;
     PAGED_CODE();
-    DPRINT("NtSetTimer(TimerHandle: 0x%p, DueTime: %I64x, Apc: 0x%p, Period: %d)\n",
-            TimerHandle, DueTime->QuadPart, TimerApcRoutine, Period);
+
+    /* Check for a valid Period */
+    if (Period < 0) return STATUS_INVALID_PARAMETER_6;
 
     /* Check Parameter Validity */
     if (PreviousMode != KernelMode)
@@ -633,26 +592,19 @@
         _SEH_TRY
         {
             TimerDueTime = ProbeForReadLargeInteger(DueTime);
-
-            if(PreviousState)
-            {
-                ProbeForWriteBoolean(PreviousState);
-            }
+            if (PreviousState) ProbeForWriteBoolean(PreviousState);
         }
         _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
         {
             Status = _SEH_GetExceptionCode();
         }
         _SEH_END;
-
         if(!NT_SUCCESS(Status)) return Status;
     }
-
-    /* Check for a valid Period */
-    if (Period < 0)
-    {
-        DPRINT1("Invalid Period for timer\n");
-        return STATUS_INVALID_PARAMETER_6;
+    else
+    {
+        /* Capture the time directly */
+        TimerDueTime = *DueTime;
     }
 
     /* Get the Timer Object */
@@ -666,7 +618,7 @@
     /* 
      * Tell the user we don't support Wake Timers...
      * when we have the ability to use/detect the Power Management 
-     * functionatliy required to support them, make this check dependent
+     * functionality required to support them, make this check dependent
      * on the actual PM capabilities
      */
     if (WakeTimer) Status = STATUS_TIMER_RESUME_IGNORED;
@@ -675,24 +627,22 @@
     if (NT_SUCCESS(Status))
     {
         /* Lock the Timer */
-        DPRINT("Timer Referencced: 0x%p\n", Timer);
         KeAcquireSpinLock(&Timer->Lock, &OldIrql);
 
         /* Cancel Running Timer */
         if (Timer->ApcAssociated)
         {
-            /*
-             * First, remove it from the Thread's Active List
-             * Get the Thread.
-             */
-            TimerThread = CONTAINING_RECORD(Timer->TimerApc.Thread, ETHREAD, Tcb);
-            DPRINT("Thread already running. Removing from Thread: 0x%p\n", TimerThread);
+            /* Get the Thread. */
+            TimerThread = CONTAINING_RECORD(Timer->TimerApc.Thread,
+                                            ETHREAD,
+                                            Tcb);
 
             /* Lock its active list */
             KeAcquireSpinLockAtDpcLevel(&TimerThread->ActiveTimerListLock);
 
             /* Remove it */
             RemoveEntryList(&TimerThread->ActiveTimerListHead);
+            Timer->ApcAssociated = FALSE;
 
             /* Unlock the list */
             KeReleaseSpinLockFromDpcLevel(&TimerThread->ActiveTimerListLock);
@@ -700,14 +650,12 @@
             /* Cancel the Timer */
             KeCancelTimer(&Timer->KeTimer);
             KeRemoveQueueDpc(&Timer->TimerDpc);
-            KeRemoveQueueApc(&Timer->TimerApc);
-            Timer->ApcAssociated = FALSE;
-            KillTimer = TRUE;
-
-        } else {
-
+            if (KeRemoveQueueApc(&Timer->TimerApc)) DerefsToDo++;
+            DerefsToDo++;
+        }
+        else
+        {
             /* If timer was disabled, we still need to cancel it */
-            DPRINT("No APCs. Simply cancelling\n");
             KeCancelTimer(&Timer->KeTimer);
         }
 
@@ -715,62 +663,60 @@
         State = KeReadStateTimer(&Timer->KeTimer);
 
         /* Handle Wake Timers */
-        DPRINT("Doing Wake Semantics\n");
+        Timer->WakeTimer = WakeTimer;
         KeAcquireSpinLockAtDpcLevel(&ExpWakeListLock);
-        if (WakeTimer && !Timer->WakeTimer)
+        if ((WakeTimer) && !(Timer->WakeTimerListEntry.Flink))
         {
             /* Insert it into the list */
-            Timer->WakeTimer = TRUE;
             InsertTailList(&ExpWakeList, &Timer->WakeTimerListEntry);
         }
-        else if (!WakeTimer && Timer->WakeTimer)
+        else if (!(WakeTimer) && (Timer->WakeTimerListEntry.Flink))
         {
             /* Remove it from the list */
             RemoveEntryList(&Timer->WakeTimerListEntry);
-            Timer->WakeTimer = FALSE;
+            Timer->WakeTimerListEntry.Flink = NULL;
         }
         KeReleaseSpinLockFromDpcLevel(&ExpWakeListLock);
 
         /* Set up the APC Routine if specified */
+        Timer->Period = Period;
         if (TimerApcRoutine)
         {
             /* Initialize the APC */
-            DPRINT("Initializing APC: 0x%p\n", Timer->TimerApc);
             KeInitializeApc(&Timer->TimerApc,
-                            &CurrentThread->Tcb,
+                            &Thread->Tcb,
                             CurrentApcEnvironment,
-                            &ExpTimerApcKernelRoutine,
+                            ExpTimerApcKernelRoutine,
                             (PKRUNDOWN_ROUTINE)NULL,
                             (PKNORMAL_ROUTINE)TimerApcRoutine,
                             PreviousMode,
                             TimerContext);
 
             /* Lock the Thread's Active List and Insert */
-            KeAcquireSpinLockAtDpcLevel(&CurrentThread->ActiveTimerListLock);
-            InsertTailList(&CurrentThread->ActiveTimerListHead,
+            KeAcquireSpinLockAtDpcLevel(&Thread->ActiveTimerListLock);
+            InsertTailList(&Thread->ActiveTimerListHead,
                            &Timer->ActiveTimerListEntry);
-            KeReleaseSpinLockFromDpcLevel(&CurrentThread->ActiveTimerListLock);
-
+            Timer->ApcAssociated = TRUE;
+            KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
+
+            /* One less dereference to do */
+            DerefsToDo--;
          }
 
         /* Enable and Set the Timer */
-        DPRINT("Setting Kernel Timer\n");
         KeSetTimerEx(&Timer->KeTimer,
                      TimerDueTime,
                      Period,
-                     TimerApcRoutine ? &Timer->TimerDpc : 0);
-        Timer->ApcAssociated = TimerApcRoutine ? TRUE : FALSE;
+                     TimerApcRoutine ? &Timer->TimerDpc : NULL);
 
         /* Unlock the Timer */
         KeReleaseSpinLock(&Timer->Lock, OldIrql);
 
         /* Dereference if it was previously enabled */
-        if (!TimerApcRoutine) ObDereferenceObject(Timer);
-        if (KillTimer) ObDereferenceObject(Timer);
-        DPRINT("Finished Setting the Timer\n");
+        if (DerefsToDo) ObDereferenceObjectEx(Timer, DerefsToDo);
 
         /* Make sure it's safe to write to the handle */
-        if(PreviousState != NULL)
+        if (PreviousState)
         {
             _SEH_TRY
             {
@@ -778,7 +724,6 @@
             }
             _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
             {
-                Status = _SEH_GetExceptionCode();
             }
             _SEH_END;
         }
@@ -787,5 +732,3 @@
     /* Return to Caller */
     return Status;
 }
-
-/* EOF */

Modified: branches/ros-branch-0_3_1/reactos/ntoskrnl/include/internal/ex.h
URL: http://svn.reactos.org/svn/reactos/branches/ros-branch-0_3_1/reactos/ntoskrnl/include/internal/ex.h?rev=25731&r1=25730&r2=25731&view=diff
==============================================================================
--- branches/ros-branch-0_3_1/reactos/ntoskrnl/include/internal/ex.h (original)
+++ branches/ros-branch-0_3_1/reactos/ntoskrnl/include/internal/ex.h Mon Feb  5 23:41:00 2007
@@ -21,6 +21,19 @@
 ULONG ExpUnicodeCaseTableDataOffset;
 PVOID ExpNlsSectionPointer;
 
+typedef struct _ETIMER
+{
+    KTIMER KeTimer;
+    KAPC TimerApc;
+    KDPC TimerDpc;
+    LIST_ENTRY ActiveTimerListEntry;
+    KSPIN_LOCK Lock;
+    LONG Period;
+    BOOLEAN ApcAssociated;
+    BOOLEAN WakeTimer;
+    LIST_ENTRY WakeTimerListEntry;
+} ETIMER, *PETIMER;
+
 #define MAX_FAST_REFS           7
 
 #define EX_OBJ_TO_HDR(eob) ((POBJECT_HEADER)((ULONG_PTR)(eob) &                \




More information about the Ros-diffs mailing list