Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/kern/lib/kprintf.c
2093 views
1
/*
2
* Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009
3
* The President and Fellows of Harvard College.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
* 3. Neither the name of the University nor the names of its contributors
14
* may be used to endorse or promote products derived from this software
15
* without specific prior written permission.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
#include <types.h>
31
#include <kern/unistd.h>
32
#include <stdarg.h>
33
#include <lib.h>
34
#include <spl.h>
35
#include <thread.h>
36
#include <current.h>
37
#include <synch.h>
38
#include <mainbus.h>
39
#include <vfs.h> // for vfs_sync()
40
41
42
/* Flags word for DEBUG() macro. */
43
uint32_t dbflags = 0;
44
45
/* Lock for non-polled kprintfs */
46
static struct lock *kprintf_lock;
47
48
/* Lock for polled kprintfs */
49
static struct spinlock kprintf_spinlock;
50
51
52
/*
53
* Warning: all this has to work from interrupt handlers and when
54
* interrupts are disabled.
55
*/
56
57
58
/*
59
* Create the kprintf lock. Must be called before creating a second
60
* thread or enabling a second CPU.
61
*/
62
void
63
kprintf_bootstrap(void)
64
{
65
KASSERT(kprintf_lock == NULL);
66
67
kprintf_lock = lock_create("kprintf_lock");
68
if (kprintf_lock == NULL) {
69
panic("Could not create kprintf_lock\n");
70
}
71
spinlock_init(&kprintf_spinlock);
72
}
73
74
/*
75
* Send characters to the console. Backend for __printf.
76
*/
77
static
78
void
79
console_send(void *junk, const char *data, size_t len)
80
{
81
size_t i;
82
83
(void)junk;
84
85
for (i=0; i<len; i++) {
86
putch(data[i]);
87
}
88
}
89
90
/*
91
* Printf to the console.
92
*/
93
int
94
kprintf(const char *fmt, ...)
95
{
96
int chars;
97
va_list ap;
98
bool dolock;
99
100
dolock = kprintf_lock != NULL
101
&& curthread->t_in_interrupt == false
102
&& curthread->t_iplhigh_count == 0;
103
104
if (dolock) {
105
lock_acquire(kprintf_lock);
106
}
107
else {
108
spinlock_acquire(&kprintf_spinlock);
109
}
110
putch_prepare();
111
112
va_start(ap, fmt);
113
chars = __vprintf(console_send, NULL, fmt, ap);
114
va_end(ap);
115
116
putch_complete();
117
if (dolock) {
118
lock_release(kprintf_lock);
119
}
120
else {
121
spinlock_release(&kprintf_spinlock);
122
}
123
124
return chars;
125
}
126
127
/*
128
* panic() is for fatal errors. It prints the printf arguments it's
129
* passed and then halts the system.
130
*/
131
132
void
133
panic(const char *fmt, ...)
134
{
135
va_list ap;
136
137
/*
138
* When we reach panic, the system is usually fairly screwed up.
139
* It's not entirely uncommon for anything else we try to do
140
* here to trigger more panics.
141
*
142
* This variable makes sure that if we try to do something here,
143
* and it causes another panic, *that* panic doesn't try again;
144
* trying again almost inevitably causes infinite recursion.
145
*
146
* This is not excessively paranoid - these things DO happen!
147
*/
148
static volatile int evil;
149
150
if (evil == 0) {
151
evil = 1;
152
153
/*
154
* Not only do we not want to be interrupted while
155
* panicking, but we also want the console to be
156
* printing in polling mode so as not to do context
157
* switches. So turn interrupts off on this CPU.
158
*/
159
splhigh();
160
}
161
162
if (evil == 1) {
163
evil = 2;
164
165
/* Kill off other threads and halt other CPUs. */
166
thread_panic();
167
}
168
169
if (evil == 2) {
170
evil = 3;
171
172
/* Print the message. */
173
kprintf("panic: ");
174
putch_prepare();
175
va_start(ap, fmt);
176
__vprintf(console_send, NULL, fmt, ap);
177
va_end(ap);
178
putch_complete();
179
}
180
181
if (evil == 3) {
182
evil = 4;
183
184
/* Try to sync the disks. */
185
vfs_sync();
186
}
187
188
if (evil == 4) {
189
evil = 5;
190
191
/* Shut down or reboot the system. */
192
mainbus_panic();
193
}
194
195
/*
196
* Last resort, just in case.
197
*/
198
199
for (;;);
200
}
201
202
/*
203
* Assertion failures go through this.
204
*/
205
void
206
badassert(const char *expr, const char *file, int line, const char *func)
207
{
208
panic("Assertion failed: %s, at %s:%d (%s)\n",
209
expr, file, line, func);
210
}
211
212