From ba1fac29997981312eea724fc91ef4822894fa0f Mon Sep 17 00:00:00 2001 From: Thomas Faber Date: Tue, 10 May 2016 15:03:56 +0000 Subject: [PATCH] [HAL] - Create a wrapper version of HalpEndSoftwareInterrupt that frees its stack before calling the noreturn version of the next software interrupt handler. Fixes excessive stack usage when DPCs are queued in quick succession. CORE-11123 #resolve svn path=/trunk/; revision=71307 --- reactos/hal/halx86/pic.cmake | 3 ++- reactos/hal/halx86/up/pic.S | 48 ++++++++++++++++++++++++++++++++++++ reactos/hal/halx86/up/pic.c | 24 ++++++++++++------ 3 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 reactos/hal/halx86/up/pic.S diff --git a/reactos/hal/halx86/pic.cmake b/reactos/hal/halx86/pic.cmake index 9a470ccad1c..30737d20da9 100644 --- a/reactos/hal/halx86/pic.cmake +++ b/reactos/hal/halx86/pic.cmake @@ -1,7 +1,8 @@ list(APPEND HAL_PIC_ASM_SOURCE generic/systimer.S - generic/trap.S) + generic/trap.S + up/pic.S) list(APPEND HAL_PIC_SOURCE generic/profil.c diff --git a/reactos/hal/halx86/up/pic.S b/reactos/hal/halx86/up/pic.S new file mode 100644 index 00000000000..c9bd891407b --- /dev/null +++ b/reactos/hal/halx86/up/pic.S @@ -0,0 +1,48 @@ +/* + * FILE: hal/halx86/up/pic.S + * COPYRIGHT: See COPYING in the top level directory + * PURPOSE: HAL PIC Management and Control Code + * PROGRAMMER: Thomas Faber (thomas.faber@reactos.org) + */ + +/* INCLUDES ******************************************************************/ + +#include + +#include + +EXTERN _HalpEndSoftwareInterrupt2@8:PROC + +/* GLOBALS *******************************************************************/ + +.data +ASSUME CS:NOTHING, DS:NOTHING, ES:NOTHING, FS:NOTHING, GS:NOTHING + +/* FUNCTIONS *****************************************************************/ + +.code +PUBLIC _HalpEndSoftwareInterrupt@8 +.PROC _HalpEndSoftwareInterrupt@8 + FPO 0, 2, 0, 0, 0, FRAME_FPO + + /* Call the C function with the same arguments we got */ + push [esp+8] + push [esp+8] + call _HalpEndSoftwareInterrupt2@8 + + /* Check if we got a pointer back */ + test eax, eax + jnz CallIntHandler + + /* No? Just return */ + ret 8 + +CallIntHandler: + /* We got a pointer to call. Since it won't return, free up our stack + space, or we could end up with some nasty deep recursion */ + mov ecx, [esp+8] + add esp, 12 + jmp eax +.ENDP + +END diff --git a/reactos/hal/halx86/up/pic.c b/reactos/hal/halx86/up/pic.c index 4857c53cb93..821f071e24c 100644 --- a/reactos/hal/halx86/up/pic.c +++ b/reactos/hal/halx86/up/pic.c @@ -12,6 +12,11 @@ #define NDEBUG #include +VOID +NTAPI +HalpEndSoftwareInterrupt(IN KIRQL OldIrql, + IN PKTRAP_FRAME TrapFrame); + /* GLOBALS ********************************************************************/ #ifndef _MINIHAL_ @@ -263,7 +268,7 @@ ULONG FindHigherIrqlMask[32] = * so it will always preempt until we reach PROFILE_LEVEL. */ 0b00000000000000000001011111110000, /* IRQL 20 */ - 0b00000000000000000001001111110000, /* IRQL 20 */ + 0b00000000000000000001001111110000, /* IRQL 21 */ 0b00000000000000000001000111110000, /* IRQL 22 */ 0b00000000000000000001000011110000, /* IRQL 23 */ 0b00000000000000000001000001110000, /* IRQL 24 */ @@ -732,15 +737,17 @@ HalClearSoftwareInterrupt(IN KIRQL Irql) KeGetPcr()->IRR &= ~(1 << Irql); } -VOID +PHAL_SW_INTERRUPT_HANDLER_2ND_ENTRY NTAPI -HalpEndSoftwareInterrupt(IN KIRQL OldIrql, - IN PKTRAP_FRAME TrapFrame) +HalpEndSoftwareInterrupt2(IN KIRQL OldIrql, + IN PKTRAP_FRAME TrapFrame) { ULONG PendingIrql, PendingIrqlMask, PendingIrqMask; PKPCR Pcr = KeGetPcr(); PIC_MASK Mask; + UNREFERENCED_PARAMETER(TrapFrame); + /* Set old IRQL */ Pcr->Irql = OldIrql; @@ -749,10 +756,10 @@ HalpEndSoftwareInterrupt(IN KIRQL OldIrql, { /* Check for pending software interrupts and compare with current IRQL */ PendingIrqlMask = Pcr->IRR & FindHigherIrqlMask[OldIrql]; - if (!PendingIrqlMask) return; + if (!PendingIrqlMask) return NULL; /* Check for in-service delayed interrupt */ - if (Pcr->IrrActive & 0xFFFFFFF0) return; + if (Pcr->IrrActive & 0xFFFFFFF0) return NULL; /* Check if pending IRQL affects hardware state */ BitScanReverse(&PendingIrql, PendingIrqlMask); @@ -777,10 +784,11 @@ HalpEndSoftwareInterrupt(IN KIRQL OldIrql, else { /* No need to loop checking for hardware interrupts */ - SWInterruptHandlerTable2[PendingIrql](TrapFrame); - UNREACHABLE; + return SWInterruptHandlerTable2[PendingIrql]; } } + + return NULL; } /* EDGE INTERRUPT DISMISSAL FUNCTIONS *****************************************/