Add DEBUG() macro for debugging that can be turned on and off with a
authorBen Pfaff <blp@cs.stanford.edu>
Tue, 31 Aug 2004 22:00:54 +0000 (22:00 +0000)
committerBen Pfaff <blp@cs.stanford.edu>
Tue, 31 Aug 2004 22:00:54 +0000 (22:00 +0000)
command line option, and associated support.
Rename panic() to PANIC().  Update references.
Rename backtrace() to debug_backtrace().

src/devices/16550a.h
src/devices/disk.c
src/lib/debug.c
src/lib/debug.h
src/threads/interrupt.c
src/threads/palloc.c

index bce26f33c5e66d54461e86d9d386953d021bffc3..bfe948489dbcb0a052765794cb052f94842b5a60 100644 (file)
@@ -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);
index 6206e78cedb9aec9df14146cae25704ee7f5e2d3..f63669d9afe5a62a2380b4fc287cf705e2f3e026 100644 (file)
@@ -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);
 }
index fafbc8c1acc69de41a5dfb4104f910c2365f4c84..3d9a9b1e28f159f1d1dc0a82d7e117c6a6f02bac 100644 (file)
@@ -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;
   
index 4f3cb5b662dd07d54adcba4debccc7017e70e897..2af8ba421ebe248b07c3a03d5e80fe09dbba3acc 100644 (file)
@@ -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 (;;)
index 6945e0a2d6843089c9e8421bc1e987d5038dcc94..5227486f4212c3d6ccab71f1e998c39fbef9ec8c 100644 (file)
@@ -269,7 +269,7 @@ void
 intr_panic (struct intr_frame *regs) 
 {
   dump_intr_frame (regs);
-  panic ("Panic!");
+  PANIC ("Panic!");
 }
 
 void
index a0196ace19665fe13c4c369283e6928c9801d26f..62e24cada4756dfa5917f74fac03512ce7626ad4 100644 (file)
@@ -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;