- 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.

svn path=/trunk/; revision=14443
This commit is contained in:
Hartmut Birr 2005-04-02 15:55:15 +00:00
parent 23ffe8c3f8
commit d5c7b7443b

View file

@ -11,6 +11,8 @@
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
/* TYPES ********************************************************************/ /* TYPES ********************************************************************/
@ -22,7 +24,6 @@ typedef struct _ETIMER {
KDPC TimerDpc; KDPC TimerDpc;
LIST_ENTRY ActiveTimerListEntry; LIST_ENTRY ActiveTimerListEntry;
KSPIN_LOCK Lock; KSPIN_LOCK Lock;
LONG Period;
BOOLEAN ApcAssociated; BOOLEAN ApcAssociated;
BOOLEAN WakeTimer; BOOLEAN WakeTimer;
LIST_ENTRY WakeTimerListEntry; LIST_ENTRY WakeTimerListEntry;
@ -60,54 +61,46 @@ ExTimerRundown(VOID)
PETHREAD Thread = PsGetCurrentThread(); PETHREAD Thread = PsGetCurrentThread();
KIRQL OldIrql; KIRQL OldIrql;
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
BOOLEAN KillTimer = FALSE;
PETIMER Timer; PETIMER Timer;
/* Lock the Thread's Active Timer List*/ /* Lock the Thread's Active Timer List*/
KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql); KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql);
/* Loop through all the timers */ while (!IsListEmpty(&Thread->ActiveTimerListHead))
CurrentEntry = Thread->ActiveTimerListHead.Flink; {
while (CurrentEntry != &Thread->ActiveTimerListHead) {
/* Remove a Timer */
CurrentEntry = RemoveTailList(&Thread->ActiveTimerListHead);
/* Get the Timer */ /* 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); DPRINT("Timer, ThreadList: %x, %x\n", Timer, Thread);
/* Unlock the list */ /* Unlock the list */
KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql); KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
/* Lock the Timer */ /* Lock the Timer */
KeAcquireSpinLock(&Timer->Lock, &OldIrql); KeAcquireSpinLockAtDpcLevel(&Timer->Lock);
/* Relock the active list */ ASSERT (&Thread->Tcb == Timer->TimerApc.Thread);
KeAcquireSpinLockAtDpcLevel(&Thread->ActiveTimerListLock);
/* Make sure it's associated to us */ KeCancelTimer(&Timer->KeTimer);
if ((Timer->ApcAssociated) && (&Thread->Tcb == Timer->TimerApc.Thread)) { KeRemoveQueueDpc(&Timer->TimerDpc);
KeRemoveQueueApc(&Timer->TimerApc);
/* 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;
}
/* Unlock the list */
KeReleaseSpinLockFromDpcLevel(&Thread->ActiveTimerListLock);
/* Unlock the Timer */ /* Unlock the Timer */
KeReleaseSpinLock(&Timer->Lock, OldIrql); KeReleaseSpinLock(&Timer->Lock, OldIrql);
/* Dereference it, if needed */ /* Dereference it, if needed */
if (KillTimer) ObDereferenceObject(Timer); ObDereferenceObject(Timer);
/* Loop again */ /* Loop again */
KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql); KeAcquireSpinLock(&Thread->ActiveTimerListLock, &OldIrql);
CurrentEntry = CurrentEntry->Flink;
} }
KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql); KeReleaseSpinLock(&Thread->ActiveTimerListLock, OldIrql);
@ -126,11 +119,12 @@ ExpDeleteTimer(PVOID ObjectBody)
KeAcquireSpinLock(&ExpWakeListLock, &OldIrql); KeAcquireSpinLock(&ExpWakeListLock, &OldIrql);
/* Check if it has a Wait List */ /* Check if it has a Wait List */
if (!IsListEmpty(&Timer->WakeTimerListEntry)) { if (Timer->WakeTimer) {
/* Remove it from the Wait List */ /* Remove it from the Wait List */
DPRINT("Removing wake list\n"); DPRINT("Removing wake list\n");
RemoveEntryList(&Timer->WakeTimerListEntry); RemoveEntryList(&Timer->WakeTimerListEntry);
Timer->WakeTimer = FALSE;
} }
/* Release the Wake List */ /* Release the Wake List */
@ -202,7 +196,7 @@ ExpTimerApcKernelRoutine(PKAPC Apc,
*/ */
if ((Timer->ApcAssociated) && if ((Timer->ApcAssociated) &&
(&CurrentThread->Tcb == Timer->TimerApc.Thread) && (&CurrentThread->Tcb == Timer->TimerApc.Thread) &&
(!Timer->Period)) { (!Timer->KeTimer.Period)) {
/* Remove it from the Active Timers List */ /* Remove it from the Active Timers List */
DPRINT("Removing Timer\n"); DPRINT("Removing Timer\n");
@ -433,7 +427,6 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
/* Set Initial State */ /* Set Initial State */
Timer->ApcAssociated = FALSE; Timer->ApcAssociated = FALSE;
InitializeListHead(&Timer->WakeTimerListEntry);
Timer->WakeTimer = FALSE; Timer->WakeTimer = FALSE;
/* Insert the Timer */ /* Insert the Timer */
@ -691,16 +684,16 @@ NtSetTimer(IN HANDLE TimerHandle,
/* Handle Wake Timers */ /* Handle Wake Timers */
DPRINT("Doing Wake Semantics\n"); DPRINT("Doing Wake Semantics\n");
KeAcquireSpinLockAtDpcLevel(&ExpWakeListLock); KeAcquireSpinLockAtDpcLevel(&ExpWakeListLock);
if (WakeTimer) { if (WakeTimer && !Timer->WakeTimer) {
/* Insert it into the list */ /* Insert it into the list */
Timer->WakeTimer = TRUE;
InsertTailList(&ExpWakeList, &Timer->WakeTimerListEntry); InsertTailList(&ExpWakeList, &Timer->WakeTimerListEntry);
} else if (!WakeTimer && Timer->WakeTimer) {
} else {
/* Remove it from the list */ /* Remove it from the list */
RemoveEntryList(&Timer->WakeTimerListEntry); RemoveEntryList(&Timer->WakeTimerListEntry);
Timer->WakeTimerListEntry.Flink = NULL; Timer->WakeTimer = FALSE;
} }
KeReleaseSpinLockFromDpcLevel(&ExpWakeListLock); KeReleaseSpinLockFromDpcLevel(&ExpWakeListLock);
@ -740,9 +733,6 @@ NtSetTimer(IN HANDLE TimerHandle,
/* Dereference the Object */ /* Dereference the Object */
ObDereferenceObject(Timer); ObDereferenceObject(Timer);
/* Unlock the Timer */
KeReleaseSpinLock(&Timer->Lock, OldIrql);
/* Dereference if it was previously enabled */ /* Dereference if it was previously enabled */
if (!TimerApcRoutine) ObDereferenceObject(Timer); if (!TimerApcRoutine) ObDereferenceObject(Timer);
if (KillTimer) ObDereferenceObject(Timer); if (KillTimer) ObDereferenceObject(Timer);