Parse command-line options much earlier, so that thread_mlfqs is
[pintos-anon] / src / lib / kernel / console.c
index 865b13b2cd810b0805acead8ec9f4e3e038f609a..0d031b5b4bdd6a2257f416bdf1fc1ffdbbb4398e 100644 (file)
@@ -3,11 +3,12 @@
 #include <stdio.h>
 #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++;