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?r…
==============================================================================
--- 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?…
==============================================================================
--- 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/…
==============================================================================
--- 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=453…
==============================================================================
--- 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);