Make KeFlushQueueApc return a standard cyclic linked list to save a few CPU cycles. Modified: trunk/reactos/ntoskrnl/ke/apc.c Modified: trunk/reactos/ntoskrnl/ps/kill.c _____
Modified: trunk/reactos/ntoskrnl/ke/apc.c --- trunk/reactos/ntoskrnl/ke/apc.c 2005-08-15 22:44:32 UTC (rev 17407) +++ trunk/reactos/ntoskrnl/ke/apc.c 2005-08-16 00:01:42 UTC (rev 17408) @@ -469,29 +469,23 @@
{ 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 @@ KeReleaseDispatcherDatabaseLock(OldIrql);
/* Return the first entry */ - return ApcEntry; + return FirstEntry; }
/*++ _____
Modified: trunk/reactos/ntoskrnl/ps/kill.c --- trunk/reactos/ntoskrnl/ps/kill.c 2005-08-15 22:44:32 UTC (rev 17407) +++ trunk/reactos/ntoskrnl/ps/kill.c 2005-08-16 00:01:42 UTC (rev 17408) @@ -214,7 +214,7 @@
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 @@ 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);