mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 08:32:58 +00:00
- 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:
parent
23ffe8c3f8
commit
d5c7b7443b
1 changed files with 28 additions and 38 deletions
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue