mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
Make KeFlushQueueApc return a standard cyclic linked list to save a few CPU cycles.
svn path=/trunk/; revision=17408
This commit is contained in:
parent
19f76e91c6
commit
51cbaf1419
2 changed files with 38 additions and 39 deletions
|
@ -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
|
Apc = CONTAINING_RECORD(CurrentEntry, KAPC, ApcListEntry);
|
||||||
{
|
Apc->Inserted = FALSE;
|
||||||
CurrentEntry->Flink = RemoveHeadList(&Thread->ApcState.ApcListHead[PreviousMode]);
|
CurrentEntry = CurrentEntry->Flink;
|
||||||
CurrentEntry = CurrentEntry->Flink;
|
} while (CurrentEntry != FirstEntry);
|
||||||
}
|
|
||||||
CurrentEntry->Flink = NULL;
|
|
||||||
|
|
||||||
/* Get the APC */
|
|
||||||
Apc = CONTAINING_RECORD(CurrentEntry, KAPC, ApcListEntry);
|
|
||||||
Apc->Inserted = FALSE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*++
|
/*++
|
||||||
|
|
|
@ -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,37 +340,42 @@ 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)
|
||||||
{
|
{
|
||||||
/* Get the APC */
|
CurrentEntry = FirstEntry;
|
||||||
Apc = CONTAINING_RECORD(ApcEntry, KAPC, ApcListEntry);
|
do
|
||||||
|
{
|
||||||
|
/* Get the APC */
|
||||||
|
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)
|
||||||
{
|
{
|
||||||
/* Call its own routine */
|
/* Call its own routine */
|
||||||
(Apc->RundownRoutine)(Apc);
|
(Apc->RundownRoutine)(Apc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Do it ourselves */
|
/* Do it ourselves */
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue