Author: sir_richard Date: Thu Jan 28 21:45:45 2010 New Revision: 45301
URL: http://svn.reactos.org/svn/reactos?rev=45301&view=rev Log: [PERF]: Optimize nested interrupt cases (where a pending interrupt exists at the end of a software or system interrupt) just like the old HAL did, by jumping into a second-level handler and completing the outer trap frame instead of the nested trap frame. This saves a lot of cycles in those cases, and they do happen quite often (pending DPC at the end of an interrupt, for example). [NTOS/HAL]: Rework respective code to handle this by using the VDM Alert field in the KPCR.
Modified: trunk/reactos/hal/halx86/generic/pic.c trunk/reactos/hal/halx86/include/halp.h trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S trunk/reactos/ntoskrnl/ke/time.c
Modified: trunk/reactos/hal/halx86/generic/pic.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/generic/pic.c?re... ============================================================================== --- trunk/reactos/hal/halx86/generic/pic.c [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/generic/pic.c [iso-8859-1] Thu Jan 28 21:45:45 2010 @@ -205,6 +205,15 @@ HalpDispatchInterrupt };
+/* Handlers for pending software interrupts when we already have a trap frame*/ +PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY SWInterruptHandlerTable2[3] = +{ + (PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY)KiUnexpectedInterrupt, + HalpApcInterrupt2ndEntry, + HalpDispatchInterrupt2ndEntry +}; + + USHORT HalpEisaELCR;
/* FUNCTIONS ******************************************************************/ @@ -552,9 +561,7 @@
/* Check for pending software interrupts and compare with current IRQL */ PendingIrql = SWInterruptLookUpTable[Pcr->IRR]; - - /* NOTE: We can do better! We need to support "jumping" a frame for nested cases! */ - if (PendingIrql > OldIrql) SWInterruptHandlerTable[PendingIrql](); + if (PendingIrql > OldIrql) HalpNestedTrap(PendingIrql); }
/* INTERRUPT DISMISSAL FUNCTIONS **********************************************/ @@ -811,18 +818,56 @@
/* Check for pending software interrupts and compare with current IRQL */ PendingIrql = SWInterruptLookUpTable[Pcr->IRR]; - if (PendingIrql > OldIrql) SWInterruptHandlerTable[PendingIrql](); + if (PendingIrql > OldIrql) HalpNestedTrap(PendingIrql); }
/* SOFTWARE INTERRUPT TRAPS ***************************************************/
VOID +FORCEINLINE +DECLSPEC_NORETURN +_HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) +{ + KIRQL CurrentIrql; + PKPCR Pcr = KeGetPcr(); + + /* Save the current IRQL and update it */ + CurrentIrql = Pcr->Irql; + Pcr->Irql = APC_LEVEL; + + /* Remove DPC from IRR */ + Pcr->IRR &= ~(1 << APC_LEVEL); + + /* Enable interrupts and call the kernel's APC interrupt handler */ + _enable(); + KiDeliverApc(((KiUserTrap(TrapFrame)) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) ? + UserMode : KernelMode, + NULL, + TrapFrame); + + /* Disable interrupts and end the interrupt */ + _disable(); + Pcr->VdmAlert = (ULONG_PTR)TrapFrame; + HalpEndSoftwareInterrupt(CurrentIrql); + + /* Exit the interrupt */ + KiEoiHelper(TrapFrame); +} + +VOID FASTCALL +DECLSPEC_NORETURN +HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame) +{ + /* Do the work */ + _HalpApcInterruptHandler(TrapFrame); +} + +VOID +FASTCALL +DECLSPEC_NORETURN HalpApcInterruptHandler(IN PKTRAP_FRAME TrapFrame) { - KIRQL CurrentIrql; - PKPCR Pcr = KeGetPcr(); - /* Set up a fake INT Stack */ TrapFrame->EFlags = __readeflags(); TrapFrame->SegCs = KGDT_R0_CODE; @@ -831,35 +876,52 @@ /* Build the trap frame */ KiEnterInterruptTrap(TrapFrame);
+ /* Do the work */ + _HalpApcInterruptHandler(TrapFrame); +} + +VOID +FORCEINLINE +DECLSPEC_NORETURN +_HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame) +{ + KIRQL CurrentIrql; + PKPCR Pcr = KeGetPcr(); + /* Save the current IRQL and update it */ CurrentIrql = Pcr->Irql; - Pcr->Irql = APC_LEVEL; + Pcr->Irql = DISPATCH_LEVEL;
/* Remove DPC from IRR */ - Pcr->IRR &= ~(1 << APC_LEVEL); - - /* Enable interrupts and call the kernel's APC interrupt handler */ + Pcr->IRR &= ~(1 << DISPATCH_LEVEL); + + /* Enable interrupts and call the kernel's DPC interrupt handler */ _enable(); - KiDeliverApc(((KiUserTrap(TrapFrame)) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) ? - UserMode : KernelMode, - NULL, - TrapFrame); - + KiDispatchInterrupt(); + /* Disable interrupts and end the interrupt */ _disable(); + Pcr->VdmAlert = (ULONG_PTR)TrapFrame; HalpEndSoftwareInterrupt(CurrentIrql);
/* Exit the interrupt */ - KiEoiHelper(TrapFrame); + KiEoiHelper(TrapFrame); }
VOID FASTCALL +DECLSPEC_NORETURN +HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame) +{ + /* Do the work */ + _HalpDispatchInterruptHandler(TrapFrame); +} + +VOID +FASTCALL +DECLSPEC_NORETURN HalpDispatchInterruptHandler(IN PKTRAP_FRAME TrapFrame) -{ - KIRQL CurrentIrql; - PKPCR Pcr = KeGetPcr(); - +{ /* Set up a fake INT Stack */ TrapFrame->EFlags = __readeflags(); TrapFrame->SegCs = KGDT_R0_CODE; @@ -868,23 +930,8 @@ /* Build the trap frame */ KiEnterInterruptTrap(TrapFrame);
- /* Save the current IRQL and update it */ - CurrentIrql = Pcr->Irql; - Pcr->Irql = DISPATCH_LEVEL; - - /* Remove DPC from IRR */ - Pcr->IRR &= ~(1 << DISPATCH_LEVEL); - - /* Enable interrupts and call the kernel's DPC interrupt handler */ - _enable(); - KiDispatchInterrupt(); - - /* Disable interrupts and end the interrupt */ - _disable(); - HalpEndSoftwareInterrupt(CurrentIrql); - - /* Exit the interrupt */ - KiEoiHelper(TrapFrame); + /* Do the work */ + _HalpDispatchInterruptHandler(TrapFrame); }
KiTrap(HalpApcInterrupt, KI_SOFTWARE_TRAP);
Modified: trunk/reactos/hal/halx86/include/halp.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/hal/halx86/include/halp.h?r... ============================================================================== --- trunk/reactos/hal/halx86/include/halp.h [iso-8859-1] (original) +++ trunk/reactos/hal/halx86/include/halp.h [iso-8859-1] Thu Jan 28 21:45:45 2010 @@ -22,6 +22,19 @@ ULONG Prefix; } HAL_BIOS_FRAME, *PHAL_BIOS_FRAME;
+typedef +VOID +(*PHAL_SW_INTERRUPT_HANDLER)( + VOID +); + +typedef +FASTCALL +VOID +(*PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY)( + IN PKTRAP_FRAME TrapFrame +); + #define HAL_APC_REQUEST 0 #define HAL_DPC_REQUEST 1
@@ -96,6 +109,28 @@ : [v] "i"(Alignment), [i] "i"(Size) ); +} + +// +// Nested Trap Trampoline +// +VOID +DECLSPEC_NORETURN +FORCEINLINE +HalpNestedTrap(IN KIRQL PendingIrql) +{ + /* Use the second interrupt handler table */ + extern PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY SWInterruptHandlerTable2[3]; + __asm__ __volatile__ + ( + "movl %c[t], %%ecx\n" + "jmp *%0\n" + : + : "im"(SWInterruptHandlerTable2[PendingIrql]), + [t] "i"(&PCR->VdmAlert) + : "%esp" + ); + UNREACHABLE; }
// @@ -432,12 +467,6 @@ } PIC_MASK, *PPIC_MASK;
typedef -VOID -(*PHAL_SW_INTERRUPT_HANDLER)( - VOID -); - -typedef BOOLEAN __attribute__((regparm(3))) (*PHAL_DISMISS_INTERRUPT)( @@ -531,6 +560,8 @@ VOID NTAPI HalpInitializePICs(IN BOOLEAN EnableInterrupts); VOID HalpApcInterrupt(VOID); VOID HalpDispatchInterrupt(VOID); +VOID FASTCALL HalpApcInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame); +VOID FASTCALL HalpDispatchInterrupt2ndEntry(IN PKTRAP_FRAME TrapFrame);
/* timer.c */ VOID NTAPI HalpInitializeClock(VOID);
Modified: trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/i386/asmmacro.S [iso-8859-1] Thu Jan 28 21:45:45 2010 @@ -1452,6 +1452,8 @@ cli
/* End the interrupt and do EOI */ + lea eax, [esp+8] + mov PCR[KPCR_VDM_ALERT], eax call _HalEndSystemInterrupt@8 jmp _Kei386EoiHelper@0 .endif
Modified: trunk/reactos/ntoskrnl/ke/time.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/time.c?rev=4530... ============================================================================== --- trunk/reactos/ntoskrnl/ke/time.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/ke/time.c [iso-8859-1] Thu Jan 28 21:45:45 2010 @@ -112,6 +112,9 @@ Prcb->InterruptCount++; }
+ /* Save the nested trap frame address */ + KeGetPcr()->VdmAlert = (ULONG_PTR)TrapFrame; + /* Disable interrupts and end the interrupt */ _disable(); HalEndSystemInterrupt(Irql, CLOCK2_LEVEL);