diff options
Diffstat (limited to 'kern/debug.c')
-rw-r--r-- | kern/debug.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/kern/debug.c b/kern/debug.c new file mode 100644 index 0000000..eda5b2a --- /dev/null +++ b/kern/debug.c @@ -0,0 +1,192 @@ +/* + * Mach Operating System + * Copyright (c) 1993 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#include <mach_kdb.h> +#include <norma_ipc.h> +#include <cpus.h> + +#include "cpu_number.h" +#include <kern/lock.h> +#include <sys/varargs.h> +#include <kern/thread.h> + + + +extern void cnputc(); +void Debugger(); + +#if MACH_KDB +extern int db_breakpoints_inserted; +#endif + +#if NCPUS>1 +simple_lock_data_t Assert_print_lock; /* uninited, we take our chances */ +#endif + +void +Assert(char *exp, char *file, int line) +{ +#if NCPUS > 1 + simple_lock(&Assert_print_lock); + printf("{%d} Assertion failed: file \"%s\", line %d\n", + cpu_number(), file, line); + simple_unlock(&Assert_print_lock); +#else + printf("Assertion `%s' failed in file \"%s\", line %d\n", + exp, file, line); +#endif + +#if MACH_KDB + if (db_breakpoints_inserted) +#endif + Debugger("assertion failure"); +} + +void Debugger(message) + char * message; +{ +#if !MACH_KDB + panic("Debugger invoked, but there isn't one!"); +#endif + +#ifdef lint + message++; +#endif /* lint */ + +#if defined(vax) || defined(PC532) + asm("bpt"); +#endif /* vax */ + +#ifdef sun3 + current_thread()->pcb->flag |= TRACE_KDB; + asm("orw #0x00008000,sr"); +#endif /* sun3 */ +#ifdef sun4 + current_thread()->pcb->pcb_flag |= TRACE_KDB; + asm("ta 0x81"); +#endif /* sun4 */ + +#if defined(mips ) || defined(luna88k) || defined(i860) || defined(alpha) + gimmeabreak(); +#endif + +#ifdef i386 + asm("int3"); +#endif +} + +/* Be prepared to panic anytime, + even before panic_init() gets called from the "normal" place in kern/startup.c. + (panic_init() still needs to be called from there + to make sure we get initialized before starting multiple processors.) */ +boolean_t panic_lock_initialized = FALSE; +decl_simple_lock_data(, panic_lock) + +char *panicstr; +int paniccpu; + +void +panic_init() +{ + if (!panic_lock_initialized) + { + panic_lock_initialized = TRUE; + simple_lock_init(&panic_lock); + } +} + +/*VARARGS1*/ +void +panic(s, va_alist) + char * s; + va_dcl +{ + va_list listp; +#if NORMA_IPC + extern int _node_self; /* node_self() may not be callable yet */ +#endif /* NORMA_IPC */ + + panic_init(); + + simple_lock(&panic_lock); + if (panicstr) { + if (cpu_number() != paniccpu) { + simple_unlock(&panic_lock); + halt_cpu(); + /* NOTREACHED */ + } + } + else { + panicstr = s; + paniccpu = cpu_number(); + } + simple_unlock(&panic_lock); + printf("panic"); +#if NORMA_IPC + printf("(node %U)", _node_self); +#endif +#if NCPUS > 1 + printf("(cpu %U)", paniccpu); +#endif + printf(": "); + va_start(listp); + _doprnt(s, &listp, cnputc, 0); + va_end(listp); + printf("\n"); + + /* Give the user time to see the message */ + { + int i = 60; /* seconds */ + while (i--) + delay (1000000); /* microseconds */ + } + +#if MACH_KDB + Debugger("panic"); +#else + halt_all_cpus (1); +#endif +} + +/* + * We'd like to use BSD's log routines here... + */ +/*VARARGS2*/ +void +log(level, fmt, va_alist) + int level; + char * fmt; + va_dcl +{ + va_list listp; + +#ifdef lint + level++; +#endif + va_start(listp); + _doprnt(fmt, &listp, cnputc, 0); + va_end(listp); +} |