X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flib%2Fkernel%2Fconsole.c;h=844b18468bde5c3b828bb4455213aed6949f0f13;hb=64e74e3536b95c4d0a46aec56bc373ad0f6d470b;hp=f62e7f34c246b0e64183d8a40c1621a32b348597;hpb=745d62ba7e4bef2887ce158a3b2cfc5f24ebadef;p=pintos-anon diff --git a/src/lib/kernel/console.c b/src/lib/kernel/console.c index f62e7f3..844b184 100644 --- a/src/lib/kernel/console.c +++ b/src/lib/kernel/console.c @@ -3,6 +3,7 @@ #include #include "devices/serial.h" #include "devices/vga.h" +#include "threads/init.h" #include "threads/interrupt.h" #include "threads/synch.h" @@ -16,6 +17,19 @@ static void putchar_have_lock (uint8_t c); from mixing their output, which looks confusing. */ static struct lock console_lock; +/* True in ordinary circumstances: we want to use the console + lock to avoid mixing output between threads, as explained + above. + + False in early boot before the point that locks are functional + or the console lock has been initialized, or after a kernel + panics. In the former case, taking the lock would cause an + assertion failure, which in turn would cause a panic, turning + it into the latter case. In the latter case, if it is a buggy + lock_acquire() implementation that caused the panic, we'll + likely just recurse. */ +static bool use_console_lock; + /* It's possible, if you add enough debug output to Pintos, to try to recursively grab console_lock from a single thread. As a real example, I added a printf() call to palloc_free(). @@ -23,17 +37,17 @@ static struct lock console_lock; lock_console() vprintf() - printf() - palloc() tries to grab the lock again + printf() - palloc() tries to grab the lock again palloc_free() - schedule_tail() - another thread dying as we switch threads + thread_schedule_tail() - another thread dying as we switch threads schedule() thread_yield() - intr_handler() - timer interrupt + intr_handler() - timer interrupt intr_set_level() serial_putc() putchar_have_lock() putbuf() - sys_write() - one process writing to the console + sys_write() - one process writing to the console syscall_handler() intr_handler() @@ -45,11 +59,21 @@ static int console_lock_depth; /* Number of characters written to console. */ static int64_t write_cnt; -/* Initializes the console. */ +/* Enable console locking. */ void console_init (void) { lock_init (&console_lock); + use_console_lock = true; +} + +/* Notifies the console that a kernel panic is underway, + which warns it to avoid trying to take the console lock from + now on. */ +void +console_panic (void) +{ + use_console_lock = false; } /* Prints console statistics. */ @@ -63,7 +87,7 @@ console_print_stats (void) static void acquire_console (void) { - if (!intr_context ()) + if (!intr_context () && use_console_lock) { if (lock_held_by_current_thread (&console_lock)) console_lock_depth++; @@ -76,7 +100,7 @@ acquire_console (void) static void release_console (void) { - if (!intr_context ()) + if (!intr_context () && use_console_lock) { if (console_lock_depth > 0) console_lock_depth--; @@ -90,7 +114,9 @@ release_console (void) static bool console_locked_by_current_thread (void) { - return intr_context () || lock_held_by_current_thread (&console_lock); + return (intr_context () + || !use_console_lock + || lock_held_by_current_thread (&console_lock)); } /* The standard vprintf() function,