Make yield_on_return only usable in an external interrupt context: (1)
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 29 Aug 2004 19:17:14 +0000 (19:17 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 29 Aug 2004 19:17:14 +0000 (19:17 +0000)
it's a global variable so it must be in use only in one context at
once, which is okay because we don't nest external interrupts and (2)
if we're not in an external interrupt context then we might as well
just call thread_yield() and not screw around with "yield on return".

Also, enforce interrupts being off in external interrupt contexts.

src/threads/interrupt.c

index 0d7b119f696c3cc32e459421e49d4967123b2b36..dc4b31ba3d5a0256f57fd1a0bc84aae15419d7e8 100644 (file)
@@ -117,16 +117,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);
@@ -137,10 +134,10 @@ intr_handler (struct intr_frame *args)
       ASSERT (intr_context ());
       intr_in_progress = false;
       pic_eoi (); 
-    }
 
-  if (yield_on_return) 
-    thread_yield (); 
+      if (yield_on_return) 
+        thread_yield (); 
+    }
 }
 
 bool
@@ -152,6 +149,7 @@ intr_context (void)
 void
 intr_yield_on_return (void) 
 {
+  ASSERT (intr_context ());
   yield_on_return = true;
 }
 
@@ -184,17 +182,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