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/includ…
==============================================================================
--- 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/ntoskr…
==============================================================================
--- 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(a)relsoft.net)
- * David Welch (welch(a)mcmail.com)
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu(a)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/ntoskr…
==============================================================================
--- 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) & \