From: Ben Pfaff Date: Tue, 31 Aug 2004 22:00:54 +0000 (+0000) Subject: Add DEBUG() macro for debugging that can be turned on and off with a X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pintos-anon;a=commitdiff_plain;h=ff144294a54d14af3c9324e6a336a3102094dea4 Add DEBUG() macro for debugging that can be turned on and off with a command line option, and associated support. Rename panic() to PANIC(). Update references. Rename backtrace() to debug_backtrace(). --- diff --git a/src/devices/16550a.h b/src/devices/16550a.h index bce26f3..bfe9484 100644 --- a/src/devices/16550a.h +++ b/src/devices/16550a.h @@ -78,7 +78,7 @@ make_lcr (int bits, enum parity_type parity, int stop, bool send_break, case EVEN: lcr |= 0x18; break; case MARK: lcr |= 0x28; break; case SPACE: lcr |= 0x38; break; - default: panic ("bad parity %d", (int) parity); + default: PANIC ("bad parity %d", (int) parity); } ASSERT (stop == 1 || stop == 2); diff --git a/src/devices/disk.c b/src/devices/disk.c index 6206e78..f63669d 100644 --- a/src/devices/disk.c +++ b/src/devices/disk.c @@ -458,7 +458,7 @@ disk_read (struct disk *d, disk_sector_no sec_no, void *buffer) sema_down (&d->channel->completion_wait); wait_while_busy (d); if (!input_sector (d->channel, buffer)) - panic ("%s: disk read failed, sector=%"PRDSNu, d->name, sec_no); + PANIC ("%s: disk read failed, sector=%"PRDSNu, d->name, sec_no); lock_release (&d->channel->lock); } @@ -473,7 +473,7 @@ disk_write (struct disk *d, disk_sector_no sec_no, const void *buffer) issue_command (d, CMD_WRITE_SECTOR_RETRY); wait_while_busy (d); if (!output_sector (d->channel, buffer)) - panic ("%s: disk write failed, sector=%"PRDSNu, d->name, sec_no); + PANIC ("%s: disk write failed, sector=%"PRDSNu, d->name, sec_no); sema_down (&d->channel->completion_wait); lock_release (&d->channel->lock); } diff --git a/src/lib/debug.c b/src/lib/debug.c index fafbc8c..3d9a9b1 100644 --- a/src/lib/debug.c +++ b/src/lib/debug.c @@ -3,25 +3,93 @@ #include "interrupt.h" #include "lib.h" +#define MAX_CLASSES 16 +static bool all_enabled; +static const char *enabled_classes[MAX_CLASSES]; +static size_t enabled_cnt; + +/* Enables the debug message classes specified in CLASSES. The + string CLASSES is modified by and becomes owned by this + function. */ +void +debug_enable (char *classes) +{ + char *class, *save; + + for (class = strtok_r (classes, ",", &save); class != NULL; + class = strtok_r (NULL, ",", &save)) + { + if (strcmp (class, "all") && enabled_cnt < MAX_CLASSES) + enabled_classes[enabled_cnt++] = class; + else + all_enabled = true; + } +} + +/* Checks whether CLASS is enabled. */ +static bool +class_is_enabled (const char *class) +{ + size_t i; + + if (all_enabled) + return true; + + for (i = 0; i < enabled_cnt; i++) + if (!strcmp (enabled_classes[i], class)) + return true; + + return false; +} + +/* Prints a debug message along with the source file name, line + number, and function name of where it was emitted. CLASS is + used to filter out unwanted messages. */ +void +debug_message (const char *file, int line, const char *function, + const char *class, const char *message, ...) +{ + if (class_is_enabled (class)) + { + va_list args; + + enum if_level old_level = intr_disable (); + printk ("%s:%d: %s(): ", file, line, function); + va_start (args, message); + vprintk (message, args); + printk ("\n"); + va_end (args); + intr_set_level (old_level); + } +} + +/* Halts the OS, printing the source file name, line number, and + function name, plus a user-specific message. */ void -panic (const char *format, ...) +debug_panic (const char *file, int line, const char *function, + const char *message, ...) { va_list args; intr_disable (); - va_start (args, format); - vprintk (format, args); + printk ("PANIC at %s:%d in %s(): ", file, line, function); + va_start (args, message); + vprintk (message, args); printk ("\n"); va_end (args); - backtrace (); + debug_backtrace (); for (;;); } +/* Prints the call stack, that is, a list of addresses in each of + the functions we are nested within. gdb or addr2line may be + applied to kernel.o to translate these into file names, line + numbers, and function names. */ void -backtrace (void) +debug_backtrace (void) { void **frame; diff --git a/src/lib/debug.h b/src/lib/debug.h index 4f3cb5b..2af8ba4 100644 --- a/src/lib/debug.h +++ b/src/lib/debug.h @@ -1,22 +1,35 @@ #ifndef HEADER_DEBUG_H #define HEADER_DEBUG_H 1 -#if __GNUC__ > 1 -#define ATTRIBUTE(X) __attribute__ (X) -#else -#define ATTRIBUTE(X) -#endif +/* GCC lets us add "attributes" to functions, function + parameters, etc. to indicate their properties. + See the GCC manual for details. */ +#define UNUSED __attribute__ ((unused)) +#define NO_RETURN __attribute__ ((noreturn)) +#define NO_INLINE __attribute__ ((noinline)) +#define PRINTF_FORMAT(FMT, FIRST) __attribute__ ((format (printf, FMT, FIRST))) + +/* Prints a debug message along with the source file name, line + number, and function name of where it was emitted. CLASS is + used to filter out unwanted messages. */ +#define DEBUG(CLASS, ...) \ + debug_message (__FILE__, __LINE__, __func__, #CLASS, __VA_ARGS__) -#define UNUSED ATTRIBUTE ((unused)) -#define NO_RETURN ATTRIBUTE ((noreturn)) -#define PRINTF_FORMAT(FMT, FIRST) ATTRIBUTE ((format (printf, FMT, FIRST))) -#define SCANF_FORMAT(FMT, FIRST) ATTRIBUTE ((format (scanf, FMT, FIRST))) +/* Halts the OS, printing the source file name, line number, and + function name, plus a user-specific message. */ +#define PANIC(...) debug_panic (__FILE__, __LINE__, __func__, __VA_ARGS__) + +void debug_enable (char *classes); +void debug_message (const char *file, int line, const char *function, + const char *class, const char *message, ...) + PRINTF_FORMAT (5, 6); +void debug_panic (const char *file, int line, const char *function, + const char *message, ...) PRINTF_FORMAT (4, 5) NO_RETURN; +void debug_backtrace (void); + +#endif -void panic (const char *, ...) - __attribute__ ((format (printf, 1, 2), noreturn)); -void backtrace (void); -#endif /* debug.h */ /* This is outside the header guard so that debug.h may be included multiple times with different settings of NDEBUG. */ @@ -24,14 +37,11 @@ void backtrace (void); #undef NOT_REACHED #ifndef NDEBUG -#define ASSERT(CONDITION) \ - if (CONDITION) { \ - /* Nothing. */ \ - } else { \ - panic ("%s:%d: %s(): assertion `%s' failed.", \ - __FILE__, __LINE__, __func__, #CONDITION); \ +#define ASSERT(CONDITION) \ + if (CONDITION) { } else { \ + PANIC ("assertion `%s' failed.", #CONDITION); \ } -#define NOT_REACHED() ASSERT (0) +#define NOT_REACHED() PANIC ("executed an unreachable statement"); #else #define ASSERT(CONDITION) ((void) 0) #define NOT_REACHED() for (;;) diff --git a/src/threads/interrupt.c b/src/threads/interrupt.c index 6945e0a..5227486 100644 --- a/src/threads/interrupt.c +++ b/src/threads/interrupt.c @@ -269,7 +269,7 @@ void intr_panic (struct intr_frame *regs) { dump_intr_frame (regs); - panic ("Panic!"); + PANIC ("Panic!"); } void diff --git a/src/threads/palloc.c b/src/threads/palloc.c index a0196ac..62e24ca 100644 --- a/src/threads/palloc.c +++ b/src/threads/palloc.c @@ -54,7 +54,7 @@ palloc_get (enum palloc_flags flags) else { if (flags & PAL_ASSERT) - panic ("palloc_get: out of pages"); + PANIC ("palloc_get: out of pages"); } return page;