X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Flib%2Fkernel%2Fconsole.c;h=0d031b5b4bdd6a2257f416bdf1fc1ffdbbb4398e;hb=53a7f5d0952a4595f252247f5ee3d017468eb57e;hp=865b13b2cd810b0805acead8ec9f4e3e038f609a;hpb=615bf3b3d2a8573ed6fb9ddc0055745e163ac999;p=pintos-anon diff --git a/src/lib/kernel/console.c b/src/lib/kernel/console.c index 865b13b..0d031b5 100644 --- a/src/lib/kernel/console.c +++ b/src/lib/kernel/console.c @@ -3,11 +3,12 @@ #include #include "devices/serial.h" #include "devices/vga.h" +#include "threads/init.h" #include "threads/interrupt.h" #include "threads/synch.h" static void vprintf_helper (char, void *); -static void putchar_unlocked (uint8_t c); +static void putchar_have_lock (uint8_t c); /* The console lock. Both the vga and serial layers do their own locking, so it's @@ -16,6 +17,19 @@ static void putchar_unlocked (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(). @@ -31,7 +45,7 @@ static struct lock console_lock; intr_handler() - timer interrupt intr_set_level() serial_putc() - putchar_unlocked() + putchar_have_lock() putbuf() sys_write() - one process writing to the console syscall_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, @@ -115,8 +141,8 @@ puts (const char *s) { acquire_console (); while (*s != '\0') - putchar_unlocked (*s++); - putchar_unlocked ('\n'); + putchar_have_lock (*s++); + putchar_have_lock ('\n'); release_console (); return 0; @@ -128,7 +154,7 @@ putbuf (const char *buffer, size_t n) { acquire_console (); while (n-- > 0) - putchar_unlocked (*buffer++); + putchar_have_lock (*buffer++); release_console (); } @@ -137,7 +163,7 @@ int putchar (int c) { acquire_console (); - putchar_unlocked (c); + putchar_have_lock (c); release_console (); return c; @@ -149,14 +175,14 @@ vprintf_helper (char c, void *char_cnt_) { int *char_cnt = char_cnt_; (*char_cnt)++; - putchar_unlocked (c); + putchar_have_lock (c); } /* Writes C to the vga display and serial port. The caller has already acquired the console lock if appropriate. */ static void -putchar_unlocked (uint8_t c) +putchar_have_lock (uint8_t c) { ASSERT (console_locked_by_current_thread ()); write_cnt++;