| @@ -1,1295 +1,1282 @@ | | | @@ -1,1295 +1,1282 @@ |
1 | /* $NetBSD: subr_prf.c,v 1.151 2014/01/11 17:07:45 christos Exp $ */ | | 1 | /* $NetBSD: subr_prf.c,v 1.152 2014/01/12 00:29:15 joerg Exp $ */ |
2 | | | 2 | |
3 | /*- | | 3 | /*- |
4 | * Copyright (c) 1986, 1988, 1991, 1993 | | 4 | * Copyright (c) 1986, 1988, 1991, 1993 |
5 | * The Regents of the University of California. All rights reserved. | | 5 | * The Regents of the University of California. All rights reserved. |
6 | * (c) UNIX System Laboratories, Inc. | | 6 | * (c) UNIX System Laboratories, Inc. |
7 | * All or some portions of this file are derived from material licensed | | 7 | * All or some portions of this file are derived from material licensed |
8 | * to the University of California by American Telephone and Telegraph | | 8 | * to the University of California by American Telephone and Telegraph |
9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with | | 9 | * Co. or Unix System Laboratories, Inc. and are reproduced herein with |
10 | * the permission of UNIX System Laboratories, Inc. | | 10 | * the permission of UNIX System Laboratories, Inc. |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
15 | * 1. Redistributions of source code must retain the above copyright | | 15 | * 1. Redistributions of source code must retain the above copyright |
16 | * notice, this list of conditions and the following disclaimer. | | 16 | * notice, this list of conditions and the following disclaimer. |
17 | * 2. Redistributions in binary form must reproduce the above copyright | | 17 | * 2. Redistributions in binary form must reproduce the above copyright |
18 | * notice, this list of conditions and the following disclaimer in the | | 18 | * notice, this list of conditions and the following disclaimer in the |
19 | * documentation and/or other materials provided with the distribution. | | 19 | * documentation and/or other materials provided with the distribution. |
20 | * 3. Neither the name of the University nor the names of its contributors | | 20 | * 3. Neither the name of the University nor the names of its contributors |
21 | * may be used to endorse or promote products derived from this software | | 21 | * may be used to endorse or promote products derived from this software |
22 | * without specific prior written permission. | | 22 | * without specific prior written permission. |
23 | * | | 23 | * |
24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 24 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 25 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 26 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 27 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 28 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 29 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 30 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 31 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 32 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 33 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
34 | * SUCH DAMAGE. | | 34 | * SUCH DAMAGE. |
35 | * | | 35 | * |
36 | * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95 | | 36 | * @(#)subr_prf.c 8.4 (Berkeley) 5/4/95 |
37 | */ | | 37 | */ |
38 | | | 38 | |
39 | #include <sys/cdefs.h> | | 39 | #include <sys/cdefs.h> |
40 | __KERNEL_RCSID(0, "$NetBSD: subr_prf.c,v 1.151 2014/01/11 17:07:45 christos Exp $"); | | 40 | __KERNEL_RCSID(0, "$NetBSD: subr_prf.c,v 1.152 2014/01/12 00:29:15 joerg Exp $"); |
41 | | | 41 | |
42 | #include "opt_ddb.h" | | 42 | #include "opt_ddb.h" |
43 | #include "opt_ipkdb.h" | | 43 | #include "opt_ipkdb.h" |
44 | #include "opt_kgdb.h" | | 44 | #include "opt_kgdb.h" |
45 | #include "opt_dump.h" | | 45 | #include "opt_dump.h" |
46 | | | 46 | |
47 | #include <sys/param.h> | | 47 | #include <sys/param.h> |
48 | #include <sys/stdint.h> | | 48 | #include <sys/stdint.h> |
49 | #include <sys/systm.h> | | 49 | #include <sys/systm.h> |
50 | #include <sys/buf.h> | | 50 | #include <sys/buf.h> |
51 | #include <sys/device.h> | | 51 | #include <sys/device.h> |
52 | #include <sys/reboot.h> | | 52 | #include <sys/reboot.h> |
53 | #include <sys/msgbuf.h> | | 53 | #include <sys/msgbuf.h> |
54 | #include <sys/proc.h> | | 54 | #include <sys/proc.h> |
55 | #include <sys/ioctl.h> | | 55 | #include <sys/ioctl.h> |
56 | #include <sys/vnode.h> | | 56 | #include <sys/vnode.h> |
57 | #include <sys/file.h> | | 57 | #include <sys/file.h> |
58 | #include <sys/tty.h> | | 58 | #include <sys/tty.h> |
59 | #include <sys/tprintf.h> | | 59 | #include <sys/tprintf.h> |
60 | #include <sys/spldebug.h> | | 60 | #include <sys/spldebug.h> |
61 | #include <sys/syslog.h> | | 61 | #include <sys/syslog.h> |
62 | #include <sys/kprintf.h> | | 62 | #include <sys/kprintf.h> |
63 | #include <sys/atomic.h> | | 63 | #include <sys/atomic.h> |
64 | #include <sys/kernel.h> | | 64 | #include <sys/kernel.h> |
65 | #include <sys/cpu.h> | | 65 | #include <sys/cpu.h> |
66 | | | 66 | |
67 | #include <dev/cons.h> | | 67 | #include <dev/cons.h> |
68 | | | 68 | |
69 | #include <net/if.h> | | 69 | #include <net/if.h> |
70 | | | 70 | |
71 | #ifdef IPKDB | | 71 | #ifdef IPKDB |
72 | #include <ipkdb/ipkdb.h> | | 72 | #include <ipkdb/ipkdb.h> |
73 | #endif | | 73 | #endif |
74 | | | 74 | |
75 | static kmutex_t kprintf_mtx; | | 75 | static kmutex_t kprintf_mtx; |
76 | static bool kprintf_inited = false; | | 76 | static bool kprintf_inited = false; |
77 | | | 77 | |
78 | #ifdef KGDB | | 78 | #ifdef KGDB |
79 | #include <sys/kgdb.h> | | 79 | #include <sys/kgdb.h> |
80 | #endif | | 80 | #endif |
81 | | | 81 | |
82 | #ifdef DDB | | 82 | #ifdef DDB |
83 | #include <ddb/ddbvar.h> /* db_panic */ | | 83 | #include <ddb/ddbvar.h> /* db_panic */ |
84 | #include <ddb/db_output.h> /* db_printf, db_putchar prototypes */ | | 84 | #include <ddb/db_output.h> /* db_printf, db_putchar prototypes */ |
85 | #endif | | 85 | #endif |
86 | | | 86 | |
87 | | | 87 | |
88 | /* | | 88 | /* |
89 | * defines | | 89 | * defines |
90 | */ | | 90 | */ |
91 | | | 91 | |
92 | | | 92 | |
93 | /* | | 93 | /* |
94 | * local prototypes | | 94 | * local prototypes |
95 | */ | | 95 | */ |
96 | | | 96 | |
97 | static void putchar(int, int, struct tty *); | | 97 | static void putchar(int, int, struct tty *); |
98 | | | 98 | |
99 | | | 99 | |
100 | /* | | 100 | /* |
101 | * globals | | 101 | * globals |
102 | */ | | 102 | */ |
103 | | | 103 | |
104 | extern struct tty *constty; /* pointer to console "window" tty */ | | 104 | extern struct tty *constty; /* pointer to console "window" tty */ |
105 | extern int log_open; /* subr_log: is /dev/klog open? */ | | 105 | extern int log_open; /* subr_log: is /dev/klog open? */ |
106 | const char *panicstr; /* arg to first call to panic (used as a flag | | 106 | const char *panicstr; /* arg to first call to panic (used as a flag |
107 | to indicate that panic has already been called). */ | | 107 | to indicate that panic has already been called). */ |
108 | struct cpu_info *paniccpu; /* cpu that first paniced */ | | 108 | struct cpu_info *paniccpu; /* cpu that first paniced */ |
109 | long panicstart, panicend; /* position in the msgbuf of the start and | | 109 | long panicstart, panicend; /* position in the msgbuf of the start and |
110 | end of the formatted panicstr. */ | | 110 | end of the formatted panicstr. */ |
111 | int doing_shutdown; /* set to indicate shutdown in progress */ | | 111 | int doing_shutdown; /* set to indicate shutdown in progress */ |
112 | | | 112 | |
113 | #ifndef DUMP_ON_PANIC | | 113 | #ifndef DUMP_ON_PANIC |
114 | #define DUMP_ON_PANIC 1 | | 114 | #define DUMP_ON_PANIC 1 |
115 | #endif | | 115 | #endif |
116 | int dumponpanic = DUMP_ON_PANIC; | | 116 | int dumponpanic = DUMP_ON_PANIC; |
117 | | | 117 | |
118 | /* | | 118 | /* |
119 | * v_putc: routine to putc on virtual console | | 119 | * v_putc: routine to putc on virtual console |
120 | * | | 120 | * |
121 | * the v_putc pointer can be used to redirect the console cnputc elsewhere | | 121 | * the v_putc pointer can be used to redirect the console cnputc elsewhere |
122 | * [e.g. to a "virtual console"]. | | 122 | * [e.g. to a "virtual console"]. |
123 | */ | | 123 | */ |
124 | | | 124 | |
125 | void (*v_putc)(int) = cnputc; /* start with cnputc (normal cons) */ | | 125 | void (*v_putc)(int) = cnputc; /* start with cnputc (normal cons) */ |
126 | void (*v_flush)(void) = cnflush; /* start with cnflush (normal cons) */ | | 126 | void (*v_flush)(void) = cnflush; /* start with cnflush (normal cons) */ |
127 | | | 127 | |
128 | const char hexdigits[] = "0123456789abcdef"; | | 128 | const char hexdigits[] = "0123456789abcdef"; |
129 | const char HEXDIGITS[] = "0123456789ABCDEF"; | | 129 | const char HEXDIGITS[] = "0123456789ABCDEF"; |
130 | | | 130 | |
131 | | | 131 | |
132 | /* | | 132 | /* |
133 | * functions | | 133 | * functions |
134 | */ | | 134 | */ |
135 | | | 135 | |
136 | /* | | 136 | /* |
137 | * Locking is inited fairly early in MI bootstrap. Before that | | 137 | * Locking is inited fairly early in MI bootstrap. Before that |
138 | * prints are done unlocked. But that doesn't really matter, | | 138 | * prints are done unlocked. But that doesn't really matter, |
139 | * since nothing can preempt us before interrupts are enabled. | | 139 | * since nothing can preempt us before interrupts are enabled. |
140 | */ | | 140 | */ |
141 | void | | 141 | void |
142 | kprintf_init(void) | | 142 | kprintf_init(void) |
143 | { | | 143 | { |
144 | | | 144 | |
145 | KASSERT(!kprintf_inited && cold); /* not foolproof, but ... */ | | 145 | KASSERT(!kprintf_inited && cold); /* not foolproof, but ... */ |
146 | mutex_init(&kprintf_mtx, MUTEX_DEFAULT, IPL_HIGH); | | 146 | mutex_init(&kprintf_mtx, MUTEX_DEFAULT, IPL_HIGH); |
147 | kprintf_inited = true; | | 147 | kprintf_inited = true; |
148 | } | | 148 | } |
149 | | | 149 | |
150 | void | | 150 | void |
151 | kprintf_lock(void) | | 151 | kprintf_lock(void) |
152 | { | | 152 | { |
153 | | | 153 | |
154 | if (__predict_true(kprintf_inited)) | | 154 | if (__predict_true(kprintf_inited)) |
155 | mutex_enter(&kprintf_mtx); | | 155 | mutex_enter(&kprintf_mtx); |
156 | } | | 156 | } |
157 | | | 157 | |
158 | void | | 158 | void |
159 | kprintf_unlock(void) | | 159 | kprintf_unlock(void) |
160 | { | | 160 | { |
161 | | | 161 | |
162 | if (__predict_true(kprintf_inited)) { | | 162 | if (__predict_true(kprintf_inited)) { |
163 | /* assert kprintf wasn't somehow inited while we were in */ | | 163 | /* assert kprintf wasn't somehow inited while we were in */ |
164 | KASSERT(mutex_owned(&kprintf_mtx)); | | 164 | KASSERT(mutex_owned(&kprintf_mtx)); |
165 | mutex_exit(&kprintf_mtx); | | 165 | mutex_exit(&kprintf_mtx); |
166 | } | | 166 | } |
167 | } | | 167 | } |
168 | | | 168 | |
169 | /* | | 169 | /* |
170 | * twiddle: spin a little propellor on the console. | | 170 | * twiddle: spin a little propellor on the console. |
171 | */ | | 171 | */ |
172 | | | 172 | |
173 | void | | 173 | void |
174 | twiddle(void) | | 174 | twiddle(void) |
175 | { | | 175 | { |
176 | static const char twiddle_chars[] = "|/-\\"; | | 176 | static const char twiddle_chars[] = "|/-\\"; |
177 | static int pos; | | 177 | static int pos; |
178 | | | 178 | |
179 | kprintf_lock(); | | 179 | kprintf_lock(); |
180 | | | 180 | |
181 | putchar(twiddle_chars[pos++ & 3], TOCONS, NULL); | | 181 | putchar(twiddle_chars[pos++ & 3], TOCONS, NULL); |
182 | putchar('\b', TOCONS, NULL); | | 182 | putchar('\b', TOCONS, NULL); |
183 | | | 183 | |
184 | kprintf_unlock(); | | 184 | kprintf_unlock(); |
185 | } | | 185 | } |
186 | | | 186 | |
187 | /* | | 187 | /* |
188 | * panic: handle an unresolvable fatal error | | 188 | * panic: handle an unresolvable fatal error |
189 | * | | 189 | * |
190 | * prints "panic: <message>" and reboots. if called twice (i.e. recursive | | 190 | * prints "panic: <message>" and reboots. if called twice (i.e. recursive |
191 | * call) we avoid trying to dump and just reboot (to avoid recursive panics). | | 191 | * call) we avoid trying to dump and just reboot (to avoid recursive panics). |
192 | */ | | 192 | */ |
193 | | | 193 | |
194 | void | | 194 | void |
195 | panic(const char *fmt, ...) | | 195 | panic(const char *fmt, ...) |
196 | { | | 196 | { |
197 | va_list ap; | | 197 | va_list ap; |
198 | | | 198 | |
199 | va_start(ap, fmt); | | 199 | va_start(ap, fmt); |
200 | vpanic(fmt, ap); | | 200 | vpanic(fmt, ap); |
201 | va_end(ap); | | 201 | va_end(ap); |
202 | } | | 202 | } |
203 | | | 203 | |
204 | void | | 204 | void |
205 | vpanic(const char *fmt, va_list ap) | | 205 | vpanic(const char *fmt, va_list ap) |
206 | { | | 206 | { |
207 | CPU_INFO_ITERATOR cii; | | 207 | CPU_INFO_ITERATOR cii; |
208 | struct cpu_info *ci, *oci; | | 208 | struct cpu_info *ci, *oci; |
209 | int bootopt; | | 209 | int bootopt; |
210 | static char scratchstr[256]; /* stores panic message */ | | 210 | static char scratchstr[256]; /* stores panic message */ |
211 | | | 211 | |
212 | spldebug_stop(); | | 212 | spldebug_stop(); |
213 | | | 213 | |
214 | if (lwp0.l_cpu && curlwp) { | | 214 | if (lwp0.l_cpu && curlwp) { |
215 | /* | | 215 | /* |
216 | * Disable preemption. If already panicing on another CPU, sit | | 216 | * Disable preemption. If already panicing on another CPU, sit |
217 | * here and spin until the system is rebooted. Allow the CPU that | | 217 | * here and spin until the system is rebooted. Allow the CPU that |
218 | * first paniced to panic again. | | 218 | * first paniced to panic again. |
219 | */ | | 219 | */ |
220 | kpreempt_disable(); | | 220 | kpreempt_disable(); |
221 | ci = curcpu(); | | 221 | ci = curcpu(); |
222 | oci = atomic_cas_ptr((void *)&paniccpu, NULL, ci); | | 222 | oci = atomic_cas_ptr((void *)&paniccpu, NULL, ci); |
223 | if (oci != NULL && oci != ci) { | | 223 | if (oci != NULL && oci != ci) { |
224 | /* Give interrupts a chance to try and prevent deadlock. */ | | 224 | /* Give interrupts a chance to try and prevent deadlock. */ |
225 | for (;;) { | | 225 | for (;;) { |
226 | #ifndef _RUMPKERNEL /* XXXpooka: temporary build fix, see kern/40505 */ | | 226 | #ifndef _RUMPKERNEL /* XXXpooka: temporary build fix, see kern/40505 */ |
227 | DELAY(10); | | 227 | DELAY(10); |
228 | #endif /* _RUMPKERNEL */ | | 228 | #endif /* _RUMPKERNEL */ |
229 | } | | 229 | } |
230 | } | | 230 | } |
231 | | | 231 | |
232 | /* | | 232 | /* |
233 | * Convert the current thread to a bound thread and prevent all | | 233 | * Convert the current thread to a bound thread and prevent all |
234 | * CPUs from scheduling unbound jobs. Do so without taking any | | 234 | * CPUs from scheduling unbound jobs. Do so without taking any |
235 | * locks. | | 235 | * locks. |
236 | */ | | 236 | */ |
237 | curlwp->l_pflag |= LP_BOUND; | | 237 | curlwp->l_pflag |= LP_BOUND; |
238 | for (CPU_INFO_FOREACH(cii, ci)) { | | 238 | for (CPU_INFO_FOREACH(cii, ci)) { |
239 | ci->ci_schedstate.spc_flags |= SPCF_OFFLINE; | | 239 | ci->ci_schedstate.spc_flags |= SPCF_OFFLINE; |
240 | } | | 240 | } |
241 | } | | 241 | } |
242 | | | 242 | |
243 | bootopt = RB_AUTOBOOT | RB_NOSYNC; | | 243 | bootopt = RB_AUTOBOOT | RB_NOSYNC; |
244 | if (!doing_shutdown) { | | 244 | if (!doing_shutdown) { |
245 | if (dumponpanic) | | 245 | if (dumponpanic) |
246 | bootopt |= RB_DUMP; | | 246 | bootopt |= RB_DUMP; |
247 | } else | | 247 | } else |
248 | printf("Skipping crash dump on recursive panic\n"); | | 248 | printf("Skipping crash dump on recursive panic\n"); |
249 | | | 249 | |
250 | doing_shutdown = 1; | | 250 | doing_shutdown = 1; |
251 | | | 251 | |
252 | if (msgbufenabled && msgbufp->msg_magic == MSG_MAGIC) | | 252 | if (msgbufenabled && msgbufp->msg_magic == MSG_MAGIC) |
253 | panicstart = msgbufp->msg_bufx; | | 253 | panicstart = msgbufp->msg_bufx; |
254 | | | 254 | |
255 | printf("panic: "); | | 255 | printf("panic: "); |
256 | if (panicstr == NULL) { | | 256 | if (panicstr == NULL) { |
257 | /* first time in panic - store fmt first for precaution */ | | 257 | /* first time in panic - store fmt first for precaution */ |
258 | panicstr = fmt; | | 258 | panicstr = fmt; |
259 | | | 259 | |
260 | vsnprintf(scratchstr, sizeof(scratchstr), fmt, ap); | | 260 | vsnprintf(scratchstr, sizeof(scratchstr), fmt, ap); |
261 | printf("%s", scratchstr); | | 261 | printf("%s", scratchstr); |
262 | panicstr = scratchstr; | | 262 | panicstr = scratchstr; |
263 | } else { | | 263 | } else { |
264 | vprintf(fmt, ap); | | 264 | vprintf(fmt, ap); |
265 | } | | 265 | } |
266 | printf("\n"); | | 266 | printf("\n"); |
267 | | | 267 | |
268 | if (msgbufenabled && msgbufp->msg_magic == MSG_MAGIC) | | 268 | if (msgbufenabled && msgbufp->msg_magic == MSG_MAGIC) |
269 | panicend = msgbufp->msg_bufx; | | 269 | panicend = msgbufp->msg_bufx; |
270 | | | 270 | |
271 | #ifdef IPKDB | | 271 | #ifdef IPKDB |
272 | ipkdb_panic(); | | 272 | ipkdb_panic(); |
273 | #endif | | 273 | #endif |
274 | #ifdef KGDB | | 274 | #ifdef KGDB |
275 | kgdb_panic(); | | 275 | kgdb_panic(); |
276 | #endif | | 276 | #endif |
277 | #ifdef KADB | | 277 | #ifdef KADB |
278 | if (boothowto & RB_KDB) | | 278 | if (boothowto & RB_KDB) |
279 | kdbpanic(); | | 279 | kdbpanic(); |
280 | #endif | | 280 | #endif |
281 | #ifdef DDB | | 281 | #ifdef DDB |
282 | db_panic(); | | 282 | db_panic(); |
283 | #endif | | 283 | #endif |
284 | printf("rebooting in"); | | | |
285 | for (int i = 10; i >= 0; --i) { | | | |
286 | printf(" %u", i); | | | |
287 | /* | | | |
288 | * sleep 10ms 100 times instead of 1s once to give a | | | |
289 | * VM hypervisor an opportunity to redraw part of the | | | |
290 | * screen during each call | | | |
291 | */ | | | |
292 | for (int j=0; i && j < 100; ++j) { | | | |
293 | DELAY(10000); | | | |
294 | } | | | |
295 | } | | | |
296 | printf("\n"); | | | |
297 | cpu_reboot(bootopt, NULL); | | 284 | cpu_reboot(bootopt, NULL); |
298 | } | | 285 | } |
299 | | | 286 | |
300 | /* | | 287 | /* |
301 | * kernel logging functions: log, logpri, addlog | | 288 | * kernel logging functions: log, logpri, addlog |
302 | */ | | 289 | */ |
303 | | | 290 | |
304 | /* | | 291 | /* |
305 | * log: write to the log buffer | | 292 | * log: write to the log buffer |
306 | * | | 293 | * |
307 | * => will not sleep [so safe to call from interrupt] | | 294 | * => will not sleep [so safe to call from interrupt] |
308 | * => will log to console if /dev/klog isn't open | | 295 | * => will log to console if /dev/klog isn't open |
309 | */ | | 296 | */ |
310 | | | 297 | |
311 | void | | 298 | void |
312 | log(int level, const char *fmt, ...) | | 299 | log(int level, const char *fmt, ...) |
313 | { | | 300 | { |
314 | va_list ap; | | 301 | va_list ap; |
315 | | | 302 | |
316 | kprintf_lock(); | | 303 | kprintf_lock(); |
317 | | | 304 | |
318 | klogpri(level); /* log the level first */ | | 305 | klogpri(level); /* log the level first */ |
319 | va_start(ap, fmt); | | 306 | va_start(ap, fmt); |
320 | kprintf(fmt, TOLOG, NULL, NULL, ap); | | 307 | kprintf(fmt, TOLOG, NULL, NULL, ap); |
321 | va_end(ap); | | 308 | va_end(ap); |
322 | if (!log_open) { | | 309 | if (!log_open) { |
323 | va_start(ap, fmt); | | 310 | va_start(ap, fmt); |
324 | kprintf(fmt, TOCONS, NULL, NULL, ap); | | 311 | kprintf(fmt, TOCONS, NULL, NULL, ap); |
325 | va_end(ap); | | 312 | va_end(ap); |
326 | } | | 313 | } |
327 | | | 314 | |
328 | kprintf_unlock(); | | 315 | kprintf_unlock(); |
329 | | | 316 | |
330 | logwakeup(); /* wake up anyone waiting for log msgs */ | | 317 | logwakeup(); /* wake up anyone waiting for log msgs */ |
331 | } | | 318 | } |
332 | | | 319 | |
333 | /* | | 320 | /* |
334 | * vlog: write to the log buffer [already have va_list] | | 321 | * vlog: write to the log buffer [already have va_list] |
335 | */ | | 322 | */ |
336 | | | 323 | |
337 | void | | 324 | void |
338 | vlog(int level, const char *fmt, va_list ap) | | 325 | vlog(int level, const char *fmt, va_list ap) |
339 | { | | 326 | { |
340 | va_list cap; | | 327 | va_list cap; |
341 | | | 328 | |
342 | va_copy(cap, ap); | | 329 | va_copy(cap, ap); |
343 | kprintf_lock(); | | 330 | kprintf_lock(); |
344 | | | 331 | |
345 | klogpri(level); /* log the level first */ | | 332 | klogpri(level); /* log the level first */ |
346 | kprintf(fmt, TOLOG, NULL, NULL, ap); | | 333 | kprintf(fmt, TOLOG, NULL, NULL, ap); |
347 | if (!log_open) | | 334 | if (!log_open) |
348 | kprintf(fmt, TOCONS, NULL, NULL, cap); | | 335 | kprintf(fmt, TOCONS, NULL, NULL, cap); |
349 | | | 336 | |
350 | kprintf_unlock(); | | 337 | kprintf_unlock(); |
351 | va_end(cap); | | 338 | va_end(cap); |
352 | | | 339 | |
353 | logwakeup(); /* wake up anyone waiting for log msgs */ | | 340 | logwakeup(); /* wake up anyone waiting for log msgs */ |
354 | } | | 341 | } |
355 | | | 342 | |
356 | /* | | 343 | /* |
357 | * logpri: log the priority level to the klog | | 344 | * logpri: log the priority level to the klog |
358 | */ | | 345 | */ |
359 | | | 346 | |
360 | void | | 347 | void |
361 | logpri(int level) | | 348 | logpri(int level) |
362 | { | | 349 | { |
363 | | | 350 | |
364 | kprintf_lock(); | | 351 | kprintf_lock(); |
365 | klogpri(level); | | 352 | klogpri(level); |
366 | kprintf_unlock(); | | 353 | kprintf_unlock(); |
367 | } | | 354 | } |
368 | | | 355 | |
369 | /* | | 356 | /* |
370 | * Note: we must be in the mutex here! | | 357 | * Note: we must be in the mutex here! |
371 | */ | | 358 | */ |
372 | void | | 359 | void |
373 | klogpri(int level) | | 360 | klogpri(int level) |
374 | { | | 361 | { |
375 | char *p; | | 362 | char *p; |
376 | char snbuf[KPRINTF_BUFSIZE]; | | 363 | char snbuf[KPRINTF_BUFSIZE]; |
377 | | | 364 | |
378 | putchar('<', TOLOG, NULL); | | 365 | putchar('<', TOLOG, NULL); |
379 | snprintf(snbuf, sizeof(snbuf), "%d", level); | | 366 | snprintf(snbuf, sizeof(snbuf), "%d", level); |
380 | for (p = snbuf ; *p ; p++) | | 367 | for (p = snbuf ; *p ; p++) |
381 | putchar(*p, TOLOG, NULL); | | 368 | putchar(*p, TOLOG, NULL); |
382 | putchar('>', TOLOG, NULL); | | 369 | putchar('>', TOLOG, NULL); |
383 | } | | 370 | } |
384 | | | 371 | |
385 | /* | | 372 | /* |
386 | * addlog: add info to previous log message | | 373 | * addlog: add info to previous log message |
387 | */ | | 374 | */ |
388 | | | 375 | |
389 | void | | 376 | void |
390 | addlog(const char *fmt, ...) | | 377 | addlog(const char *fmt, ...) |
391 | { | | 378 | { |
392 | va_list ap; | | 379 | va_list ap; |
393 | | | 380 | |
394 | kprintf_lock(); | | 381 | kprintf_lock(); |
395 | | | 382 | |
396 | va_start(ap, fmt); | | 383 | va_start(ap, fmt); |
397 | kprintf(fmt, TOLOG, NULL, NULL, ap); | | 384 | kprintf(fmt, TOLOG, NULL, NULL, ap); |
398 | va_end(ap); | | 385 | va_end(ap); |
399 | if (!log_open) { | | 386 | if (!log_open) { |
400 | va_start(ap, fmt); | | 387 | va_start(ap, fmt); |
401 | kprintf(fmt, TOCONS, NULL, NULL, ap); | | 388 | kprintf(fmt, TOCONS, NULL, NULL, ap); |
402 | va_end(ap); | | 389 | va_end(ap); |
403 | } | | 390 | } |
404 | | | 391 | |
405 | kprintf_unlock(); | | 392 | kprintf_unlock(); |
406 | | | 393 | |
407 | logwakeup(); | | 394 | logwakeup(); |
408 | } | | 395 | } |
409 | | | 396 | |
410 | | | 397 | |
411 | /* | | 398 | /* |
412 | * putchar: print a single character on console or user terminal. | | 399 | * putchar: print a single character on console or user terminal. |
413 | * | | 400 | * |
414 | * => if console, then the last MSGBUFS chars are saved in msgbuf | | 401 | * => if console, then the last MSGBUFS chars are saved in msgbuf |
415 | * for inspection later (e.g. dmesg/syslog) | | 402 | * for inspection later (e.g. dmesg/syslog) |
416 | * => we must already be in the mutex! | | 403 | * => we must already be in the mutex! |
417 | */ | | 404 | */ |
418 | static void | | 405 | static void |
419 | putchar(int c, int flags, struct tty *tp) | | 406 | putchar(int c, int flags, struct tty *tp) |
420 | { | | 407 | { |
421 | | | 408 | |
422 | if (panicstr) | | 409 | if (panicstr) |
423 | constty = NULL; | | 410 | constty = NULL; |
424 | if ((flags & TOCONS) && tp == NULL && constty) { | | 411 | if ((flags & TOCONS) && tp == NULL && constty) { |
425 | tp = constty; | | 412 | tp = constty; |
426 | flags |= TOTTY; | | 413 | flags |= TOTTY; |
427 | } | | 414 | } |
428 | if ((flags & TOTTY) && tp && | | 415 | if ((flags & TOTTY) && tp && |
429 | tputchar(c, flags, tp) < 0 && | | 416 | tputchar(c, flags, tp) < 0 && |
430 | (flags & TOCONS) && tp == constty) | | 417 | (flags & TOCONS) && tp == constty) |
431 | constty = NULL; | | 418 | constty = NULL; |
432 | if ((flags & TOLOG) && | | 419 | if ((flags & TOLOG) && |
433 | c != '\0' && c != '\r' && c != 0177) | | 420 | c != '\0' && c != '\r' && c != 0177) |
434 | logputchar(c); | | 421 | logputchar(c); |
435 | if ((flags & TOCONS) && constty == NULL && c != '\0') | | 422 | if ((flags & TOCONS) && constty == NULL && c != '\0') |
436 | (*v_putc)(c); | | 423 | (*v_putc)(c); |
437 | #ifdef DDB | | 424 | #ifdef DDB |
438 | if (flags & TODDB) | | 425 | if (flags & TODDB) |
439 | db_putchar(c); | | 426 | db_putchar(c); |
440 | #endif | | 427 | #endif |
441 | } | | 428 | } |
442 | | | 429 | |
443 | /* | | 430 | /* |
444 | * tablefull: warn that a system table is full | | 431 | * tablefull: warn that a system table is full |
445 | */ | | 432 | */ |
446 | | | 433 | |
447 | void | | 434 | void |
448 | tablefull(const char *tab, const char *hint) | | 435 | tablefull(const char *tab, const char *hint) |
449 | { | | 436 | { |
450 | if (hint) | | 437 | if (hint) |
451 | log(LOG_ERR, "%s: table is full - %s\n", tab, hint); | | 438 | log(LOG_ERR, "%s: table is full - %s\n", tab, hint); |
452 | else | | 439 | else |
453 | log(LOG_ERR, "%s: table is full\n", tab); | | 440 | log(LOG_ERR, "%s: table is full\n", tab); |
454 | } | | 441 | } |
455 | | | 442 | |
456 | | | 443 | |
457 | /* | | 444 | /* |
458 | * uprintf: print to the controlling tty of the current process | | 445 | * uprintf: print to the controlling tty of the current process |
459 | * | | 446 | * |
460 | * => we may block if the tty queue is full | | 447 | * => we may block if the tty queue is full |
461 | * => no message is printed if the queue doesn't clear in a reasonable | | 448 | * => no message is printed if the queue doesn't clear in a reasonable |
462 | * time | | 449 | * time |
463 | */ | | 450 | */ |
464 | | | 451 | |
465 | void | | 452 | void |
466 | uprintf(const char *fmt, ...) | | 453 | uprintf(const char *fmt, ...) |
467 | { | | 454 | { |
468 | struct proc *p = curproc; | | 455 | struct proc *p = curproc; |
469 | va_list ap; | | 456 | va_list ap; |
470 | | | 457 | |
471 | /* mutex_enter(proc_lock); XXXSMP */ | | 458 | /* mutex_enter(proc_lock); XXXSMP */ |
472 | | | 459 | |
473 | if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) { | | 460 | if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) { |
474 | /* No mutex needed; going to process TTY. */ | | 461 | /* No mutex needed; going to process TTY. */ |
475 | va_start(ap, fmt); | | 462 | va_start(ap, fmt); |
476 | kprintf(fmt, TOTTY, p->p_session->s_ttyp, NULL, ap); | | 463 | kprintf(fmt, TOTTY, p->p_session->s_ttyp, NULL, ap); |
477 | va_end(ap); | | 464 | va_end(ap); |
478 | } | | 465 | } |
479 | | | 466 | |
480 | /* mutex_exit(proc_lock); XXXSMP */ | | 467 | /* mutex_exit(proc_lock); XXXSMP */ |
481 | } | | 468 | } |
482 | | | 469 | |
483 | void | | 470 | void |
484 | uprintf_locked(const char *fmt, ...) | | 471 | uprintf_locked(const char *fmt, ...) |
485 | { | | 472 | { |
486 | struct proc *p = curproc; | | 473 | struct proc *p = curproc; |
487 | va_list ap; | | 474 | va_list ap; |
488 | | | 475 | |
489 | if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) { | | 476 | if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) { |
490 | /* No mutex needed; going to process TTY. */ | | 477 | /* No mutex needed; going to process TTY. */ |
491 | va_start(ap, fmt); | | 478 | va_start(ap, fmt); |
492 | kprintf(fmt, TOTTY, p->p_session->s_ttyp, NULL, ap); | | 479 | kprintf(fmt, TOTTY, p->p_session->s_ttyp, NULL, ap); |
493 | va_end(ap); | | 480 | va_end(ap); |
494 | } | | 481 | } |
495 | } | | 482 | } |
496 | | | 483 | |
497 | /* | | 484 | /* |
498 | * tprintf functions: used to send messages to a specific process | | 485 | * tprintf functions: used to send messages to a specific process |
499 | * | | 486 | * |
500 | * usage: | | 487 | * usage: |
501 | * get a tpr_t handle on a process "p" by using "tprintf_open(p)" | | 488 | * get a tpr_t handle on a process "p" by using "tprintf_open(p)" |
502 | * use the handle when calling "tprintf" | | 489 | * use the handle when calling "tprintf" |
503 | * when done, do a "tprintf_close" to drop the handle | | 490 | * when done, do a "tprintf_close" to drop the handle |
504 | */ | | 491 | */ |
505 | | | 492 | |
506 | /* | | 493 | /* |
507 | * tprintf_open: get a tprintf handle on a process "p" | | 494 | * tprintf_open: get a tprintf handle on a process "p" |
508 | * | | 495 | * |
509 | * => returns NULL if process can't be printed to | | 496 | * => returns NULL if process can't be printed to |
510 | */ | | 497 | */ |
511 | | | 498 | |
512 | tpr_t | | 499 | tpr_t |
513 | tprintf_open(struct proc *p) | | 500 | tprintf_open(struct proc *p) |
514 | { | | 501 | { |
515 | tpr_t cookie; | | 502 | tpr_t cookie; |
516 | | | 503 | |
517 | cookie = NULL; | | 504 | cookie = NULL; |
518 | | | 505 | |
519 | mutex_enter(proc_lock); | | 506 | mutex_enter(proc_lock); |
520 | if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) { | | 507 | if (p->p_lflag & PL_CONTROLT && p->p_session->s_ttyvp) { |
521 | proc_sesshold(p->p_session); | | 508 | proc_sesshold(p->p_session); |
522 | cookie = (tpr_t)p->p_session; | | 509 | cookie = (tpr_t)p->p_session; |
523 | } | | 510 | } |
524 | mutex_exit(proc_lock); | | 511 | mutex_exit(proc_lock); |
525 | | | 512 | |
526 | return cookie; | | 513 | return cookie; |
527 | } | | 514 | } |
528 | | | 515 | |
529 | /* | | 516 | /* |
530 | * tprintf_close: dispose of a tprintf handle obtained with tprintf_open | | 517 | * tprintf_close: dispose of a tprintf handle obtained with tprintf_open |
531 | */ | | 518 | */ |
532 | | | 519 | |
533 | void | | 520 | void |
534 | tprintf_close(tpr_t sess) | | 521 | tprintf_close(tpr_t sess) |
535 | { | | 522 | { |
536 | | | 523 | |
537 | if (sess) { | | 524 | if (sess) { |
538 | mutex_enter(proc_lock); | | 525 | mutex_enter(proc_lock); |
539 | /* Releases proc_lock. */ | | 526 | /* Releases proc_lock. */ |
540 | proc_sessrele((struct session *)sess); | | 527 | proc_sessrele((struct session *)sess); |
541 | } | | 528 | } |
542 | } | | 529 | } |
543 | | | 530 | |
544 | /* | | 531 | /* |
545 | * tprintf: given tprintf handle to a process [obtained with tprintf_open], | | 532 | * tprintf: given tprintf handle to a process [obtained with tprintf_open], |
546 | * send a message to the controlling tty for that process. | | 533 | * send a message to the controlling tty for that process. |
547 | * | | 534 | * |
548 | * => also sends message to /dev/klog | | 535 | * => also sends message to /dev/klog |
549 | */ | | 536 | */ |
550 | void | | 537 | void |
551 | tprintf(tpr_t tpr, const char *fmt, ...) | | 538 | tprintf(tpr_t tpr, const char *fmt, ...) |
552 | { | | 539 | { |
553 | struct session *sess = (struct session *)tpr; | | 540 | struct session *sess = (struct session *)tpr; |
554 | struct tty *tp = NULL; | | 541 | struct tty *tp = NULL; |
555 | int flags = TOLOG; | | 542 | int flags = TOLOG; |
556 | va_list ap; | | 543 | va_list ap; |
557 | | | 544 | |
558 | /* mutex_enter(proc_lock); XXXSMP */ | | 545 | /* mutex_enter(proc_lock); XXXSMP */ |
559 | if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { | | 546 | if (sess && sess->s_ttyvp && ttycheckoutq(sess->s_ttyp, 0)) { |
560 | flags |= TOTTY; | | 547 | flags |= TOTTY; |
561 | tp = sess->s_ttyp; | | 548 | tp = sess->s_ttyp; |
562 | } | | 549 | } |
563 | | | 550 | |
564 | kprintf_lock(); | | 551 | kprintf_lock(); |
565 | | | 552 | |
566 | klogpri(LOG_INFO); | | 553 | klogpri(LOG_INFO); |
567 | va_start(ap, fmt); | | 554 | va_start(ap, fmt); |
568 | kprintf(fmt, flags, tp, NULL, ap); | | 555 | kprintf(fmt, flags, tp, NULL, ap); |
569 | va_end(ap); | | 556 | va_end(ap); |
570 | | | 557 | |
571 | kprintf_unlock(); | | 558 | kprintf_unlock(); |
572 | /* mutex_exit(proc_lock); XXXSMP */ | | 559 | /* mutex_exit(proc_lock); XXXSMP */ |
573 | | | 560 | |
574 | logwakeup(); | | 561 | logwakeup(); |
575 | } | | 562 | } |
576 | | | 563 | |
577 | | | 564 | |
578 | /* | | 565 | /* |
579 | * ttyprintf: send a message to a specific tty | | 566 | * ttyprintf: send a message to a specific tty |
580 | * | | 567 | * |
581 | * => should be used only by tty driver or anything that knows the | | 568 | * => should be used only by tty driver or anything that knows the |
582 | * underlying tty will not be revoked(2)'d away. [otherwise, | | 569 | * underlying tty will not be revoked(2)'d away. [otherwise, |
583 | * use tprintf] | | 570 | * use tprintf] |
584 | */ | | 571 | */ |
585 | void | | 572 | void |
586 | ttyprintf(struct tty *tp, const char *fmt, ...) | | 573 | ttyprintf(struct tty *tp, const char *fmt, ...) |
587 | { | | 574 | { |
588 | va_list ap; | | 575 | va_list ap; |
589 | | | 576 | |
590 | /* No mutex needed; going to process TTY. */ | | 577 | /* No mutex needed; going to process TTY. */ |
591 | va_start(ap, fmt); | | 578 | va_start(ap, fmt); |
592 | kprintf(fmt, TOTTY, tp, NULL, ap); | | 579 | kprintf(fmt, TOTTY, tp, NULL, ap); |
593 | va_end(ap); | | 580 | va_end(ap); |
594 | } | | 581 | } |
595 | | | 582 | |
596 | #ifdef DDB | | 583 | #ifdef DDB |
597 | | | 584 | |
598 | /* | | 585 | /* |
599 | * db_printf: printf for DDB (via db_putchar) | | 586 | * db_printf: printf for DDB (via db_putchar) |
600 | */ | | 587 | */ |
601 | | | 588 | |
602 | void | | 589 | void |
603 | db_printf(const char *fmt, ...) | | 590 | db_printf(const char *fmt, ...) |
604 | { | | 591 | { |
605 | va_list ap; | | 592 | va_list ap; |
606 | | | 593 | |
607 | /* No mutex needed; DDB pauses all processors. */ | | 594 | /* No mutex needed; DDB pauses all processors. */ |
608 | va_start(ap, fmt); | | 595 | va_start(ap, fmt); |
609 | kprintf(fmt, TODDB, NULL, NULL, ap); | | 596 | kprintf(fmt, TODDB, NULL, NULL, ap); |
610 | va_end(ap); | | 597 | va_end(ap); |
611 | | | 598 | |
612 | if (db_tee_msgbuf) { | | 599 | if (db_tee_msgbuf) { |
613 | va_start(ap, fmt); | | 600 | va_start(ap, fmt); |
614 | kprintf(fmt, TOLOG, NULL, NULL, ap); | | 601 | kprintf(fmt, TOLOG, NULL, NULL, ap); |
615 | va_end(ap); | | 602 | va_end(ap); |
616 | }; | | 603 | }; |
617 | } | | 604 | } |
618 | | | 605 | |
619 | void | | 606 | void |
620 | db_vprintf(const char *fmt, va_list ap) | | 607 | db_vprintf(const char *fmt, va_list ap) |
621 | { | | 608 | { |
622 | va_list cap; | | 609 | va_list cap; |
623 | | | 610 | |
624 | va_copy(cap, ap); | | 611 | va_copy(cap, ap); |
625 | /* No mutex needed; DDB pauses all processors. */ | | 612 | /* No mutex needed; DDB pauses all processors. */ |
626 | kprintf(fmt, TODDB, NULL, NULL, ap); | | 613 | kprintf(fmt, TODDB, NULL, NULL, ap); |
627 | if (db_tee_msgbuf) | | 614 | if (db_tee_msgbuf) |
628 | kprintf(fmt, TOLOG, NULL, NULL, cap); | | 615 | kprintf(fmt, TOLOG, NULL, NULL, cap); |
629 | va_end(cap); | | 616 | va_end(cap); |
630 | } | | 617 | } |
631 | | | 618 | |
632 | #endif /* DDB */ | | 619 | #endif /* DDB */ |
633 | | | 620 | |
634 | static void | | 621 | static void |
635 | kprintf_internal(const char *fmt, int oflags, void *vp, char *sbuf, ...) | | 622 | kprintf_internal(const char *fmt, int oflags, void *vp, char *sbuf, ...) |
636 | { | | 623 | { |
637 | va_list ap; | | 624 | va_list ap; |
638 | | | 625 | |
639 | va_start(ap, sbuf); | | 626 | va_start(ap, sbuf); |
640 | (void)kprintf(fmt, oflags, vp, sbuf, ap); | | 627 | (void)kprintf(fmt, oflags, vp, sbuf, ap); |
641 | va_end(ap); | | 628 | va_end(ap); |
642 | } | | 629 | } |
643 | | | 630 | |
644 | /* | | 631 | /* |
645 | * Device autoconfiguration printf routines. These change their | | 632 | * Device autoconfiguration printf routines. These change their |
646 | * behavior based on the AB_* flags in boothowto. If AB_SILENT | | 633 | * behavior based on the AB_* flags in boothowto. If AB_SILENT |
647 | * is set, messages never go to the console (but they still always | | 634 | * is set, messages never go to the console (but they still always |
648 | * go to the log). AB_VERBOSE overrides AB_SILENT. | | 635 | * go to the log). AB_VERBOSE overrides AB_SILENT. |
649 | */ | | 636 | */ |
650 | | | 637 | |
651 | /* | | 638 | /* |
652 | * aprint_normal: Send to console unless AB_QUIET. Always goes | | 639 | * aprint_normal: Send to console unless AB_QUIET. Always goes |
653 | * to the log. | | 640 | * to the log. |
654 | */ | | 641 | */ |
655 | static void | | 642 | static void |
656 | aprint_normal_internal(const char *prefix, const char *fmt, va_list ap) | | 643 | aprint_normal_internal(const char *prefix, const char *fmt, va_list ap) |
657 | { | | 644 | { |
658 | int flags = TOLOG; | | 645 | int flags = TOLOG; |
659 | | | 646 | |
660 | if ((boothowto & (AB_SILENT|AB_QUIET)) == 0 || | | 647 | if ((boothowto & (AB_SILENT|AB_QUIET)) == 0 || |
661 | (boothowto & AB_VERBOSE) != 0) | | 648 | (boothowto & AB_VERBOSE) != 0) |
662 | flags |= TOCONS; | | 649 | flags |= TOCONS; |
663 | | | 650 | |
664 | kprintf_lock(); | | 651 | kprintf_lock(); |
665 | | | 652 | |
666 | if (prefix) | | 653 | if (prefix) |
667 | kprintf_internal("%s: ", flags, NULL, NULL, prefix); | | 654 | kprintf_internal("%s: ", flags, NULL, NULL, prefix); |
668 | kprintf(fmt, flags, NULL, NULL, ap); | | 655 | kprintf(fmt, flags, NULL, NULL, ap); |
669 | | | 656 | |
670 | kprintf_unlock(); | | 657 | kprintf_unlock(); |
671 | | | 658 | |
672 | if (!panicstr) | | 659 | if (!panicstr) |
673 | logwakeup(); | | 660 | logwakeup(); |
674 | } | | 661 | } |
675 | | | 662 | |
676 | void | | 663 | void |
677 | aprint_normal(const char *fmt, ...) | | 664 | aprint_normal(const char *fmt, ...) |
678 | { | | 665 | { |
679 | va_list ap; | | 666 | va_list ap; |
680 | | | 667 | |
681 | va_start(ap, fmt); | | 668 | va_start(ap, fmt); |
682 | aprint_normal_internal(NULL, fmt, ap); | | 669 | aprint_normal_internal(NULL, fmt, ap); |
683 | va_end(ap); | | 670 | va_end(ap); |
684 | } | | 671 | } |
685 | | | 672 | |
686 | void | | 673 | void |
687 | aprint_normal_dev(device_t dv, const char *fmt, ...) | | 674 | aprint_normal_dev(device_t dv, const char *fmt, ...) |
688 | { | | 675 | { |
689 | va_list ap; | | 676 | va_list ap; |
690 | | | 677 | |
691 | va_start(ap, fmt); | | 678 | va_start(ap, fmt); |
692 | aprint_normal_internal(device_xname(dv), fmt, ap); | | 679 | aprint_normal_internal(device_xname(dv), fmt, ap); |
693 | va_end(ap); | | 680 | va_end(ap); |
694 | } | | 681 | } |
695 | | | 682 | |
696 | void | | 683 | void |
697 | aprint_normal_ifnet(struct ifnet *ifp, const char *fmt, ...) | | 684 | aprint_normal_ifnet(struct ifnet *ifp, const char *fmt, ...) |
698 | { | | 685 | { |
699 | va_list ap; | | 686 | va_list ap; |
700 | | | 687 | |
701 | va_start(ap, fmt); | | 688 | va_start(ap, fmt); |
702 | aprint_normal_internal(ifp->if_xname, fmt, ap); | | 689 | aprint_normal_internal(ifp->if_xname, fmt, ap); |
703 | va_end(ap); | | 690 | va_end(ap); |
704 | } | | 691 | } |
705 | | | 692 | |
706 | /* | | 693 | /* |
707 | * aprint_error: Send to console unless AB_QUIET. Always goes | | 694 | * aprint_error: Send to console unless AB_QUIET. Always goes |
708 | * to the log. Also counts the number of times called so other | | 695 | * to the log. Also counts the number of times called so other |
709 | * parts of the kernel can report the number of errors during a | | 696 | * parts of the kernel can report the number of errors during a |
710 | * given phase of system startup. | | 697 | * given phase of system startup. |
711 | */ | | 698 | */ |
712 | static int aprint_error_count; | | 699 | static int aprint_error_count; |
713 | | | 700 | |
714 | int | | 701 | int |
715 | aprint_get_error_count(void) | | 702 | aprint_get_error_count(void) |
716 | { | | 703 | { |
717 | int count; | | 704 | int count; |
718 | | | 705 | |
719 | kprintf_lock(); | | 706 | kprintf_lock(); |
720 | | | 707 | |
721 | count = aprint_error_count; | | 708 | count = aprint_error_count; |
722 | aprint_error_count = 0; | | 709 | aprint_error_count = 0; |
723 | | | 710 | |
724 | kprintf_unlock(); | | 711 | kprintf_unlock(); |
725 | | | 712 | |
726 | return (count); | | 713 | return (count); |
727 | } | | 714 | } |
728 | | | 715 | |
729 | static void | | 716 | static void |
730 | aprint_error_internal(const char *prefix, const char *fmt, va_list ap) | | 717 | aprint_error_internal(const char *prefix, const char *fmt, va_list ap) |
731 | { | | 718 | { |
732 | int flags = TOLOG; | | 719 | int flags = TOLOG; |
733 | | | 720 | |
734 | if ((boothowto & (AB_SILENT|AB_QUIET)) == 0 || | | 721 | if ((boothowto & (AB_SILENT|AB_QUIET)) == 0 || |
735 | (boothowto & AB_VERBOSE) != 0) | | 722 | (boothowto & AB_VERBOSE) != 0) |
736 | flags |= TOCONS; | | 723 | flags |= TOCONS; |
737 | | | 724 | |
738 | kprintf_lock(); | | 725 | kprintf_lock(); |
739 | | | 726 | |
740 | aprint_error_count++; | | 727 | aprint_error_count++; |
741 | | | 728 | |
742 | if (prefix) | | 729 | if (prefix) |
743 | kprintf_internal("%s: ", flags, NULL, NULL, prefix); | | 730 | kprintf_internal("%s: ", flags, NULL, NULL, prefix); |
744 | kprintf(fmt, flags, NULL, NULL, ap); | | 731 | kprintf(fmt, flags, NULL, NULL, ap); |
745 | | | 732 | |
746 | kprintf_unlock(); | | 733 | kprintf_unlock(); |
747 | | | 734 | |
748 | if (!panicstr) | | 735 | if (!panicstr) |
749 | logwakeup(); | | 736 | logwakeup(); |
750 | } | | 737 | } |
751 | | | 738 | |
752 | void | | 739 | void |
753 | aprint_error(const char *fmt, ...) | | 740 | aprint_error(const char *fmt, ...) |
754 | { | | 741 | { |
755 | va_list ap; | | 742 | va_list ap; |
756 | | | 743 | |
757 | va_start(ap, fmt); | | 744 | va_start(ap, fmt); |
758 | aprint_error_internal(NULL, fmt, ap); | | 745 | aprint_error_internal(NULL, fmt, ap); |
759 | va_end(ap); | | 746 | va_end(ap); |
760 | } | | 747 | } |
761 | | | 748 | |
762 | void | | 749 | void |
763 | aprint_error_dev(device_t dv, const char *fmt, ...) | | 750 | aprint_error_dev(device_t dv, const char *fmt, ...) |
764 | { | | 751 | { |
765 | va_list ap; | | 752 | va_list ap; |
766 | | | 753 | |
767 | va_start(ap, fmt); | | 754 | va_start(ap, fmt); |
768 | aprint_error_internal(device_xname(dv), fmt, ap); | | 755 | aprint_error_internal(device_xname(dv), fmt, ap); |
769 | va_end(ap); | | 756 | va_end(ap); |
770 | } | | 757 | } |
771 | | | 758 | |
772 | void | | 759 | void |
773 | aprint_error_ifnet(struct ifnet *ifp, const char *fmt, ...) | | 760 | aprint_error_ifnet(struct ifnet *ifp, const char *fmt, ...) |
774 | { | | 761 | { |
775 | va_list ap; | | 762 | va_list ap; |
776 | | | 763 | |
777 | va_start(ap, fmt); | | 764 | va_start(ap, fmt); |
778 | aprint_error_internal(ifp->if_xname, fmt, ap); | | 765 | aprint_error_internal(ifp->if_xname, fmt, ap); |
779 | va_end(ap); | | 766 | va_end(ap); |
780 | } | | 767 | } |
781 | | | 768 | |
782 | /* | | 769 | /* |
783 | * aprint_naive: Send to console only if AB_QUIET. Never goes | | 770 | * aprint_naive: Send to console only if AB_QUIET. Never goes |
784 | * to the log. | | 771 | * to the log. |
785 | */ | | 772 | */ |
786 | static void | | 773 | static void |
787 | aprint_naive_internal(const char *prefix, const char *fmt, va_list ap) | | 774 | aprint_naive_internal(const char *prefix, const char *fmt, va_list ap) |
788 | { | | 775 | { |
789 | | | 776 | |
790 | if ((boothowto & (AB_QUIET|AB_SILENT|AB_VERBOSE)) != AB_QUIET) | | 777 | if ((boothowto & (AB_QUIET|AB_SILENT|AB_VERBOSE)) != AB_QUIET) |
791 | return; | | 778 | return; |
792 | | | 779 | |
793 | kprintf_lock(); | | 780 | kprintf_lock(); |
794 | | | 781 | |
795 | if (prefix) | | 782 | if (prefix) |
796 | kprintf_internal("%s: ", TOCONS, NULL, NULL, prefix); | | 783 | kprintf_internal("%s: ", TOCONS, NULL, NULL, prefix); |
797 | kprintf(fmt, TOCONS, NULL, NULL, ap); | | 784 | kprintf(fmt, TOCONS, NULL, NULL, ap); |
798 | | | 785 | |
799 | kprintf_unlock(); | | 786 | kprintf_unlock(); |
800 | } | | 787 | } |
801 | | | 788 | |
802 | void | | 789 | void |
803 | aprint_naive(const char *fmt, ...) | | 790 | aprint_naive(const char *fmt, ...) |
804 | { | | 791 | { |
805 | va_list ap; | | 792 | va_list ap; |
806 | | | 793 | |
807 | va_start(ap, fmt); | | 794 | va_start(ap, fmt); |
808 | aprint_naive_internal(NULL, fmt, ap); | | 795 | aprint_naive_internal(NULL, fmt, ap); |
809 | va_end(ap); | | 796 | va_end(ap); |
810 | } | | 797 | } |
811 | | | 798 | |
812 | void | | 799 | void |
813 | aprint_naive_dev(device_t dv, const char *fmt, ...) | | 800 | aprint_naive_dev(device_t dv, const char *fmt, ...) |
814 | { | | 801 | { |
815 | va_list ap; | | 802 | va_list ap; |
816 | | | 803 | |
817 | va_start(ap, fmt); | | 804 | va_start(ap, fmt); |
818 | aprint_naive_internal(device_xname(dv), fmt, ap); | | 805 | aprint_naive_internal(device_xname(dv), fmt, ap); |
819 | va_end(ap); | | 806 | va_end(ap); |
820 | } | | 807 | } |
821 | | | 808 | |
822 | void | | 809 | void |
823 | aprint_naive_ifnet(struct ifnet *ifp, const char *fmt, ...) | | 810 | aprint_naive_ifnet(struct ifnet *ifp, const char *fmt, ...) |
824 | { | | 811 | { |
825 | va_list ap; | | 812 | va_list ap; |
826 | | | 813 | |
827 | va_start(ap, fmt); | | 814 | va_start(ap, fmt); |
828 | aprint_naive_internal(ifp->if_xname, fmt, ap); | | 815 | aprint_naive_internal(ifp->if_xname, fmt, ap); |
829 | va_end(ap); | | 816 | va_end(ap); |
830 | } | | 817 | } |
831 | | | 818 | |
832 | /* | | 819 | /* |
833 | * aprint_verbose: Send to console only if AB_VERBOSE. Always | | 820 | * aprint_verbose: Send to console only if AB_VERBOSE. Always |
834 | * goes to the log. | | 821 | * goes to the log. |
835 | */ | | 822 | */ |
836 | static void | | 823 | static void |
837 | aprint_verbose_internal(const char *prefix, const char *fmt, va_list ap) | | 824 | aprint_verbose_internal(const char *prefix, const char *fmt, va_list ap) |
838 | { | | 825 | { |
839 | int flags = TOLOG; | | 826 | int flags = TOLOG; |
840 | | | 827 | |
841 | if (boothowto & AB_VERBOSE) | | 828 | if (boothowto & AB_VERBOSE) |
842 | flags |= TOCONS; | | 829 | flags |= TOCONS; |
843 | | | 830 | |
844 | kprintf_lock(); | | 831 | kprintf_lock(); |
845 | | | 832 | |
846 | if (prefix) | | 833 | if (prefix) |
847 | kprintf_internal("%s: ", flags, NULL, NULL, prefix); | | 834 | kprintf_internal("%s: ", flags, NULL, NULL, prefix); |
848 | kprintf(fmt, flags, NULL, NULL, ap); | | 835 | kprintf(fmt, flags, NULL, NULL, ap); |
849 | | | 836 | |
850 | kprintf_unlock(); | | 837 | kprintf_unlock(); |
851 | | | 838 | |
852 | if (!panicstr) | | 839 | if (!panicstr) |
853 | logwakeup(); | | 840 | logwakeup(); |
854 | } | | 841 | } |
855 | | | 842 | |
856 | void | | 843 | void |
857 | aprint_verbose(const char *fmt, ...) | | 844 | aprint_verbose(const char *fmt, ...) |
858 | { | | 845 | { |
859 | va_list ap; | | 846 | va_list ap; |
860 | | | 847 | |
861 | va_start(ap, fmt); | | 848 | va_start(ap, fmt); |
862 | aprint_verbose_internal(NULL, fmt, ap); | | 849 | aprint_verbose_internal(NULL, fmt, ap); |
863 | va_end(ap); | | 850 | va_end(ap); |
864 | } | | 851 | } |
865 | | | 852 | |
866 | void | | 853 | void |
867 | aprint_verbose_dev(device_t dv, const char *fmt, ...) | | 854 | aprint_verbose_dev(device_t dv, const char *fmt, ...) |
868 | { | | 855 | { |
869 | va_list ap; | | 856 | va_list ap; |
870 | | | 857 | |
871 | va_start(ap, fmt); | | 858 | va_start(ap, fmt); |
872 | aprint_verbose_internal(device_xname(dv), fmt, ap); | | 859 | aprint_verbose_internal(device_xname(dv), fmt, ap); |
873 | va_end(ap); | | 860 | va_end(ap); |
874 | } | | 861 | } |
875 | | | 862 | |
876 | void | | 863 | void |
877 | aprint_verbose_ifnet(struct ifnet *ifp, const char *fmt, ...) | | 864 | aprint_verbose_ifnet(struct ifnet *ifp, const char *fmt, ...) |
878 | { | | 865 | { |
879 | va_list ap; | | 866 | va_list ap; |
880 | | | 867 | |
881 | va_start(ap, fmt); | | 868 | va_start(ap, fmt); |
882 | aprint_verbose_internal(ifp->if_xname, fmt, ap); | | 869 | aprint_verbose_internal(ifp->if_xname, fmt, ap); |
883 | va_end(ap); | | 870 | va_end(ap); |
884 | } | | 871 | } |
885 | | | 872 | |
886 | /* | | 873 | /* |
887 | * aprint_debug: Send to console and log only if AB_DEBUG. | | 874 | * aprint_debug: Send to console and log only if AB_DEBUG. |
888 | */ | | 875 | */ |
889 | static void | | 876 | static void |
890 | aprint_debug_internal(const char *prefix, const char *fmt, va_list ap) | | 877 | aprint_debug_internal(const char *prefix, const char *fmt, va_list ap) |
891 | { | | 878 | { |
892 | | | 879 | |
893 | if ((boothowto & AB_DEBUG) == 0) | | 880 | if ((boothowto & AB_DEBUG) == 0) |
894 | return; | | 881 | return; |
895 | | | 882 | |
896 | kprintf_lock(); | | 883 | kprintf_lock(); |
897 | | | 884 | |
898 | if (prefix) | | 885 | if (prefix) |
899 | kprintf_internal("%s: ", TOCONS | TOLOG, NULL, NULL, prefix); | | 886 | kprintf_internal("%s: ", TOCONS | TOLOG, NULL, NULL, prefix); |
900 | kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap); | | 887 | kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap); |
901 | | | 888 | |
902 | kprintf_unlock(); | | 889 | kprintf_unlock(); |
903 | } | | 890 | } |
904 | | | 891 | |
905 | void | | 892 | void |
906 | aprint_debug(const char *fmt, ...) | | 893 | aprint_debug(const char *fmt, ...) |
907 | { | | 894 | { |
908 | va_list ap; | | 895 | va_list ap; |
909 | | | 896 | |
910 | va_start(ap, fmt); | | 897 | va_start(ap, fmt); |
911 | aprint_debug_internal(NULL, fmt, ap); | | 898 | aprint_debug_internal(NULL, fmt, ap); |
912 | va_end(ap); | | 899 | va_end(ap); |
913 | } | | 900 | } |
914 | | | 901 | |
915 | void | | 902 | void |
916 | aprint_debug_dev(device_t dv, const char *fmt, ...) | | 903 | aprint_debug_dev(device_t dv, const char *fmt, ...) |
917 | { | | 904 | { |
918 | va_list ap; | | 905 | va_list ap; |
919 | | | 906 | |
920 | va_start(ap, fmt); | | 907 | va_start(ap, fmt); |
921 | aprint_debug_internal(device_xname(dv), fmt, ap); | | 908 | aprint_debug_internal(device_xname(dv), fmt, ap); |
922 | va_end(ap); | | 909 | va_end(ap); |
923 | } | | 910 | } |
924 | | | 911 | |
925 | void | | 912 | void |
926 | aprint_debug_ifnet(struct ifnet *ifp, const char *fmt, ...) | | 913 | aprint_debug_ifnet(struct ifnet *ifp, const char *fmt, ...) |
927 | { | | 914 | { |
928 | va_list ap; | | 915 | va_list ap; |
929 | | | 916 | |
930 | va_start(ap, fmt); | | 917 | va_start(ap, fmt); |
931 | aprint_debug_internal(ifp->if_xname, fmt, ap); | | 918 | aprint_debug_internal(ifp->if_xname, fmt, ap); |
932 | va_end(ap); | | 919 | va_end(ap); |
933 | } | | 920 | } |
934 | | | 921 | |
935 | void | | 922 | void |
936 | printf_tolog(const char *fmt, ...) | | 923 | printf_tolog(const char *fmt, ...) |
937 | { | | 924 | { |
938 | va_list ap; | | 925 | va_list ap; |
939 | | | 926 | |
940 | kprintf_lock(); | | 927 | kprintf_lock(); |
941 | | | 928 | |
942 | va_start(ap, fmt); | | 929 | va_start(ap, fmt); |
943 | (void)kprintf(fmt, TOLOG, NULL, NULL, ap); | | 930 | (void)kprintf(fmt, TOLOG, NULL, NULL, ap); |
944 | va_end(ap); | | 931 | va_end(ap); |
945 | | | 932 | |
946 | kprintf_unlock(); | | 933 | kprintf_unlock(); |
947 | } | | 934 | } |
948 | | | 935 | |
949 | /* | | 936 | /* |
950 | * printf_nolog: Like printf(), but does not send message to the log. | | 937 | * printf_nolog: Like printf(), but does not send message to the log. |
951 | */ | | 938 | */ |
952 | | | 939 | |
953 | void | | 940 | void |
954 | printf_nolog(const char *fmt, ...) | | 941 | printf_nolog(const char *fmt, ...) |
955 | { | | 942 | { |
956 | va_list ap; | | 943 | va_list ap; |
957 | | | 944 | |
958 | kprintf_lock(); | | 945 | kprintf_lock(); |
959 | | | 946 | |
960 | va_start(ap, fmt); | | 947 | va_start(ap, fmt); |
961 | kprintf(fmt, TOCONS, NULL, NULL, ap); | | 948 | kprintf(fmt, TOCONS, NULL, NULL, ap); |
962 | va_end(ap); | | 949 | va_end(ap); |
963 | | | 950 | |
964 | kprintf_unlock(); | | 951 | kprintf_unlock(); |
965 | } | | 952 | } |
966 | | | 953 | |
967 | /* | | 954 | /* |
968 | * normal kernel printf functions: printf, vprintf, snprintf, vsnprintf | | 955 | * normal kernel printf functions: printf, vprintf, snprintf, vsnprintf |
969 | */ | | 956 | */ |
970 | | | 957 | |
971 | /* | | 958 | /* |
972 | * printf: print a message to the console and the log | | 959 | * printf: print a message to the console and the log |
973 | */ | | 960 | */ |
974 | void | | 961 | void |
975 | printf(const char *fmt, ...) | | 962 | printf(const char *fmt, ...) |
976 | { | | 963 | { |
977 | va_list ap; | | 964 | va_list ap; |
978 | | | 965 | |
979 | kprintf_lock(); | | 966 | kprintf_lock(); |
980 | | | 967 | |
981 | va_start(ap, fmt); | | 968 | va_start(ap, fmt); |
982 | kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap); | | 969 | kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap); |
983 | va_end(ap); | | 970 | va_end(ap); |
984 | | | 971 | |
985 | kprintf_unlock(); | | 972 | kprintf_unlock(); |
986 | | | 973 | |
987 | if (!panicstr) | | 974 | if (!panicstr) |
988 | logwakeup(); | | 975 | logwakeup(); |
989 | } | | 976 | } |
990 | | | 977 | |
991 | /* | | 978 | /* |
992 | * vprintf: print a message to the console and the log [already have | | 979 | * vprintf: print a message to the console and the log [already have |
993 | * va_list] | | 980 | * va_list] |
994 | */ | | 981 | */ |
995 | | | 982 | |
996 | void | | 983 | void |
997 | vprintf(const char *fmt, va_list ap) | | 984 | vprintf(const char *fmt, va_list ap) |
998 | { | | 985 | { |
999 | | | 986 | |
1000 | kprintf_lock(); | | 987 | kprintf_lock(); |
1001 | | | 988 | |
1002 | kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap); | | 989 | kprintf(fmt, TOCONS | TOLOG, NULL, NULL, ap); |
1003 | | | 990 | |
1004 | kprintf_unlock(); | | 991 | kprintf_unlock(); |
1005 | | | 992 | |
1006 | if (!panicstr) | | 993 | if (!panicstr) |
1007 | logwakeup(); | | 994 | logwakeup(); |
1008 | } | | 995 | } |
1009 | | | 996 | |
1010 | /* | | 997 | /* |
1011 | * sprintf: print a message to a buffer | | 998 | * sprintf: print a message to a buffer |
1012 | */ | | 999 | */ |
1013 | int | | 1000 | int |
1014 | sprintf(char *bf, const char *fmt, ...) | | 1001 | sprintf(char *bf, const char *fmt, ...) |
1015 | { | | 1002 | { |
1016 | int retval; | | 1003 | int retval; |
1017 | va_list ap; | | 1004 | va_list ap; |
1018 | | | 1005 | |
1019 | va_start(ap, fmt); | | 1006 | va_start(ap, fmt); |
1020 | retval = kprintf(fmt, TOBUFONLY, NULL, bf, ap); | | 1007 | retval = kprintf(fmt, TOBUFONLY, NULL, bf, ap); |
1021 | va_end(ap); | | 1008 | va_end(ap); |
1022 | if (bf) | | 1009 | if (bf) |
1023 | bf[retval] = '\0'; /* nul terminate */ | | 1010 | bf[retval] = '\0'; /* nul terminate */ |
1024 | return retval; | | 1011 | return retval; |
1025 | } | | 1012 | } |
1026 | | | 1013 | |
1027 | /* | | 1014 | /* |
1028 | * vsprintf: print a message to a buffer [already have va_list] | | 1015 | * vsprintf: print a message to a buffer [already have va_list] |
1029 | */ | | 1016 | */ |
1030 | | | 1017 | |
1031 | int | | 1018 | int |
1032 | vsprintf(char *bf, const char *fmt, va_list ap) | | 1019 | vsprintf(char *bf, const char *fmt, va_list ap) |
1033 | { | | 1020 | { |
1034 | int retval; | | 1021 | int retval; |
1035 | | | 1022 | |
1036 | retval = kprintf(fmt, TOBUFONLY, NULL, bf, ap); | | 1023 | retval = kprintf(fmt, TOBUFONLY, NULL, bf, ap); |
1037 | if (bf) | | 1024 | if (bf) |
1038 | bf[retval] = '\0'; /* nul terminate */ | | 1025 | bf[retval] = '\0'; /* nul terminate */ |
1039 | return retval; | | 1026 | return retval; |
1040 | } | | 1027 | } |
1041 | | | 1028 | |
1042 | /* | | 1029 | /* |
1043 | * snprintf: print a message to a buffer | | 1030 | * snprintf: print a message to a buffer |
1044 | */ | | 1031 | */ |
1045 | int | | 1032 | int |
1046 | snprintf(char *bf, size_t size, const char *fmt, ...) | | 1033 | snprintf(char *bf, size_t size, const char *fmt, ...) |
1047 | { | | 1034 | { |
1048 | int retval; | | 1035 | int retval; |
1049 | va_list ap; | | 1036 | va_list ap; |
1050 | | | 1037 | |
1051 | va_start(ap, fmt); | | 1038 | va_start(ap, fmt); |
1052 | retval = vsnprintf(bf, size, fmt, ap); | | 1039 | retval = vsnprintf(bf, size, fmt, ap); |
1053 | va_end(ap); | | 1040 | va_end(ap); |
1054 | | | 1041 | |
1055 | return retval; | | 1042 | return retval; |
1056 | } | | 1043 | } |
1057 | | | 1044 | |
1058 | /* | | 1045 | /* |
1059 | * vsnprintf: print a message to a buffer [already have va_list] | | 1046 | * vsnprintf: print a message to a buffer [already have va_list] |
1060 | */ | | 1047 | */ |
1061 | int | | 1048 | int |
1062 | vsnprintf(char *bf, size_t size, const char *fmt, va_list ap) | | 1049 | vsnprintf(char *bf, size_t size, const char *fmt, va_list ap) |
1063 | { | | 1050 | { |
1064 | int retval; | | 1051 | int retval; |
1065 | char *p; | | 1052 | char *p; |
1066 | | | 1053 | |
1067 | p = bf + size; | | 1054 | p = bf + size; |
1068 | retval = kprintf(fmt, TOBUFONLY, &p, bf, ap); | | 1055 | retval = kprintf(fmt, TOBUFONLY, &p, bf, ap); |
1069 | if (bf && size > 0) { | | 1056 | if (bf && size > 0) { |
1070 | /* nul terminate */ | | 1057 | /* nul terminate */ |
1071 | if (size <= (size_t)retval) | | 1058 | if (size <= (size_t)retval) |
1072 | bf[size - 1] = '\0'; | | 1059 | bf[size - 1] = '\0'; |
1073 | else | | 1060 | else |
1074 | bf[retval] = '\0'; | | 1061 | bf[retval] = '\0'; |
1075 | } | | 1062 | } |
1076 | return retval; | | 1063 | return retval; |
1077 | } | | 1064 | } |
1078 | | | 1065 | |
1079 | /* | | 1066 | /* |
1080 | * kprintf: scaled down version of printf(3). | | 1067 | * kprintf: scaled down version of printf(3). |
1081 | * | | 1068 | * |
1082 | * this version based on vfprintf() from libc which was derived from | | 1069 | * this version based on vfprintf() from libc which was derived from |
1083 | * software contributed to Berkeley by Chris Torek. | | 1070 | * software contributed to Berkeley by Chris Torek. |
1084 | * | | 1071 | * |
1085 | * NOTE: The kprintf mutex must be held if we're going TOBUF or TOCONS! | | 1072 | * NOTE: The kprintf mutex must be held if we're going TOBUF or TOCONS! |
1086 | */ | | 1073 | */ |
1087 | | | 1074 | |
1088 | /* | | 1075 | /* |
1089 | * macros for converting digits to letters and vice versa | | 1076 | * macros for converting digits to letters and vice versa |
1090 | */ | | 1077 | */ |
1091 | #define to_digit(c) ((c) - '0') | | 1078 | #define to_digit(c) ((c) - '0') |
1092 | #define is_digit(c) ((unsigned)to_digit(c) <= 9) | | 1079 | #define is_digit(c) ((unsigned)to_digit(c) <= 9) |
1093 | #define to_char(n) ((n) + '0') | | 1080 | #define to_char(n) ((n) + '0') |
1094 | | | 1081 | |
1095 | /* | | 1082 | /* |
1096 | * flags used during conversion. | | 1083 | * flags used during conversion. |
1097 | */ | | 1084 | */ |
1098 | #define ALT 0x001 /* alternate form */ | | 1085 | #define ALT 0x001 /* alternate form */ |
1099 | #define HEXPREFIX 0x002 /* add 0x or 0X prefix */ | | 1086 | #define HEXPREFIX 0x002 /* add 0x or 0X prefix */ |
1100 | #define LADJUST 0x004 /* left adjustment */ | | 1087 | #define LADJUST 0x004 /* left adjustment */ |
1101 | #define LONGDBL 0x008 /* long double; unimplemented */ | | 1088 | #define LONGDBL 0x008 /* long double; unimplemented */ |
1102 | #define LONGINT 0x010 /* long integer */ | | 1089 | #define LONGINT 0x010 /* long integer */ |
1103 | #define QUADINT 0x020 /* quad integer */ | | 1090 | #define QUADINT 0x020 /* quad integer */ |
1104 | #define SHORTINT 0x040 /* short integer */ | | 1091 | #define SHORTINT 0x040 /* short integer */ |
1105 | #define MAXINT 0x080 /* intmax_t */ | | 1092 | #define MAXINT 0x080 /* intmax_t */ |
1106 | #define PTRINT 0x100 /* intptr_t */ | | 1093 | #define PTRINT 0x100 /* intptr_t */ |
1107 | #define SIZEINT 0x200 /* size_t */ | | 1094 | #define SIZEINT 0x200 /* size_t */ |
1108 | #define ZEROPAD 0x400 /* zero (as opposed to blank) pad */ | | 1095 | #define ZEROPAD 0x400 /* zero (as opposed to blank) pad */ |
1109 | #define FPT 0x800 /* Floating point number */ | | 1096 | #define FPT 0x800 /* Floating point number */ |
1110 | | | 1097 | |
1111 | /* | | 1098 | /* |
1112 | * To extend shorts properly, we need both signed and unsigned | | 1099 | * To extend shorts properly, we need both signed and unsigned |
1113 | * argument extraction methods. | | 1100 | * argument extraction methods. |
1114 | */ | | 1101 | */ |
1115 | #define SARG() \ | | 1102 | #define SARG() \ |
1116 | (flags&MAXINT ? va_arg(ap, intmax_t) : \ | | 1103 | (flags&MAXINT ? va_arg(ap, intmax_t) : \ |
1117 | flags&PTRINT ? va_arg(ap, intptr_t) : \ | | 1104 | flags&PTRINT ? va_arg(ap, intptr_t) : \ |
1118 | flags&SIZEINT ? va_arg(ap, ssize_t) : /* XXX */ \ | | 1105 | flags&SIZEINT ? va_arg(ap, ssize_t) : /* XXX */ \ |
1119 | flags&QUADINT ? va_arg(ap, quad_t) : \ | | 1106 | flags&QUADINT ? va_arg(ap, quad_t) : \ |
1120 | flags&LONGINT ? va_arg(ap, long) : \ | | 1107 | flags&LONGINT ? va_arg(ap, long) : \ |
1121 | flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ | | 1108 | flags&SHORTINT ? (long)(short)va_arg(ap, int) : \ |
1122 | (long)va_arg(ap, int)) | | 1109 | (long)va_arg(ap, int)) |
1123 | #define UARG() \ | | 1110 | #define UARG() \ |
1124 | (flags&MAXINT ? va_arg(ap, uintmax_t) : \ | | 1111 | (flags&MAXINT ? va_arg(ap, uintmax_t) : \ |
1125 | flags&PTRINT ? va_arg(ap, uintptr_t) : \ | | 1112 | flags&PTRINT ? va_arg(ap, uintptr_t) : \ |
1126 | flags&SIZEINT ? va_arg(ap, size_t) : \ | | 1113 | flags&SIZEINT ? va_arg(ap, size_t) : \ |
1127 | flags&QUADINT ? va_arg(ap, u_quad_t) : \ | | 1114 | flags&QUADINT ? va_arg(ap, u_quad_t) : \ |
1128 | flags&LONGINT ? va_arg(ap, u_long) : \ | | 1115 | flags&LONGINT ? va_arg(ap, u_long) : \ |
1129 | flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \ | | 1116 | flags&SHORTINT ? (u_long)(u_short)va_arg(ap, int) : \ |
1130 | (u_long)va_arg(ap, u_int)) | | 1117 | (u_long)va_arg(ap, u_int)) |
1131 | | | 1118 | |
1132 | #define KPRINTF_PUTCHAR(C) { \ | | 1119 | #define KPRINTF_PUTCHAR(C) { \ |
1133 | if (oflags == TOBUFONLY) { \ | | 1120 | if (oflags == TOBUFONLY) { \ |
1134 | if (sbuf && ((vp == NULL) || (sbuf < tailp))) \ | | 1121 | if (sbuf && ((vp == NULL) || (sbuf < tailp))) \ |
1135 | *sbuf++ = (C); \ | | 1122 | *sbuf++ = (C); \ |
1136 | } else { \ | | 1123 | } else { \ |
1137 | putchar((C), oflags, vp); \ | | 1124 | putchar((C), oflags, vp); \ |
1138 | } \ | | 1125 | } \ |
1139 | } | | 1126 | } |
1140 | | | 1127 | |
1141 | void | | 1128 | void |
1142 | device_printf(device_t dev, const char *fmt, ...) | | 1129 | device_printf(device_t dev, const char *fmt, ...) |
1143 | { | | 1130 | { |
1144 | va_list ap; | | 1131 | va_list ap; |
1145 | | | 1132 | |
1146 | va_start(ap, fmt); | | 1133 | va_start(ap, fmt); |
1147 | printf("%s: ", device_xname(dev)); | | 1134 | printf("%s: ", device_xname(dev)); |
1148 | vprintf(fmt, ap); | | 1135 | vprintf(fmt, ap); |
1149 | va_end(ap); | | 1136 | va_end(ap); |
1150 | return; | | 1137 | return; |
1151 | } | | 1138 | } |
1152 | | | 1139 | |
1153 | /* | | 1140 | /* |
1154 | * Guts of kernel printf. Note, we already expect to be in a mutex! | | 1141 | * Guts of kernel printf. Note, we already expect to be in a mutex! |
1155 | */ | | 1142 | */ |
1156 | int | | 1143 | int |
1157 | kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap) | | 1144 | kprintf(const char *fmt0, int oflags, void *vp, char *sbuf, va_list ap) |
1158 | { | | 1145 | { |
1159 | const char *fmt; /* format string */ | | 1146 | const char *fmt; /* format string */ |
1160 | int ch; /* character from fmt */ | | 1147 | int ch; /* character from fmt */ |
1161 | int n; /* handy integer (short term usage) */ | | 1148 | int n; /* handy integer (short term usage) */ |
1162 | char *cp; /* handy char pointer (short term usage) */ | | 1149 | char *cp; /* handy char pointer (short term usage) */ |
1163 | int flags; /* flags as above */ | | 1150 | int flags; /* flags as above */ |
1164 | int ret; /* return value accumulator */ | | 1151 | int ret; /* return value accumulator */ |
1165 | int width; /* width from format (%8d), or 0 */ | | 1152 | int width; /* width from format (%8d), or 0 */ |
1166 | int prec; /* precision from format (%.3d), or -1 */ | | 1153 | int prec; /* precision from format (%.3d), or -1 */ |
1167 | char sign; /* sign prefix (' ', '+', '-', or \0) */ | | 1154 | char sign; /* sign prefix (' ', '+', '-', or \0) */ |
1168 | | | 1155 | |
1169 | u_quad_t _uquad; /* integer arguments %[diouxX] */ | | 1156 | u_quad_t _uquad; /* integer arguments %[diouxX] */ |
1170 | enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ | | 1157 | enum { OCT, DEC, HEX } base;/* base for [diouxX] conversion */ |
1171 | int dprec; /* a copy of prec if [diouxX], 0 otherwise */ | | 1158 | int dprec; /* a copy of prec if [diouxX], 0 otherwise */ |
1172 | int realsz; /* field size expanded by dprec */ | | 1159 | int realsz; /* field size expanded by dprec */ |
1173 | int size; /* size of converted field or string */ | | 1160 | int size; /* size of converted field or string */ |
1174 | const char *xdigs; /* digits for [xX] conversion */ | | 1161 | const char *xdigs; /* digits for [xX] conversion */ |
1175 | char bf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */ | | 1162 | char bf[KPRINTF_BUFSIZE]; /* space for %c, %[diouxX] */ |
1176 | char *tailp; /* tail pointer for snprintf */ | | 1163 | char *tailp; /* tail pointer for snprintf */ |
1177 | | | 1164 | |
1178 | if (oflags == TOBUFONLY && (vp != NULL)) | | 1165 | if (oflags == TOBUFONLY && (vp != NULL)) |
1179 | tailp = *(char **)vp; | | 1166 | tailp = *(char **)vp; |
1180 | else | | 1167 | else |
1181 | tailp = NULL; | | 1168 | tailp = NULL; |
1182 | | | 1169 | |
1183 | cp = NULL; /* XXX: shutup gcc */ | | 1170 | cp = NULL; /* XXX: shutup gcc */ |
1184 | size = 0; /* XXX: shutup gcc */ | | 1171 | size = 0; /* XXX: shutup gcc */ |
1185 | | | 1172 | |
1186 | fmt = fmt0; | | 1173 | fmt = fmt0; |
1187 | ret = 0; | | 1174 | ret = 0; |
1188 | | | 1175 | |
1189 | xdigs = NULL; /* XXX: shut up gcc warning */ | | 1176 | xdigs = NULL; /* XXX: shut up gcc warning */ |
1190 | | | 1177 | |
1191 | /* | | 1178 | /* |
1192 | * Scan the format for conversions (`%' character). | | 1179 | * Scan the format for conversions (`%' character). |
1193 | */ | | 1180 | */ |
1194 | for (;;) { | | 1181 | for (;;) { |
1195 | for (; *fmt != '%' && *fmt; fmt++) { | | 1182 | for (; *fmt != '%' && *fmt; fmt++) { |
1196 | ret++; | | 1183 | ret++; |
1197 | KPRINTF_PUTCHAR(*fmt); | | 1184 | KPRINTF_PUTCHAR(*fmt); |
1198 | } | | 1185 | } |
1199 | if (*fmt == 0) | | 1186 | if (*fmt == 0) |
1200 | goto done; | | 1187 | goto done; |
1201 | | | 1188 | |
1202 | fmt++; /* skip over '%' */ | | 1189 | fmt++; /* skip over '%' */ |
1203 | | | 1190 | |
1204 | flags = 0; | | 1191 | flags = 0; |
1205 | dprec = 0; | | 1192 | dprec = 0; |
1206 | width = 0; | | 1193 | width = 0; |
1207 | prec = -1; | | 1194 | prec = -1; |
1208 | sign = '\0'; | | 1195 | sign = '\0'; |
1209 | | | 1196 | |
1210 | rflag: ch = *fmt++; | | 1197 | rflag: ch = *fmt++; |
1211 | reswitch: switch (ch) { | | 1198 | reswitch: switch (ch) { |
1212 | case ' ': | | 1199 | case ' ': |
1213 | /* | | 1200 | /* |
1214 | * ``If the space and + flags both appear, the space | | 1201 | * ``If the space and + flags both appear, the space |
1215 | * flag will be ignored.'' | | 1202 | * flag will be ignored.'' |
1216 | * -- ANSI X3J11 | | 1203 | * -- ANSI X3J11 |
1217 | */ | | 1204 | */ |
1218 | if (!sign) | | 1205 | if (!sign) |
1219 | sign = ' '; | | 1206 | sign = ' '; |
1220 | goto rflag; | | 1207 | goto rflag; |
1221 | case '#': | | 1208 | case '#': |
1222 | flags |= ALT; | | 1209 | flags |= ALT; |
1223 | goto rflag; | | 1210 | goto rflag; |
1224 | case '*': | | 1211 | case '*': |
1225 | /* | | 1212 | /* |
1226 | * ``A negative field width argument is taken as a | | 1213 | * ``A negative field width argument is taken as a |
1227 | * - flag followed by a positive field width.'' | | 1214 | * - flag followed by a positive field width.'' |
1228 | * -- ANSI X3J11 | | 1215 | * -- ANSI X3J11 |
1229 | * They don't exclude field widths read from args. | | 1216 | * They don't exclude field widths read from args. |
1230 | */ | | 1217 | */ |
1231 | if ((width = va_arg(ap, int)) >= 0) | | 1218 | if ((width = va_arg(ap, int)) >= 0) |
1232 | goto rflag; | | 1219 | goto rflag; |
1233 | width = -width; | | 1220 | width = -width; |
1234 | /* FALLTHROUGH */ | | 1221 | /* FALLTHROUGH */ |
1235 | case '-': | | 1222 | case '-': |
1236 | flags |= LADJUST; | | 1223 | flags |= LADJUST; |
1237 | goto rflag; | | 1224 | goto rflag; |
1238 | case '+': | | 1225 | case '+': |
1239 | sign = '+'; | | 1226 | sign = '+'; |
1240 | goto rflag; | | 1227 | goto rflag; |
1241 | case '.': | | 1228 | case '.': |
1242 | if ((ch = *fmt++) == '*') { | | 1229 | if ((ch = *fmt++) == '*') { |
1243 | n = va_arg(ap, int); | | 1230 | n = va_arg(ap, int); |
1244 | prec = n < 0 ? -1 : n; | | 1231 | prec = n < 0 ? -1 : n; |
1245 | goto rflag; | | 1232 | goto rflag; |
1246 | } | | 1233 | } |
1247 | n = 0; | | 1234 | n = 0; |
1248 | while (is_digit(ch)) { | | 1235 | while (is_digit(ch)) { |
1249 | n = 10 * n + to_digit(ch); | | 1236 | n = 10 * n + to_digit(ch); |
1250 | ch = *fmt++; | | 1237 | ch = *fmt++; |
1251 | } | | 1238 | } |
1252 | prec = n < 0 ? -1 : n; | | 1239 | prec = n < 0 ? -1 : n; |
1253 | goto reswitch; | | 1240 | goto reswitch; |
1254 | case '0': | | 1241 | case '0': |
1255 | /* | | 1242 | /* |
1256 | * ``Note that 0 is taken as a flag, not as the | | 1243 | * ``Note that 0 is taken as a flag, not as the |
1257 | * beginning of a field width.'' | | 1244 | * beginning of a field width.'' |
1258 | * -- ANSI X3J11 | | 1245 | * -- ANSI X3J11 |
1259 | */ | | 1246 | */ |
1260 | flags |= ZEROPAD; | | 1247 | flags |= ZEROPAD; |
1261 | goto rflag; | | 1248 | goto rflag; |
1262 | case '1': case '2': case '3': case '4': | | 1249 | case '1': case '2': case '3': case '4': |
1263 | case '5': case '6': case '7': case '8': case '9': | | 1250 | case '5': case '6': case '7': case '8': case '9': |
1264 | n = 0; | | 1251 | n = 0; |
1265 | do { | | 1252 | do { |
1266 | n = 10 * n + to_digit(ch); | | 1253 | n = 10 * n + to_digit(ch); |
1267 | ch = *fmt++; | | 1254 | ch = *fmt++; |
1268 | } while (is_digit(ch)); | | 1255 | } while (is_digit(ch)); |
1269 | width = n; | | 1256 | width = n; |
1270 | goto reswitch; | | 1257 | goto reswitch; |
1271 | case 'h': | | 1258 | case 'h': |
1272 | flags |= SHORTINT; | | 1259 | flags |= SHORTINT; |
1273 | goto rflag; | | 1260 | goto rflag; |
1274 | case 'j': | | 1261 | case 'j': |
1275 | flags |= MAXINT; | | 1262 | flags |= MAXINT; |
1276 | goto rflag; | | 1263 | goto rflag; |
1277 | case 'l': | | 1264 | case 'l': |
1278 | if (*fmt == 'l') { | | 1265 | if (*fmt == 'l') { |
1279 | fmt++; | | 1266 | fmt++; |
1280 | flags |= QUADINT; | | 1267 | flags |= QUADINT; |
1281 | } else { | | 1268 | } else { |
1282 | flags |= LONGINT; | | 1269 | flags |= LONGINT; |
1283 | } | | 1270 | } |
1284 | goto rflag; | | 1271 | goto rflag; |
1285 | case 'q': | | 1272 | case 'q': |
1286 | flags |= QUADINT; | | 1273 | flags |= QUADINT; |
1287 | goto rflag; | | 1274 | goto rflag; |
1288 | case 't': | | 1275 | case 't': |
1289 | flags |= PTRINT; | | 1276 | flags |= PTRINT; |
1290 | goto rflag; | | 1277 | goto rflag; |
1291 | case 'z': | | 1278 | case 'z': |
1292 | flags |= SIZEINT; | | 1279 | flags |= SIZEINT; |
1293 | goto rflag; | | 1280 | goto rflag; |
1294 | case 'c': | | 1281 | case 'c': |
1295 | *(cp = bf) = va_arg(ap, int); | | 1282 | *(cp = bf) = va_arg(ap, int); |