Make KeFlushQueueApc return a standard cyclic linked list to save a few CPU cycles.

svn path=/trunk/; revision=17408
This commit is contained in:
Filip Navara 2005-08-16 00:01:42 +00:00
parent 19f76e91c6
commit 51cbaf1419
2 changed files with 38 additions and 39 deletions

View file

@ -469,29 +469,23 @@ KeFlushQueueApc(IN PKTHREAD Thread,
{ {
KIRQL OldIrql; KIRQL OldIrql;
PKAPC Apc; PKAPC Apc;
PLIST_ENTRY ApcEntry, CurrentEntry; PLIST_ENTRY FirstEntry, CurrentEntry;
/* Lock the Dispatcher Database and APC Queue */ /* Lock the Dispatcher Database and APC Queue */
OldIrql = KeAcquireDispatcherDatabaseLock(); OldIrql = KeAcquireDispatcherDatabaseLock();
KeAcquireSpinLockAtDpcLevel(&Thread->ApcQueueLock); KeAcquireSpinLockAtDpcLevel(&Thread->ApcQueueLock);
ApcEntry = CurrentEntry = NULL; if (IsListEmpty(&Thread->ApcState.ApcListHead[PreviousMode])) {
while (!IsListEmpty(&Thread->ApcState.ApcListHead[PreviousMode])) FirstEntry = NULL;
{ } else {
if (ApcEntry == NULL) FirstEntry = Thread->ApcState.ApcListHead[PreviousMode].Flink;
{ RemoveEntryList(&Thread->ApcState.ApcListHead[PreviousMode]);
ApcEntry = CurrentEntry = RemoveHeadList(&Thread->ApcState.ApcListHead[PreviousMode]); CurrentEntry = FirstEntry;
} do {
else
{
CurrentEntry->Flink = RemoveHeadList(&Thread->ApcState.ApcListHead[PreviousMode]);
CurrentEntry = CurrentEntry->Flink;
}
CurrentEntry->Flink = NULL;
/* Get the APC */
Apc = CONTAINING_RECORD(CurrentEntry, KAPC, ApcListEntry); Apc = CONTAINING_RECORD(CurrentEntry, KAPC, ApcListEntry);
Apc->Inserted = FALSE; Apc->Inserted = FALSE;
CurrentEntry = CurrentEntry->Flink;
} while (CurrentEntry != FirstEntry);
} }
/* Release the locks */ /* Release the locks */
@ -499,7 +493,7 @@ KeFlushQueueApc(IN PKTHREAD Thread,
KeReleaseDispatcherDatabaseLock(OldIrql); KeReleaseDispatcherDatabaseLock(OldIrql);
/* Return the first entry */ /* Return the first entry */
return ApcEntry; return FirstEntry;
} }
/*++ /*++

View file

@ -214,7 +214,7 @@ PspExitThread(NTSTATUS ExitStatus)
PTERMINATION_PORT TerminationPort; PTERMINATION_PORT TerminationPort;
PTEB Teb; PTEB Teb;
KIRQL oldIrql; KIRQL oldIrql;
PLIST_ENTRY ApcEntry; PLIST_ENTRY FirstEntry, CurrentEntry;
PKAPC Apc; PKAPC Apc;
DPRINT("PspExitThread(ExitStatus %x), Current: 0x%x\n", ExitStatus, PsGetCurrentThread()); DPRINT("PspExitThread(ExitStatus %x), Current: 0x%x\n", ExitStatus, PsGetCurrentThread());
@ -340,14 +340,17 @@ PspExitThread(NTSTATUS ExitStatus)
KeDisableThreadApcQueueing(&CurrentThread->Tcb); KeDisableThreadApcQueueing(&CurrentThread->Tcb);
/* Flush the User APCs */ /* Flush the User APCs */
ApcEntry = KeFlushQueueApc(&CurrentThread->Tcb, UserMode); FirstEntry = KeFlushQueueApc(&CurrentThread->Tcb, UserMode);
while(ApcEntry) if (FirstEntry != NULL)
{
CurrentEntry = FirstEntry;
do
{ {
/* Get the APC */ /* Get the APC */
Apc = CONTAINING_RECORD(ApcEntry, KAPC, ApcListEntry); Apc = CONTAINING_RECORD(CurrentEntry, KAPC, ApcListEntry);
/* Move to the next one */ /* Move to the next one */
ApcEntry = ApcEntry->Flink; CurrentEntry = CurrentEntry->Flink;
/* Rundown the APC or de-allocate it */ /* Rundown the APC or de-allocate it */
if (Apc->RundownRoutine) if (Apc->RundownRoutine)
@ -361,16 +364,18 @@ PspExitThread(NTSTATUS ExitStatus)
ExFreePool(Apc); ExFreePool(Apc);
} }
} }
while (CurrentEntry != FirstEntry);
}
/* Call the Lego routine */ /* Call the Lego routine */
if (CurrentThread->Tcb.LegoData) PspRunLegoRoutine(&CurrentThread->Tcb); if (CurrentThread->Tcb.LegoData) PspRunLegoRoutine(&CurrentThread->Tcb);
/* Flush the APC queue, which should be empty */ /* Flush the APC queue, which should be empty */
if ((ApcEntry = KeFlushQueueApc(&CurrentThread->Tcb, KernelMode))) if ((FirstEntry = KeFlushQueueApc(&CurrentThread->Tcb, KernelMode)))
{ {
/* Bugcheck time */ /* Bugcheck time */
KEBUGCHECKEX(KERNEL_APC_PENDING_DURING_EXIT, KEBUGCHECKEX(KERNEL_APC_PENDING_DURING_EXIT,
(ULONG_PTR)ApcEntry, (ULONG_PTR)FirstEntry,
CurrentThread->Tcb.KernelApcDisable, CurrentThread->Tcb.KernelApcDisable,
oldIrql, oldIrql,
0); 0);