Annotation of prex-old/sys/kern/debug.c, Revision 1.1.1.1
1.1 nbrk 1: /*-
2: * Copyright (c) 2005-2007, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * debug.c - kernel debug services
32: */
33:
34: #include <kernel.h>
35: #include <task.h>
36: #include <ipc.h>
37: #include <thread.h>
38: #include <device.h>
39: #include <page.h>
40: #include <kmem.h>
41: #include <vm.h>
42: #include <irq.h>
43:
44: #ifdef DEBUG
45:
46: #ifdef printk
47: #undef printk
48: #endif
49: #ifdef panic
50: #undef panic
51: #endif
52:
53: #ifdef CONFIG_DMESG
54: #define LOG_SIZE 2048 /* size of ring buffer for log */
55: #define LOG_MASK (LOG_SIZE-1)
56:
57: static void log_save(char *buf);
58:
59: static char log_buf[LOG_SIZE]; /* buffer for message log */
60: static u_long log_start; /* start index of log_buf */
61: static u_long log_end; /* end index of log_buf */
62: static u_long log_len; /* length of logged char */
63: #endif
64:
65: static char msg_buf[MSGBUFSZ]; /* temporary buffer for message */
66: static void (*alt_print)(char *); /* alternate print handler */
67:
68: /*
69: * Print out the specified string with a variable argument.
70: *
71: * An actual output is displayed via the platform specific device by
72: * diag_print() routine in kernel. As an alternate option, the device
73: * driver can replace the print routine by using debug_attach().
74: * All printk() inside the kernel are defined as a macro.
75: * The printk() macro is compiled only when the debug option is
76: * enabled (NDEBUG=0).
77: */
78: void
79: printk(const char *fmt, ...)
80: {
81: va_list args;
82:
83: irq_lock();
84: va_start(args, fmt);
85: vsprintf(msg_buf, fmt, args);
86: #ifdef CONFIG_DMESG
87: log_save(msg_buf);
88: #endif
89: if (alt_print != NULL)
90: alt_print(msg_buf);
91: else
92: diag_print(msg_buf);
93: va_end(args);
94: irq_unlock();
95: }
96:
97: /*
98: * Kernel assertion.
99: *
100: * assert() is called only when the expression is false in ASSERT()
101: * macro. ASSERT() macro is compiled only when the debug option is
102: * enabled.
103: */
104: void
105: assert(const char *file, int line, const char *exp)
106: {
107: irq_lock();
108: printk("\nAssertion failed: %s line:%d '%s'\n", file, line, exp);
109: BREAKPOINT();
110: for (;;)
111: machine_idle();
112: /* NOTREACHED */
113: }
114:
115: /*
116: * Kernel panic.
117: *
118: * panic() is called for a fatal kernel error. It shows specified
119: * message, and stops CPU. If the kernel is not debug version,
120: * panic() macro will reset the system instead of calling this
121: * routine.
122: */
123: void
124: panic(const char *fmt, ...)
125: {
126: va_list args;
127:
128: irq_lock();
129: printk("\nKernel panic: ");
130: va_start(args, fmt);
131: vsprintf(msg_buf, fmt, args);
132: printk(msg_buf);
133: va_end(args);
134: printk("\n");
135: irq_unlock();
136: BREAKPOINT();
137: for (;;)
138: machine_idle();
139: /* NOTREACHED */
140: }
141:
142: #ifdef CONFIG_DMESG
143: /*
144: * Save diag message to ring buffer
145: */
146: static void
147: log_save(char *buf)
148: {
149: char *p;
150:
151: for (p = buf; *p != '\0'; p++) {
152: log_buf[log_end & LOG_MASK] = *p;
153: log_end++;
154: if (log_end - log_start > LOG_SIZE)
155: log_start = log_end - LOG_SIZE;
156: if (log_len < LOG_SIZE)
157: log_len++;
158: }
159: /* Store end tag */
160: log_buf[log_end & LOG_MASK] = -1;
161: }
162: #endif
163:
164: /*
165: * Return infomation about log
166: */
167: int
168: log_get(char **buf, size_t *size)
169: {
170:
171: #ifdef CONFIG_DMESG
172: *buf = log_buf;
173: *size = LOG_SIZE;
174: return 0;
175: #else
176: return -1;
177: #endif
178: }
179:
180: #if defined(CONFIG_DMESG) && defined (CONFIG_KDUMP)
181: static void
182: log_dump(void)
183: {
184: int i, len;
185: u_long index;
186: char c;
187:
188: index = log_start;
189: len = log_len;
190: if (log_len == LOG_SIZE) {
191: /* Skip first line */
192: while (log_buf[index & LOG_MASK] != '\n') {
193: index++;
194: len--;
195: }
196: }
197: for (i = 0; i < len; i++) {
198: c = log_buf[index & LOG_MASK];
199: printk("%c", c);
200: index++;
201: }
202: }
203: #endif
204:
205: /*
206: * Dump system information.
207: *
208: * A keyboard driver may call this routine if a user presses
209: * a predefined "dump" key.
210: * Since interrupt is locked in this routine, there is no need
211: * to lock the interrupt/scheduler in each dump function.
212: */
213: int
214: debug_dump(int item)
215: {
216: #ifdef CONFIG_KDUMP
217: int err = 0;
218:
219: printk("\n");
220: irq_lock();
221: switch (item) {
222: case DUMP_THREAD:
223: thread_dump();
224: break;
225: case DUMP_TASK:
226: task_dump();
227: break;
228: case DUMP_OBJECT:
229: object_dump();
230: break;
231: case DUMP_TIMER:
232: timer_dump();
233: break;
234: case DUMP_IRQ:
235: irq_dump();
236: break;
237: case DUMP_DEVICE:
238: device_dump();
239: break;
240: case DUMP_VM:
241: page_dump();
242: kmem_dump();
243: vm_dump();
244: break;
245: #ifdef CONFIG_DMESG
246: case DUMP_MSGLOG:
247: log_dump();
248: break;
249: #endif
250: default:
251: err = 1;
252: break;
253: }
254: irq_unlock();
255: return err;
256: #else
257: return ENOSYS;
258: #endif
259: }
260:
261: /*
262: * Attach an alternate print handler.
263: * A device driver can hook the function to display message.
264: */
265: void
266: debug_attach(void (*fn)(char *))
267: {
268: ASSERT(fn);
269: alt_print = fn;
270: }
271:
272: #else /* !DEBUG */
273:
274: /*
275: * Stubs for the release build.
276: */
277: int
278: debug_dump(int item)
279: {
280: return ENOSYS;
281: }
282:
283: void
284: debug_attach(void (*fn)(char *))
285: {
286: }
287: #endif /* !DEBUG */
CVSweb