Move reboot() and power_off() to new file, and rename to fit convention.
[pintos-anon] / src / lib / kernel / debug.c
1 #include <debug.h>
2 #include <console.h>
3 #include <stdarg.h>
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include "threads/init.h"
9 #include "threads/interrupt.h"
10 #include "threads/thread.h"
11 #include "threads/switch.h"
12 #include "threads/vaddr.h"
13 #include "devices/serial.h"
14 #include "devices/shutdown.h"
15
16 /* Halts the OS, printing the source file name, line number, and
17    function name, plus a user-specific message. */
18 void
19 debug_panic (const char *file, int line, const char *function,
20              const char *message, ...)
21 {
22   static int level;
23   va_list args;
24
25   intr_disable ();
26   console_panic ();
27
28   level++;
29   if (level == 1) 
30     {
31       printf ("Kernel PANIC at %s:%d in %s(): ", file, line, function);
32
33       va_start (args, message);
34       vprintf (message, args);
35       printf ("\n");
36       va_end (args);
37
38       debug_backtrace ();
39     }
40   else if (level == 2)
41     printf ("Kernel PANIC recursion at %s:%d in %s().\n",
42             file, line, function);
43   else 
44     {
45       /* Don't print anything: that's probably why we recursed. */
46     }
47
48   serial_flush ();
49   if (power_off_when_done)
50     shutdown_power_off ();
51   for (;;);
52 }
53
54 /* Print call stack of a thread.
55    The thread may be running, ready, or blocked. */
56 static void
57 print_stacktrace(struct thread *t, void *aux UNUSED)
58 {
59   void *retaddr = NULL, **frame = NULL;
60   const char *status = "UNKNOWN";
61
62   switch (t->status) {
63     case THREAD_RUNNING:  
64       status = "RUNNING";
65       break;
66
67     case THREAD_READY:  
68       status = "READY";
69       break;
70
71     case THREAD_BLOCKED:  
72       status = "BLOCKED";
73       break;
74
75     default:
76       break;
77   }
78
79   printf ("Call stack of thread `%s' (status %s):", t->name, status);
80
81   if (t == thread_current()) 
82     {
83       frame = __builtin_frame_address (1);
84       retaddr = __builtin_return_address (0);
85     }
86   else
87     {
88       /* Retrieve the values of the base and instruction pointers
89          as they were saved when this thread called switch_threads. */
90       struct switch_threads_frame * saved_frame;
91
92       saved_frame = (struct switch_threads_frame *)t->stack;
93
94       /* Skip threads if they have been added to the all threads
95          list, but have never been scheduled.
96          We can identify because their `stack' member either points 
97          at the top of their kernel stack page, or the 
98          switch_threads_frame's 'eip' member points at switch_entry.
99          See also threads.c. */
100       if (t->stack == (uint8_t *)t + PGSIZE || saved_frame->eip == switch_entry)
101         {
102           printf (" thread was never scheduled.\n");
103           return;
104         }
105
106       frame = (void **) saved_frame->ebp;
107       retaddr = (void *) saved_frame->eip;
108     }
109
110   printf (" %p", retaddr);
111   for (; (uintptr_t) frame >= 0x1000 && frame[0] != NULL; frame = frame[0])
112     printf (" %p", frame[1]);
113   printf (".\n");
114 }
115
116 /* Prints call stack of all threads. */
117 void
118 debug_backtrace_all (void)
119 {
120   enum intr_level oldlevel = intr_disable ();
121
122   thread_foreach (print_stacktrace, 0);
123   intr_set_level (oldlevel);
124 }