Place interrupt handling in a critical section and remove double

counting in incrementing the interrupt nesting level. This fixes a number
of bugs in which the interrupt thread could be preempted by an IPI,
indefinitely delaying acknowledgement of the interrupt to the PIC, causing
interrupt starvation and hangs.

Reported by:	linimon
Reviewed by:	marcel, jhb
MFC after:	1 week
This commit is contained in:
nwhitehorn 2010-03-09 02:00:53 +00:00
parent 93013817b0
commit 3f119cd4f7
2 changed files with 8 additions and 6 deletions

View File

@ -80,15 +80,17 @@ powerpc_interrupt(struct trapframe *framep)
switch (framep->exc) {
case EXC_EXI:
atomic_add_int(&td->td_intr_nesting_level, 1);
critical_enter();
PIC_DISPATCH(pic, framep);
atomic_subtract_int(&td->td_intr_nesting_level, 1);
critical_exit();
break;
case EXC_DECR:
critical_enter();
atomic_add_int(&td->td_intr_nesting_level, 1);
decr_intr(framep);
atomic_subtract_int(&td->td_intr_nesting_level, 1);
critical_exit();
break;
default:

View File

@ -118,9 +118,11 @@ powerpc_decr_interrupt(struct trapframe *framep)
struct thread *td;
td = PCPU_GET(curthread);
critical_enter();
atomic_add_int(&td->td_intr_nesting_level, 1);
decr_intr(framep);
atomic_subtract_int(&td->td_intr_nesting_level, 1);
critical_exit();
}
/*
@ -129,10 +131,8 @@ powerpc_decr_interrupt(struct trapframe *framep)
void
powerpc_extr_interrupt(struct trapframe *framep)
{
struct thread *td;
td = PCPU_GET(curthread);
atomic_add_int(&td->td_intr_nesting_level, 1);
critical_enter();
PIC_DISPATCH(pic, framep);
atomic_subtract_int(&td->td_intr_nesting_level, 1);
critical_exit();
}