From ce501f07c624ec7f7aeb90b4f18c19a3cdb115d3 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Tue, 16 Jan 2007 01:27:36 +0000 Subject: [PATCH] - Fix insertion of special APC into APC delivery list. - Re-identize some APC code (just formatting change). - Detect APC during GateWait. Previous check scanned for DeferredReady, which is incorrect. - Simplfy KeremovequeueApc to take advantage of the fact RemoveEntryList now returns whether the list is empty or not. svn path=/trunk/; revision=25479 --- reactos/ntoskrnl/ex/timer.c | 15 +++--- reactos/ntoskrnl/ke/apc.c | 96 +++++++++++++------------------------ 2 files changed, 43 insertions(+), 68 deletions(-) diff --git a/reactos/ntoskrnl/ex/timer.c b/reactos/ntoskrnl/ex/timer.c index 63a841c4aba..06121fc69a6 100644 --- a/reactos/ntoskrnl/ex/timer.c +++ b/reactos/ntoskrnl/ex/timer.c @@ -280,7 +280,7 @@ NtCancelTimer(IN HANDLE TimerHandle, PreviousMode, (PVOID*)&Timer, NULL); - if(NT_SUCCESS(Status)) + if (NT_SUCCESS(Status)) { /* Lock the Timer */ KeAcquireSpinLock(&Timer->Lock, &OldIrql); @@ -289,7 +289,9 @@ NtCancelTimer(IN HANDLE TimerHandle, if (Timer->ApcAssociated) { /* Get the Thread. */ - TimerThread = CONTAINING_RECORD(Timer->TimerApc.Thread, ETHREAD, Tcb); + TimerThread = CONTAINING_RECORD(Timer->TimerApc.Thread, + ETHREAD, + Tcb); /* Lock its active list */ KeAcquireSpinLockAtDpcLevel(&TimerThread->ActiveTimerListLock); @@ -403,7 +405,7 @@ NtCreateTimer(OUT PHANDLE TimerHandle, 0, 0, (PVOID*)&Timer); - if(NT_SUCCESS(Status)) + if (NT_SUCCESS(Status)) { /* Initialize the DPC */ KeInitializeDpc(&Timer->TimerDpc, ExpTimerDpcRoutine, Timer); @@ -475,7 +477,7 @@ NtOpenTimer(OUT PHANDLE TimerHandle, DesiredAccess, NULL, &hTimer); - if(NT_SUCCESS(Status)) + if (NT_SUCCESS(Status)) { /* Make sure it's safe to write to the handle */ _SEH_TRY @@ -531,14 +533,15 @@ NtQueryTimer(IN HANDLE TimerHandle, _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) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION); + if (ReturnLength) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION); } _SEH_EXCEPT(_SEH_ExSystemExceptionFilter) { diff --git a/reactos/ntoskrnl/ke/apc.c b/reactos/ntoskrnl/ke/apc.c index 6f198042b8f..85112e3967a 100644 --- a/reactos/ntoskrnl/ke/apc.c +++ b/reactos/ntoskrnl/ke/apc.c @@ -8,6 +8,7 @@ /* INCLUDES *****************************************************************/ +#define NTDDI_VERSION NTDDI_WS03 #include #define NDEBUG #include @@ -89,7 +90,7 @@ KiInsertQueueApc(IN PKAPC Apc, PLIST_ENTRY ListHead, NextEntry; PKAPC QueuedApc; NTSTATUS Status; - BOOLEAN RequestInterrupt; + BOOLEAN RequestInterrupt = FALSE; /* * Check if the caller wanted this APC to use the thread's environment at @@ -137,8 +138,8 @@ KiInsertQueueApc(IN PKAPC Apc, { /* Special APC, find the first Normal APC in the list */ ListHead = &ApcState->ApcListHead[ApcMode]; - NextEntry = ListHead->Flink; - while(NextEntry != ListHead) + NextEntry = ListHead->Blink; + while (NextEntry != ListHead) { /* Get the APC */ QueuedApc = CONTAINING_RECORD(NextEntry, KAPC, ApcListEntry); @@ -147,12 +148,9 @@ KiInsertQueueApc(IN PKAPC Apc, if (QueuedApc->NormalRoutine) break; /* Move to the next APC in the Queue */ - NextEntry = NextEntry->Flink; + NextEntry = NextEntry->Blink; } - /* Move to the APC before this one (ie: the last Special APC) */ - NextEntry = NextEntry->Blink; - /* Insert us here */ InsertHeadList(NextEntry, &Apc->ApcListEntry); } @@ -185,23 +183,8 @@ KiInsertQueueApc(IN PKAPC Apc, /* Acquire the dispatcher lock */ KiAcquireDispatcherLock(); - /* Check if this is a non-kernel mode APC */ - if (ApcMode != KernelMode) - { - /* - * Not a Kernel-Mode APC. Are we waiting in user-mode? - * If so, then are we alertable or already have an APC pending? - */ - if (((Thread->State == Waiting) && (Thread->WaitMode == UserMode)) && - ((Thread->Alertable) || (Thread->ApcState.UserApcPending))) - { - /* Set user-mode APC pending */ - Thread->ApcState.UserApcPending = TRUE; - Status = STATUS_USER_APC; - goto Unwait; - } - } - else + /* Check if this is a kernel-mode APC */ + if (ApcMode == KernelMode) { /* Kernel-mode APC, set us pending */ Thread->ApcState.KernelApcPending = TRUE; @@ -211,45 +194,37 @@ KiInsertQueueApc(IN PKAPC Apc, { /* The thread is running, so remember to send a request */ RequestInterrupt = TRUE; -#ifndef CONFIG_SMP - /* On UP systems, request it immediately */ - HalRequestSoftwareInterrupt(APC_LEVEL); -#endif } - else + else if ((Thread->State == Waiting) && + (Thread->WaitIrql == PASSIVE_LEVEL) && + !(Thread->SpecialApcDisable) && + (!(Apc->NormalRoutine) || + (!(Thread->KernelApcDisable) && + !(Thread->ApcState.KernelApcInProgress)))) { - /* - * If the thread is Waiting at PASSIVE_LEVEL AND - * Special APCs are not disabled AND - * He is a Normal APC AND - * Kernel APCs are not disabled AND - * Kernel APC is not pending OR - * He is a Special APC THEN - * Unwait thread with STATUS_KERNEL_APC - */ - if ((Thread->State == Waiting) && - (Thread->WaitIrql == PASSIVE_LEVEL) && - !(Thread->SpecialApcDisable) && - (!(Apc->NormalRoutine) || - (!(Thread->KernelApcDisable) && - !(Thread->ApcState.KernelApcInProgress)))) - { - /* We'll unwait with this status */ - Status = STATUS_KERNEL_APC; + /* We'll unwait with this status */ + Status = STATUS_KERNEL_APC; - /* Wake up the thread */ + /* Wake up the thread */ Unwait: - KiUnwaitThread(Thread, Status, PriorityBoost); - } - else - { - /* Check if the thread is in a deferred ready state */ - if (Thread->State == DeferredReady) - { - /* FIXME: TODO in new scheduler */ - } - } + KiUnwaitThread(Thread, Status, PriorityBoost); } + else if (Thread->State == GateWait) + { + /* We were in a gate wait. FIXME: Handle this */ + DPRINT1("Not yet supported -- Report this to Alex\n"); + KEBUGCHECK(0); + } + } + else if ((Thread->State == Waiting) && + (Thread->WaitMode == UserMode) && + ((Thread->Alertable) || + (Thread->ApcState.UserApcPending))) + { + /* Set user-mode APC pending */ + Thread->ApcState.UserApcPending = TRUE; + Status = STATUS_USER_APC; + goto Unwait; } /* Release dispatcher lock */ @@ -891,10 +866,7 @@ KeRemoveQueueApc(IN PKAPC Apc) /* Acquire the dispatcher lock and remove it from the list */ KiAcquireDispatcherLockAtDpcLevel(); - RemoveEntryList(&Apc->ApcListEntry); - - /* If the Queue is completely empty, then no more APCs are pending */ - if (IsListEmpty(&ApcState->ApcListHead[Apc->ApcMode])) + if (RemoveEntryList(&ApcState->ApcListHead[Apc->ApcMode])) { /* Set the correct state based on the APC Mode */ if (Apc->ApcMode == KernelMode)