4 #include "devices/serial.h"
5 #include "devices/vga.h"
6 #include "threads/interrupt.h"
7 #include "threads/synch.h"
9 static void vprintf_helper (char, void *);
10 static void put_char_unlocked (uint8_t c);
13 Both the vga and serial layers do their own locking, so it's
14 safe to call them at any time.
15 But this lock is useful to prevent simultaneous printf() calls
16 from mixing their output, which looks confusing. */
17 static struct lock console_lock;
19 /* It's possible, if you add enough debug output to Pintos, to
20 try to recursively grab console_lock from a single thread. As
21 a real example, I added a printf() call to palloc_free().
22 Here's a real backtrace that resulted:
26 printf() - palloc() tries to grab the lock again
28 schedule_tail() - another thread dying as we switch threads
31 intr_handler() - timer interrupt
36 sys_write() - one process writing to the console
40 This kind of thing is very difficult to debug, so we avoid the
41 problem by simulating a recursive lock with a depth
43 static int console_lock_depth;
45 /* Number of characters written to console. */
46 static int64_t write_cnt;
48 /* Initializes the console. */
52 lock_init (&console_lock);
55 /* Acquires the console lock. */
57 acquire_console (void)
61 if (lock_held_by_current_thread (&console_lock))
64 lock_acquire (&console_lock);
68 /* Releases the console lock. */
70 release_console (void)
74 if (console_lock_depth > 0)
77 lock_release (&console_lock);
81 /* Returns true if the current thread has the console lock,
84 console_locked_by_current_thread (void)
86 return intr_context () || lock_held_by_current_thread (&console_lock);
89 /* Prints console statistics. */
91 console_print_stats (void)
94 printf ("Console: %lld characters output\n", write_cnt);
98 /* The standard vprintf() function,
99 which is like printf() but uses a va_list.
100 Writes its output to both vga display and serial port. */
102 vprintf (const char *format, va_list args)
107 __vprintf (format, args, vprintf_helper, &char_cnt);
113 /* Writes string S to the console, followed by a new-line
120 put_char_unlocked (*s++);
121 put_char_unlocked ('\n');
127 /* Writes the N characters in BUFFER to the console. */
129 putbuf (const char *buffer, size_t n)
133 put_char_unlocked (*buffer++);
137 /* Writes C to the vga display and serial port. */
142 put_char_unlocked (c);
148 /* Helper function for vprintf(). */
150 vprintf_helper (char c, void *char_cnt_)
152 int *char_cnt = char_cnt_;
154 put_char_unlocked (c);
157 /* Writes C to the vga display and serial port.
158 The caller has already acquired the console lock if
161 put_char_unlocked (uint8_t c)
163 ASSERT (console_locked_by_current_thread ());