mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 10:35:28 +00:00
- 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:
parent
5b7abf2e8a
commit
ce501f07c6
2 changed files with 43 additions and 68 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue