Eliminate race condition in console_print_stats() found by Sorav's
[pintos-anon] / src / lib / kernel / console.c
index 14c707a63681129a66463677d6e7916d80199855..176dd0688dc5717919b06e59d4a784f0d24c1f64 100644 (file)
@@ -7,7 +7,7 @@
 #include "threads/synch.h"
 
 static void vprintf_helper (char, void *);
-static void putchar_unlocked (uint8_t c);
+static void put_char_unlocked (uint8_t c);
 
 /* The console lock.
    Both the vga and serial layers do their own locking, so it's
@@ -31,7 +31,7 @@ static struct lock console_lock;
    intr_handler()       - timer interrupt
    intr_set_level()
    serial_putc()
-   putchar_unlocked()
+   put_char_unlocked()
    putbuf()
    sys_write()          - one process writing to the console
    syscall_handler()
@@ -42,11 +42,14 @@ static struct lock console_lock;
    counter. */
 static int console_lock_depth;
 
+/* Number of characters written to console. */
+static int64_t write_cnt;
+
 /* Initializes the console. */
 void
 console_init (void) 
 {
-  lock_init (&console_lock, "console");
+  lock_init (&console_lock);
 }
 
 /* Acquires the console lock. */
@@ -75,6 +78,23 @@ release_console (void)
     }
 }
 
+/* Returns true if the current thread has the console lock,
+   false otherwise. */
+static bool
+console_locked_by_current_thread (void) 
+{
+  return intr_context () || lock_held_by_current_thread (&console_lock);
+}
+
+/* Prints console statistics. */
+void
+console_print_stats (void) 
+{
+  acquire_console ();
+  printf ("Console: %lld characters output\n", write_cnt);
+  release_console ();
+}
+
 /* The standard vprintf() function,
    which is like printf() but uses a va_list.
    Writes its output to both vga display and serial port. */
@@ -97,8 +117,8 @@ puts (const char *s)
 {
   acquire_console ();
   while (*s != '\0')
-    putchar_unlocked (*s++);
-  putchar_unlocked ('\n');
+    put_char_unlocked (*s++);
+  put_char_unlocked ('\n');
   release_console ();
 
   return 0;
@@ -110,7 +130,7 @@ putbuf (const char *buffer, size_t n)
 {
   acquire_console ();
   while (n-- > 0)
-    putchar_unlocked (*buffer++);
+    put_char_unlocked (*buffer++);
   release_console ();
 }
 
@@ -119,7 +139,7 @@ int
 putchar (int c) 
 {
   acquire_console ();
-  putchar_unlocked (c);
+  put_char_unlocked (c);
   release_console ();
   
   return c;
@@ -131,15 +151,17 @@ vprintf_helper (char c, void *char_cnt_)
 {
   int *char_cnt = char_cnt_;
   (*char_cnt)++;
-  putchar_unlocked (c);
+  put_char_unlocked (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) 
+put_char_unlocked (uint8_t c) 
 {
+  ASSERT (console_locked_by_current_thread ());
+  write_cnt++;
   serial_putc (c);
   vga_putc (c);
 }