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

View file

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