PKUOS - Pintos
Pintos source browser for PKU Operating System course
console.c
Go to the documentation of this file.
1#include <console.h>
2#include <stdarg.h>
3#include <stdio.h>
4#include "devices/serial.h"
5#include "devices/vga.h"
6#include "threads/init.h"
7#include "threads/interrupt.h"
8#include "threads/synch.h"
9
10static void vprintf_helper (char, void *);
11static void putchar_have_lock (uint8_t c);
12
13/** The console lock.
14 Both the vga and serial layers do their own locking, so it's
15 safe to call them at any time.
16 But this lock is useful to prevent simultaneous printf() calls
17 from mixing their output, which looks confusing. */
18static struct lock console_lock;
19
20/** True in ordinary circumstances: we want to use the console
21 lock to avoid mixing output between threads, as explained
22 above.
23
24 False in early boot before the point that locks are functional
25 or the console lock has been initialized, or after a kernel
26 panics. In the former case, taking the lock would cause an
27 assertion failure, which in turn would cause a panic, turning
28 it into the latter case. In the latter case, if it is a buggy
29 lock_acquire() implementation that caused the panic, we'll
30 likely just recurse. */
31static bool use_console_lock;
32
33/** It's possible, if you add enough debug output to Pintos, to
34 try to recursively grab console_lock from a single thread. As
35 a real example, I added a printf() call to palloc_free().
36 Here's a real backtrace that resulted:
37
38 lock_console()
39 vprintf()
40 printf() - palloc() tries to grab the lock again
41 palloc_free()
42 thread_schedule_tail() - another thread dying as we switch threads
43 schedule()
44 thread_yield()
45 intr_handler() - timer interrupt
46 intr_set_level()
47 serial_putc()
48 putchar_have_lock()
49 putbuf()
50 sys_write() - one process writing to the console
51 syscall_handler()
52 intr_handler()
53
54 This kind of thing is very difficult to debug, so we avoid the
55 problem by simulating a recursive lock with a depth
56 counter. */
58
59/** Number of characters written to console. */
61
62/** Enable console locking. */
63void
65{
67 use_console_lock = true;
68}
69
70/** Notifies the console that a kernel panic is underway,
71 which warns it to avoid trying to take the console lock from
72 now on. */
73void
75{
76 use_console_lock = false;
77}
78
79/** Prints console statistics. */
80void
82{
83 printf ("Console: %lld characters output\n", write_cnt);
84}
85
86/** Acquires the console lock. */
87static void
89{
91 {
94 else
96 }
97}
98
99/** Releases the console lock. */
100static void
102{
103 if (!intr_context () && use_console_lock)
104 {
105 if (console_lock_depth > 0)
107 else
109 }
110}
111
112/** Returns true if the current thread has the console lock,
113 false otherwise. */
114static bool
116{
117 return (intr_context ()
120}
121
122/** The standard vprintf() function,
123 which is like printf() but uses a va_list.
124 Writes its output to both vga display and serial port. */
125int
126vprintf (const char *format, va_list args)
127{
128 int char_cnt = 0;
129
131 __vprintf (format, args, vprintf_helper, &char_cnt);
133
134 return char_cnt;
135}
136
137/** Writes string S to the console, followed by a new-line
138 character. */
139int
140puts (const char *s)
141{
143 while (*s != '\0')
144 putchar_have_lock (*s++);
145 putchar_have_lock ('\n');
147
148 return 0;
149}
150
151/** Writes the N characters in BUFFER to the console. */
152void
153putbuf (const char *buffer, size_t n)
154{
156 while (n-- > 0)
159}
160
161/** Writes C to the vga display and serial port. */
162int
163putchar (int c)
164{
168
169 return c;
170}
171
172/** Helper function for vprintf(). */
173static void
174vprintf_helper (char c, void *char_cnt_)
175{
176 int *char_cnt = char_cnt_;
177 (*char_cnt)++;
179}
180
181/** Writes C to the vga display and serial port.
182 The caller has already acquired the console lock if
183 appropriate. */
184static void
186{
188 write_cnt++;
189 serial_putc (c);
190 vga_putc (c);
191}
#define ASSERT(CONDITION)
This is outside the header guard so that debug.h may be included multiple times with different settin...
Definition: debug.h:31
static struct intq buffer
Stores keys from the keyboard and serial port.
Definition: input.c:7
bool intr_context(void)
Returns true during processing of an external interrupt and false at all other times.
Definition: interrupt.c:212
void console_print_stats(void)
Prints console statistics.
Definition: console.c:81
static bool use_console_lock
True in ordinary circumstances: we want to use the console lock to avoid mixing output between thread...
Definition: console.c:31
static void putchar_have_lock(uint8_t c)
Writes C to the vga display and serial port.
Definition: console.c:185
void putbuf(const char *buffer, size_t n)
Writes the N characters in BUFFER to the console.
Definition: console.c:153
static void acquire_console(void)
Acquires the console lock.
Definition: console.c:88
static int console_lock_depth
It's possible, if you add enough debug output to Pintos, to try to recursively grab console_lock from...
Definition: console.c:57
static struct lock console_lock
The console lock.
Definition: console.c:18
void console_panic(void)
Notifies the console that a kernel panic is underway, which warns it to avoid trying to take the cons...
Definition: console.c:74
static int64_t write_cnt
Number of characters written to console.
Definition: console.c:60
int vprintf(const char *format, va_list args)
The standard vprintf() function, which is like printf() but uses a va_list.
Definition: console.c:126
static bool console_locked_by_current_thread(void)
Returns true if the current thread has the console lock, false otherwise.
Definition: console.c:115
void console_init(void)
Enable console locking.
Definition: console.c:64
static void release_console(void)
Releases the console lock.
Definition: console.c:101
int puts(const char *s)
Writes string S to the console, followed by a new-line character.
Definition: console.c:140
static void vprintf_helper(char, void *)
Helper function for vprintf().
Definition: console.c:174
int putchar(int c)
Writes C to the vga display and serial port.
Definition: console.c:163
void __vprintf(const char *format, va_list args, void(*output)(char, void *), void *aux)
Internal functions.
Definition: stdio.c:157
int printf(const char *format,...)
Writes formatted output to the console.
Definition: stdio.c:79
static uint8_t s[256]
RC4-based pseudo-random number generator (PRNG).
Definition: random.c:17
void serial_putc(uint8_t byte)
Sends BYTE to the serial port.
Definition: serial.c:99
__builtin_va_list va_list
GCC has <stdarg.h> functionality as built-ins, so all we need is to use it.
Definition: stdarg.h:7
signed long long int int64_t
Definition: stdint.h:16
unsigned char uint8_t
Definition: stdint.h:20
Lock.
Definition: synch.h:22
void lock_release(struct lock *lock)
Releases LOCK, which must be owned by the current thread.
Definition: synch.c:229
bool lock_held_by_current_thread(const struct lock *lock)
Returns true if the current thread holds LOCK, false otherwise.
Definition: synch.c:242
void lock_init(struct lock *lock)
Initializes LOCK.
Definition: synch.c:176
void lock_acquire(struct lock *lock)
Acquires LOCK, sleeping until it becomes available if necessary.
Definition: synch.c:193
void vga_putc(int c)
Writes C to the VGA text display, interpreting control characters in the conventional ways.
Definition: vga.c:52