Clean up threads.
[pintos-anon] / src / threads / interrupt.c
index 0d7b119f696c3cc32e459421e49d4967123b2b36..9f71b8c1ae08bb92e7efbded26a11954c949dc6f 100644 (file)
@@ -88,10 +88,13 @@ pic_init (void)
    If we don't acknowledge the IRQ, we'll never get it again, so
    this is important.  */
 static void
-pic_eoi (void
+pic_eoi (int irq
 {
   /* FIXME?  The Linux code is much more complicated. */
+  ASSERT (irq >= 0x20 && irq < 0x30);
   outb (0x20, 0x20);
+  if (irq >= 0x28)
+    outb (0xa0, 0x20);
 }
 \f
 #define INTR_CNT 256
@@ -117,16 +120,13 @@ intr_name (int vec)
 void
 intr_handler (struct intr_frame *args) 
 {
-  bool external;
-  
-  yield_on_return = false;
-
-  external = args->vec_no >= 0x20 && args->vec_no < 0x30;
+  bool external = args->vec_no >= 0x20 && args->vec_no < 0x30;
   if (external) 
     {
       ASSERT (intr_get_level () == IF_OFF);
       ASSERT (!intr_context ());
       intr_in_progress = true;
+      yield_on_return = false;
     }
 
   intr_handlers[args->vec_no] (args);
@@ -136,11 +136,11 @@ intr_handler (struct intr_frame *args)
       ASSERT (intr_get_level () == IF_OFF);
       ASSERT (intr_context ());
       intr_in_progress = false;
-      pic_eoi (); 
-    }
+      pic_eoi (args->vec_no); 
 
-  if (yield_on_return) 
-    thread_yield (); 
+      if (yield_on_return) 
+        thread_yield (); 
+    }
 }
 
 bool
@@ -152,6 +152,7 @@ intr_context (void)
 void
 intr_yield_on_return (void) 
 {
+  ASSERT (intr_context ());
   yield_on_return = true;
 }
 
@@ -184,17 +185,18 @@ make_trap_gate (void (*target) (void), int dpl)
   return make_gate (target, dpl, TYPE_TRAP_32);
 }
 
-/* We don't support nested interrupts generated by external
-   hardware, so these interrupts (vec_no 0x20...0x2f) should
-   specify IF_OFF for LEVEL.  Otherwise a timer interrupt could
-   cause a task switch during interrupt handling.  Most other
-   interrupts can and should be handled with interrupts
-   enabled. */
 void
 intr_register (uint8_t vec_no, int dpl, enum if_level level,
                intr_handler_func *handler,
                const char *name) 
 {
+  /* Interrupts generated by external hardware (0x20 <= VEC_NO <=
+     0x2f) should specify IF_OFF for LEVEL.  Otherwise a timer
+     interrupt could cause a task switch during interrupt
+     handling.  Most other interrupts can and should be handled
+     with interrupts enabled. */
+  ASSERT (vec_no < 0x20 || vec_no > 0x2f || level == IF_OFF);
+
   if (level == IF_ON)
     idt[vec_no] = make_trap_gate (intr_stubs[vec_no], dpl);
   else
@@ -267,7 +269,7 @@ void
 intr_panic (struct intr_frame *regs) 
 {
   dump_intr_frame (regs);
-  panic ("Panic!");
+  PANIC ("Panic!");
 }
 
 void
@@ -276,8 +278,10 @@ intr_kill (struct intr_frame *f)
   switch (f->cs)
     {
     case SEL_UCSEG:
-      printk ("[%p] Interrupt %#04x (%s), killing process.\n",
-              thread_current (), f->vec_no, intr_name (f->vec_no));
+      printk ("%s: dying due to interrupt %#04x (%s).\n",
+              thread_name (thread_current ()),
+              f->vec_no, intr_name (f->vec_no));
+      dump_intr_frame (f);
       thread_exit (); 
 
     case SEL_KCSEG: