source: branches/minix3-book/kernel/utility.c@ 4

Last change on this file since 4 was 4, checked in by Mattia Monga, 13 years ago

Importazione sorgenti libro

File size: 4.8 KB
Line 
1/* This file contains a collection of miscellaneous procedures:
2 * panic: abort MINIX due to a fatal error
3 * kprintf: diagnostic output for the kernel
4 *
5 * Changes:
6 * Dec 10, 2004 kernel printing to circular buffer (Jorrit N. Herder)
7 *
8 * This file contains the routines that take care of kernel messages, i.e.,
9 * diagnostic output within the kernel. Kernel messages are not directly
10 * displayed on the console, because this must be done by the output driver.
11 * Instead, the kernel accumulates characters in a buffer and notifies the
12 * output driver when a new message is ready.
13 */
14
15#include <minix/com.h>
16#include "kernel.h"
17#include <stdarg.h>
18#include <unistd.h>
19#include <stddef.h>
20#include <stdlib.h>
21#include <signal.h>
22#include "proc.h"
23
24#define END_OF_KMESS -1
25FORWARD _PROTOTYPE(void kputc, (int c));
26
27/*===========================================================================*
28 * panic *
29 *===========================================================================*/
30PUBLIC void panic(mess,nr)
31_CONST char *mess;
32int nr;
33{
34/* The system has run aground of a fatal kernel error. Terminate execution. */
35 static int panicking = 0;
36 if (panicking ++) return; /* prevent recursive panics */
37
38 if (mess != NULL) {
39 kprintf("\nKernel panic: %s", mess);
40 if (nr != NO_NUM) kprintf(" %d", nr);
41 kprintf("\n",NO_NUM);
42 }
43
44 /* Abort MINIX. */
45 prepare_shutdown(RBT_PANIC);
46}
47
48/*===========================================================================*
49 * kprintf *
50 *===========================================================================*/
51PUBLIC void kprintf(const char *fmt, ...) /* format to be printed */
52{
53 int c; /* next character in fmt */
54 int d;
55 unsigned long u; /* hold number argument */
56 int base; /* base of number arg */
57 int negative = 0; /* print minus sign */
58 static char x2c[] = "0123456789ABCDEF"; /* nr conversion table */
59 char ascii[8 * sizeof(long) / 3 + 2]; /* string for ascii number */
60 char *s = NULL; /* string to be printed */
61 va_list argp; /* optional arguments */
62
63 va_start(argp, fmt); /* init variable arguments */
64
65 while((c=*fmt++) != 0) {
66
67 if (c == '%') { /* expect format '%key' */
68 switch(c = *fmt++) { /* determine what to do */
69
70 /* Known keys are %d, %u, %x, %s, and %%. This is easily extended
71 * with number types like %b and %o by providing a different base.
72 * Number type keys don't set a string to 's', but use the general
73 * conversion after the switch statement.
74 */
75 case 'd': /* output decimal */
76 d = va_arg(argp, signed int);
77 if (d < 0) { negative = 1; u = -d; } else { u = d; }
78 base = 10;
79 break;
80 case 'u': /* output unsigned long */
81 u = va_arg(argp, unsigned long);
82 base = 10;
83 break;
84 case 'x': /* output hexadecimal */
85 u = va_arg(argp, unsigned long);
86 base = 0x10;
87 break;
88 case 's': /* output string */
89 s = va_arg(argp, char *);
90 if (s == NULL) s = "(null)";
91 break;
92 case '%': /* output percent */
93 s = "%";
94 break;
95
96 /* Unrecognized key. */
97 default: /* echo back %key */
98 s = "%?";
99 s[1] = c; /* set unknown key */
100 }
101
102 /* Assume a number if no string is set. Convert to ascii. */
103 if (s == NULL) {
104 s = ascii + sizeof(ascii)-1;
105 *s = 0;
106 do { *--s = x2c[(u % base)]; } /* work backwards */
107 while ((u /= base) > 0);
108 }
109
110 /* This is where the actual output for format "%key" is done. */
111 if (negative) kputc('-'); /* print sign if negative */
112 while(*s != 0) { kputc(*s++); } /* print string/ number */
113 s = NULL; /* reset for next round */
114 }
115 else {
116 kputc(c); /* print and continue */
117 }
118 }
119 kputc(END_OF_KMESS); /* terminate output */
120 va_end(argp); /* end variable arguments */
121}
122
123/*===========================================================================*
124 * kputc *
125 *===========================================================================*/
126PRIVATE void kputc(c)
127int c; /* character to append */
128{
129/* Accumulate a single character for a kernel message. Send a notification
130 * to the output driver if an END_OF_KMESS is encountered.
131 */
132 if (c != END_OF_KMESS) {
133 kmess.km_buf[kmess.km_next] = c; /* put normal char in buffer */
134 if (kmess.km_size < KMESS_BUF_SIZE)
135 kmess.km_size += 1;
136 kmess.km_next = (kmess.km_next + 1) % KMESS_BUF_SIZE;
137 } else {
138 send_sig(OUTPUT_PROC_NR, SIGKMESS);
139 }
140}
141
Note: See TracBrowser for help on using the repository browser.