#include #include #include #include #include #include #include #include "threads/init.h" #include "threads/interrupt.h" #include "threads/thread.h" #include "threads/switch.h" #include "threads/vaddr.h" #include "devices/serial.h" #include "devices/shutdown.h" /* Halts the OS, printing the source file name, line number, and function name, plus a user-specific message. */ void debug_panic (const char *file, int line, const char *function, const char *message, ...) { static int level; va_list args; intr_disable (); console_panic (); level++; if (level == 1) { printf ("Kernel PANIC at %s:%d in %s(): ", file, line, function); va_start (args, message); vprintf (message, args); printf ("\n"); va_end (args); debug_backtrace (); } else if (level == 2) printf ("Kernel PANIC recursion at %s:%d in %s().\n", file, line, function); else { /* Don't print anything: that's probably why we recursed. */ } serial_flush (); shutdown (); for (;;); } /* Print call stack of a thread. The thread may be running, ready, or blocked. */ static void print_stacktrace(struct thread *t, void *aux UNUSED) { void *retaddr = NULL, **frame = NULL; const char *status = "UNKNOWN"; switch (t->status) { case THREAD_RUNNING: status = "RUNNING"; break; case THREAD_READY: status = "READY"; break; case THREAD_BLOCKED: status = "BLOCKED"; break; default: break; } printf ("Call stack of thread `%s' (status %s):", t->name, status); if (t == thread_current()) { frame = __builtin_frame_address (1); retaddr = __builtin_return_address (0); } else { /* Retrieve the values of the base and instruction pointers as they were saved when this thread called switch_threads. */ struct switch_threads_frame * saved_frame; saved_frame = (struct switch_threads_frame *)t->stack; /* Skip threads if they have been added to the all threads list, but have never been scheduled. We can identify because their `stack' member either points at the top of their kernel stack page, or the switch_threads_frame's 'eip' member points at switch_entry. See also threads.c. */ if (t->stack == (uint8_t *)t + PGSIZE || saved_frame->eip == switch_entry) { printf (" thread was never scheduled.\n"); return; } frame = (void **) saved_frame->ebp; retaddr = (void *) saved_frame->eip; } printf (" %p", retaddr); for (; (uintptr_t) frame >= 0x1000 && frame[0] != NULL; frame = frame[0]) printf (" %p", frame[1]); printf (".\n"); } /* Prints call stack of all threads. */ void debug_backtrace_all (void) { enum intr_level oldlevel = intr_disable (); thread_foreach (print_stacktrace, 0); intr_set_level (oldlevel); }