Do console locking.
[pintos-anon] / src / lib / kernel / console.c
diff --git a/src/lib/kernel/console.c b/src/lib/kernel/console.c
new file mode 100644 (file)
index 0000000..7ce9cbf
--- /dev/null
@@ -0,0 +1,93 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include "devices/serial.h"
+#include "devices/vga.h"
+#include "threads/interrupt.h"
+#include "threads/synch.h"
+
+static void vprintf_helper (char, void *);
+static void putchar_unlocked (uint8_t c);
+
+/* The console lock.
+   Both the vga and serial layers do their own locking, so it's
+   safe to call them at any time.
+   But this lock is useful to prevent simultaneous printf() calls
+   from mixing their output, which looks confusing. */
+static struct lock console_lock;
+
+void
+console_init (void) 
+{
+  lock_init (&console_lock, "console");
+}
+
+/* The standard vprintf() function,
+   which is like printf() but uses a va_list.
+   Writes its output to both vga display and serial port. */
+int
+vprintf (const char *format, va_list args) 
+{
+  int char_cnt = 0;
+
+  if (!intr_context ())
+    lock_acquire (&console_lock);
+
+  __vprintf (format, args, vprintf_helper, &char_cnt);
+
+  if (!intr_context ())
+    lock_release (&console_lock);
+
+  return char_cnt;
+}
+
+/* Writes string S to the console, followed by a new-line
+   character. */
+int
+puts (const char *s) 
+{
+  if (!intr_context ())
+    lock_acquire (&console_lock);
+
+  while (*s != '\0')
+    putchar_unlocked (*s++);
+  putchar_unlocked ('\n');
+
+  if (!intr_context ())
+    lock_release (&console_lock);
+
+  return 0;
+}
+
+/* Writes C to the vga display and serial port. */
+int
+putchar (int c) 
+{
+  if (!intr_context ())
+    lock_acquire (&console_lock);
+
+  putchar_unlocked (c);
+
+  if (!intr_context ())
+    lock_release (&console_lock);
+
+  return c;
+}
+\f
+/* Helper function for vprintf(). */
+static void
+vprintf_helper (char c, void *char_cnt_) 
+{
+  int *char_cnt = char_cnt_;
+  (*char_cnt)++;
+  putchar_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) 
+{
+  serial_putc (c);
+  vga_putc (c);
+}