- 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
This commit is contained in:
Alex Ionescu 2007-01-16 01:27:36 +00:00
parent 5b7abf2e8a
commit ce501f07c6
2 changed files with 43 additions and 68 deletions

View file

@ -280,7 +280,7 @@ NtCancelTimer(IN HANDLE TimerHandle,
PreviousMode, PreviousMode,
(PVOID*)&Timer, (PVOID*)&Timer,
NULL); NULL);
if(NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Lock the Timer */ /* Lock the Timer */
KeAcquireSpinLock(&Timer->Lock, &OldIrql); KeAcquireSpinLock(&Timer->Lock, &OldIrql);
@ -289,7 +289,9 @@ NtCancelTimer(IN HANDLE TimerHandle,
if (Timer->ApcAssociated) if (Timer->ApcAssociated)
{ {
/* Get the Thread. */ /* Get the Thread. */
TimerThread = CONTAINING_RECORD(Timer->TimerApc.Thread, ETHREAD, Tcb); TimerThread = CONTAINING_RECORD(Timer->TimerApc.Thread,
ETHREAD,
Tcb);
/* Lock its active list */ /* Lock its active list */
KeAcquireSpinLockAtDpcLevel(&TimerThread->ActiveTimerListLock); KeAcquireSpinLockAtDpcLevel(&TimerThread->ActiveTimerListLock);
@ -403,7 +405,7 @@ NtCreateTimer(OUT PHANDLE TimerHandle,
0, 0,
0, 0,
(PVOID*)&Timer); (PVOID*)&Timer);
if(NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Initialize the DPC */ /* Initialize the DPC */
KeInitializeDpc(&Timer->TimerDpc, ExpTimerDpcRoutine, Timer); KeInitializeDpc(&Timer->TimerDpc, ExpTimerDpcRoutine, Timer);
@ -475,7 +477,7 @@ NtOpenTimer(OUT PHANDLE TimerHandle,
DesiredAccess, DesiredAccess,
NULL, NULL,
&hTimer); &hTimer);
if(NT_SUCCESS(Status)) if (NT_SUCCESS(Status))
{ {
/* Make sure it's safe to write to the handle */ /* Make sure it's safe to write to the handle */
_SEH_TRY _SEH_TRY
@ -531,14 +533,15 @@ NtQueryTimer(IN HANDLE TimerHandle,
_SEH_TRY _SEH_TRY
{ {
/* Return the remaining time, corrected */ /* Return the remaining time, corrected */
BasicInfo->TimeRemaining.QuadPart = Timer->KeTimer.DueTime.QuadPart - BasicInfo->TimeRemaining.QuadPart = Timer->
KeTimer.DueTime.QuadPart -
KeQueryInterruptTime(); KeQueryInterruptTime();
/* Return the current state */ /* Return the current state */
BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer); BasicInfo->SignalState = KeReadStateTimer(&Timer->KeTimer);
/* Return the buffer length if requested */ /* Return the buffer length if requested */
if(ReturnLength) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION); if (ReturnLength) *ReturnLength = sizeof(TIMER_BASIC_INFORMATION);
} }
_SEH_EXCEPT(_SEH_ExSystemExceptionFilter) _SEH_EXCEPT(_SEH_ExSystemExceptionFilter)
{ {

View file

@ -8,6 +8,7 @@
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
#define NTDDI_VERSION NTDDI_WS03
#include <ntoskrnl.h> #include <ntoskrnl.h>
#define NDEBUG #define NDEBUG
#include <internal/debug.h> #include <internal/debug.h>
@ -89,7 +90,7 @@ KiInsertQueueApc(IN PKAPC Apc,
PLIST_ENTRY ListHead, NextEntry; PLIST_ENTRY ListHead, NextEntry;
PKAPC QueuedApc; PKAPC QueuedApc;
NTSTATUS Status; NTSTATUS Status;
BOOLEAN RequestInterrupt; BOOLEAN RequestInterrupt = FALSE;
/* /*
* Check if the caller wanted this APC to use the thread's environment at * 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 */ /* Special APC, find the first Normal APC in the list */
ListHead = &ApcState->ApcListHead[ApcMode]; ListHead = &ApcState->ApcListHead[ApcMode];
NextEntry = ListHead->Flink; NextEntry = ListHead->Blink;
while(NextEntry != ListHead) while (NextEntry != ListHead)
{ {
/* Get the APC */ /* Get the APC */
QueuedApc = CONTAINING_RECORD(NextEntry, KAPC, ApcListEntry); QueuedApc = CONTAINING_RECORD(NextEntry, KAPC, ApcListEntry);
@ -147,12 +148,9 @@ KiInsertQueueApc(IN PKAPC Apc,
if (QueuedApc->NormalRoutine) break; if (QueuedApc->NormalRoutine) break;
/* Move to the next APC in the Queue */ /* 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 */ /* Insert us here */
InsertHeadList(NextEntry, &Apc->ApcListEntry); InsertHeadList(NextEntry, &Apc->ApcListEntry);
} }
@ -185,23 +183,8 @@ KiInsertQueueApc(IN PKAPC Apc,
/* Acquire the dispatcher lock */ /* Acquire the dispatcher lock */
KiAcquireDispatcherLock(); KiAcquireDispatcherLock();
/* Check if this is a non-kernel mode APC */ /* Check if this is a kernel-mode APC */
if (ApcMode != KernelMode) 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
{ {
/* Kernel-mode APC, set us pending */ /* Kernel-mode APC, set us pending */
Thread->ApcState.KernelApcPending = TRUE; Thread->ApcState.KernelApcPending = TRUE;
@ -211,45 +194,37 @@ KiInsertQueueApc(IN PKAPC Apc,
{ {
/* The thread is running, so remember to send a request */ /* The thread is running, so remember to send a request */
RequestInterrupt = TRUE; 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))))
{ {
/* /* We'll unwait with this status */
* If the thread is Waiting at PASSIVE_LEVEL AND Status = STATUS_KERNEL_APC;
* 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;
/* Wake up the thread */ /* Wake up the thread */
Unwait: Unwait:
KiUnwaitThread(Thread, Status, PriorityBoost); KiUnwaitThread(Thread, Status, PriorityBoost);
}
else
{
/* Check if the thread is in a deferred ready state */
if (Thread->State == DeferredReady)
{
/* FIXME: TODO in new scheduler */
}
}
} }
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 */ /* Release dispatcher lock */
@ -891,10 +866,7 @@ KeRemoveQueueApc(IN PKAPC Apc)
/* Acquire the dispatcher lock and remove it from the list */ /* Acquire the dispatcher lock and remove it from the list */
KiAcquireDispatcherLockAtDpcLevel(); KiAcquireDispatcherLockAtDpcLevel();
RemoveEntryList(&Apc->ApcListEntry); if (RemoveEntryList(&ApcState->ApcListHead[Apc->ApcMode]))
/* If the Queue is completely empty, then no more APCs are pending */
if (IsListEmpty(&ApcState->ApcListHead[Apc->ApcMode]))
{ {
/* Set the correct state based on the APC Mode */ /* Set the correct state based on the APC Mode */
if (Apc->ApcMode == KernelMode) if (Apc->ApcMode == KernelMode)