From: Ben Pfaff Date: Sun, 29 Aug 2004 19:17:14 +0000 (+0000) Subject: Make yield_on_return only usable in an external interrupt context: (1) X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pintos-anon;a=commitdiff_plain;h=8d75e156311e8224d1c54ae6912fefd4a5ff059d Make yield_on_return only usable in an external interrupt context: (1) 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. --- diff --git a/src/threads/interrupt.c b/src/threads/interrupt.c index 0d7b119..dc4b31b 100644 --- a/src/threads/interrupt.c +++ b/src/threads/interrupt.c @@ -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