Author: nwhitehorn
Date: Tue Mar  9 02:00:53 2010
New Revision: 204903
URL: http://svn.freebsd.org/changeset/base/204903

Log:
  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

Modified:
  head/sys/powerpc/aim/interrupt.c
  head/sys/powerpc/booke/interrupt.c

Modified: head/sys/powerpc/aim/interrupt.c
==============================================================================
--- head/sys/powerpc/aim/interrupt.c    Tue Mar  9 01:11:45 2010        
(r204902)
+++ head/sys/powerpc/aim/interrupt.c    Tue Mar  9 02:00:53 2010        
(r204903)
@@ -80,15 +80,17 @@ powerpc_interrupt(struct trapframe *fram
 
        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:

Modified: head/sys/powerpc/booke/interrupt.c
==============================================================================
--- head/sys/powerpc/booke/interrupt.c  Tue Mar  9 01:11:45 2010        
(r204902)
+++ head/sys/powerpc/booke/interrupt.c  Tue Mar  9 02:00:53 2010        
(r204903)
@@ -118,9 +118,11 @@ powerpc_decr_interrupt(struct trapframe 
        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 
 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();
 }
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to