00001 #include <debug.h>
00002 #include <console.h>
00003 #include <stdarg.h>
00004 #include <stdbool.h>
00005 #include <stddef.h>
00006 #include <stdio.h>
00007 #include <string.h>
00008 #include "threads/init.h"
00009 #include "threads/interrupt.h"
00010 #include "threads/thread.h"
00011 #include "threads/switch.h"
00012 #include "threads/vaddr.h"
00013 #include "devices/serial.h"
00014
00015
00016
00017 void
00018 debug_panic (const char *file, int line, const char *function,
00019 const char *message, ...)
00020 {
00021 static int level;
00022 va_list args;
00023
00024 intr_disable ();
00025 console_panic ();
00026
00027 level++;
00028 if (level == 1)
00029 {
00030 printf ("Kernel PANIC at %s:%d in %s(): ", file, line, function);
00031
00032 va_start (args, message);
00033 vprintf (message, args);
00034 printf ("\n");
00035 va_end (args);
00036
00037 debug_backtrace ();
00038 }
00039 else if (level == 2)
00040 printf ("Kernel PANIC recursion at %s:%d in %s().\n",
00041 file, line, function);
00042 else
00043 {
00044
00045 }
00046
00047 serial_flush ();
00048 if (power_off_when_done)
00049 power_off ();
00050 for (;;);
00051 }
00052
00053
00054
00055 static void
00056 print_stacktrace(struct thread *t, void *aux UNUSED)
00057 {
00058 void *retaddr = NULL, **frame = NULL;
00059 const char *status = "UNKNOWN";
00060
00061 switch (t->status) {
00062 case THREAD_RUNNING:
00063 status = "RUNNING";
00064 break;
00065
00066 case THREAD_READY:
00067 status = "READY";
00068 break;
00069
00070 case THREAD_BLOCKED:
00071 status = "BLOCKED";
00072 break;
00073
00074 default:
00075 break;
00076 }
00077
00078 printf ("Call stack of thread `%s' (status %s):", t->name, status);
00079
00080 if (t == thread_current())
00081 {
00082 frame = __builtin_frame_address (1);
00083 retaddr = __builtin_return_address (0);
00084 }
00085 else
00086 {
00087
00088
00089 struct switch_threads_frame * saved_frame;
00090
00091 saved_frame = (struct switch_threads_frame *)t->stack;
00092
00093
00094
00095
00096
00097
00098
00099 if (t->stack == (uint8_t *)t + PGSIZE || saved_frame->eip == switch_entry)
00100 {
00101 printf (" thread was never scheduled.\n");
00102 return;
00103 }
00104
00105 frame = (void **) saved_frame->ebp;
00106 retaddr = (void *) saved_frame->eip;
00107 }
00108
00109 printf (" %p", retaddr);
00110 for (; (uintptr_t) frame >= 0x1000 && frame[0] != NULL; frame = frame[0])
00111 printf (" %p", frame[1]);
00112 printf (".\n");
00113 }
00114
00115
00116 void
00117 debug_backtrace_all (void)
00118 {
00119 enum intr_level oldlevel = intr_disable ();
00120
00121 thread_foreach (print_stacktrace, 0);
00122 intr_set_level (oldlevel);
00123 }