Kernel - Unlocked debug lock when entering kernel panic
[tpg/acess2.git] / Kernel / debug.c
1 /*
2  * AcessOS Microkernel Version
3  * debug.c
4  * 
5  * TODO: Move the Debug_putchar methods out to the arch/ tree
6  */
7 #include <acess.h>
8 #include <stdarg.h>
9
10 #define DEBUG_MAX_LINE_LEN      256
11
12 #define LOCK_DEBUG_OUTPUT       1
13
14 #define TRACE_TO_KTERM  0
15
16 // === IMPORTS ===
17 extern void     Threads_Dump(void);
18 extern void     KernelPanic_SetMode(void);
19 extern void     KernelPanic_PutChar(char Ch);
20
21 // === PROTOTYPES ===
22 static void     Debug_Putchar(char ch);
23 static void     Debug_Puts(int bUseKTerm, const char *Str);
24 void    Debug_DbgOnlyFmt(const char *format, va_list args);
25 void    Debug_FmtS(int bUseKTerm, const char *format, ...);
26 void    Debug_Fmt(int bUseKTerm, const char *format, va_list args);
27 void    Debug_SetKTerminal(const char *File);
28
29 // === GLOBALS ===
30  int    gDebug_Level = 0;
31  int    giDebug_KTerm = -1;
32  int    gbDebug_IsKPanic = 0;
33 volatile int    gbInPutChar = 0;
34 #if LOCK_DEBUG_OUTPUT
35 tShortSpinlock  glDebug_Lock;
36 #endif
37
38 // === CODE ===
39 static void Debug_Putchar(char ch)
40 {       
41         Debug_PutCharDebug(ch);
42         if( !gbDebug_IsKPanic )
43         {
44                 if(gbInPutChar) return ;
45                 gbInPutChar = 1;
46                 if(giDebug_KTerm != -1)
47                         VFS_Write(giDebug_KTerm, 1, &ch);
48                 gbInPutChar = 0;
49         }
50         else
51                 KernelPanic_PutChar(ch);
52 }
53
54 static void Debug_Puts(int UseKTerm, const char *Str)
55 {
56          int    len = 0;
57         
58         Debug_PutStringDebug(Str);
59         
60         if( gbDebug_IsKPanic )
61         {               
62                 for( len = 0; Str[len]; len ++ )
63                         KernelPanic_PutChar( Str[len] );
64         }
65         else
66                 for( len = 0; Str[len]; len ++ );
67         
68         // Output to the kernel terminal
69         if( UseKTerm && !gbDebug_IsKPanic && giDebug_KTerm != -1)
70         {
71                 if(gbInPutChar) return ;
72                 gbInPutChar = 1;
73                 VFS_Write(giDebug_KTerm, len, Str);
74                 gbInPutChar = 0;
75         }
76 }
77
78 void Debug_DbgOnlyFmt(const char *format, va_list args)
79 {
80         Debug_Fmt(0, format, args);
81 }
82
83 void Debug_Fmt(int bUseKTerm, const char *format, va_list args)
84 {
85         char    buf[DEBUG_MAX_LINE_LEN];
86          int    len;
87         buf[DEBUG_MAX_LINE_LEN-1] = 0;
88         len = vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
89         //if( len < DEBUG_MAX_LINE )
90                 // do something
91         Debug_Puts(bUseKTerm, buf);
92         return ;
93 }
94
95 void Debug_FmtS(int bUseKTerm, const char *format, ...)
96 {
97         va_list args;   
98         va_start(args, format);
99         Debug_Fmt(bUseKTerm, format, args);
100         va_end(args);
101 }
102
103 void Debug_KernelPanic(void)
104 {
105         #if LOCK_DEBUG_OUTPUT
106         SHORTREL(&glDebug_Lock);
107         #endif
108         gbDebug_IsKPanic = 1;
109         KernelPanic_SetMode();
110 }
111
112 /**
113  * \fn void LogF(const char *Msg, ...)
114  * \brief Raw debug log (no new line, no prefix)
115  */
116 void LogF(const char *Fmt, ...)
117 {
118         va_list args;
119
120         #if LOCK_DEBUG_OUTPUT
121         SHORTLOCK(&glDebug_Lock);
122         #endif
123         
124         va_start(args, Fmt);
125
126         Debug_Fmt(1, Fmt, args);
127
128         va_end(args);
129         
130         #if LOCK_DEBUG_OUTPUT
131         SHORTREL(&glDebug_Lock);
132         #endif
133 }
134 /**
135  * \fn void Debug(const char *Msg, ...)
136  * \brief Print only to the debug channel (not KTerm)
137  */
138 void Debug(const char *Fmt, ...)
139 {
140         va_list args;
141         
142         #if LOCK_DEBUG_OUTPUT
143         SHORTLOCK(&glDebug_Lock);
144         #endif
145
146         Debug_Puts(0, "Debug: ");
147         va_start(args, Fmt);
148         Debug_DbgOnlyFmt(Fmt, args);
149         va_end(args);
150         Debug_PutCharDebug('\r');
151         Debug_PutCharDebug('\n');
152         #if LOCK_DEBUG_OUTPUT
153         SHORTREL(&glDebug_Lock);
154         #endif
155 }
156 /**
157  * \fn void Log(const char *Msg, ...)
158  */
159 void Log(const char *Fmt, ...)
160 {
161         va_list args;
162         
163         #if LOCK_DEBUG_OUTPUT
164         SHORTLOCK(&glDebug_Lock);
165         #endif
166
167         Debug_Puts(1, "Log: ");
168         va_start(args, Fmt);
169         Debug_Fmt(1, Fmt, args);
170         va_end(args);
171         Debug_Puts(1, "\r\n");
172         
173         #if LOCK_DEBUG_OUTPUT
174         SHORTREL(&glDebug_Lock);
175         #endif
176 }
177 void Warning(const char *Fmt, ...)
178 {
179         va_list args;
180         
181         #if LOCK_DEBUG_OUTPUT
182         SHORTLOCK(&glDebug_Lock);
183         #endif
184         
185         Debug_Puts(1, "Warning: ");
186         va_start(args, Fmt);
187         Debug_Fmt(1, Fmt, args);
188         va_end(args);
189         Debug_Putchar('\r');
190         Debug_Putchar('\n');
191         
192         #if LOCK_DEBUG_OUTPUT
193         SHORTREL(&glDebug_Lock);
194         #endif
195 }
196 void Panic(const char *Fmt, ...)
197 {
198         va_list args;
199         
200         #if LOCK_DEBUG_OUTPUT
201         SHORTLOCK(&glDebug_Lock);
202         #endif
203         // And never SHORTREL
204         
205         Debug_KernelPanic();
206         
207         Debug_Puts(1, "Panic: ");
208         va_start(args, Fmt);
209         Debug_Fmt(1, Fmt, args);
210         va_end(args);
211         Debug_Putchar('\r');
212         Debug_Putchar('\n');
213
214         Threads_Dump();
215
216 //      __asm__ __volatile__ ("xchg %bx, %bx");
217 //      __asm__ __volatile__ ("cli;\n\thlt");
218 //      for(;;) __asm__ __volatile__ ("hlt");
219         for(;;) ;
220 }
221
222 void Debug_SetKTerminal(const char *File)
223 {
224          int    tmp;
225         if(giDebug_KTerm != -1) {
226                 tmp = giDebug_KTerm;
227                 giDebug_KTerm = -1;
228                 VFS_Close(tmp);
229         }
230         tmp = VFS_Open(File, VFS_OPENFLAG_WRITE);
231         Log_Log("Debug", "Opened '%s' as 0x%x", File, tmp);
232         giDebug_KTerm = tmp;
233         Log_Log("Debug", "Returning to %p", __builtin_return_address(0));
234 }
235
236 void Debug_Enter(const char *FuncName, const char *ArgTypes, ...)
237 {
238         va_list args;
239          int    i;
240          int    pos;
241         tTID    tid = Threads_GetTID();
242          
243         #if LOCK_DEBUG_OUTPUT
244         SHORTLOCK(&glDebug_Lock);
245         #endif
246
247         i = gDebug_Level ++;
248
249         va_start(args, ArgTypes);
250
251         Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
252         while(i--)      Debug_Puts(TRACE_TO_KTERM, " ");
253
254         Debug_Puts(TRACE_TO_KTERM, FuncName);
255         Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
256         Debug_Puts(TRACE_TO_KTERM, ": (");
257
258         while(*ArgTypes)
259         {
260                 pos = strpos(ArgTypes, ' ');
261                 if(pos == -1 || pos > 1) {
262                         if(pos == -1)
263                                 Debug_Puts(TRACE_TO_KTERM, ArgTypes+1);
264                         else {
265                                 Debug_FmtS(TRACE_TO_KTERM, "%.*s", pos-1, ArgTypes+1);
266                         }
267                         Debug_Puts(TRACE_TO_KTERM, "=");
268                 }
269                 switch(*ArgTypes)
270                 {
271                 case 'p':       Debug_FmtS(TRACE_TO_KTERM, "%p", va_arg(args, void*));  break;
272                 case 'P':       Debug_FmtS(TRACE_TO_KTERM, "%P", va_arg(args, tPAddr)); break;
273                 case 's':       Debug_FmtS(TRACE_TO_KTERM, "'%s'", va_arg(args, char*));        break;
274                 case 'i':       Debug_FmtS(TRACE_TO_KTERM, "%i", va_arg(args, int));    break;
275                 case 'u':       Debug_FmtS(TRACE_TO_KTERM, "%u", va_arg(args, Uint));   break;
276                 case 'x':       Debug_FmtS(TRACE_TO_KTERM, "0x%x", va_arg(args, Uint)); break;
277                 case 'b':       Debug_FmtS(TRACE_TO_KTERM, "0b%b", va_arg(args, Uint)); break;
278                 case 'X':       Debug_FmtS(TRACE_TO_KTERM, "0x%llx", va_arg(args, Uint64));     break;  // Extended (64-Bit)
279                 case 'B':       Debug_FmtS(TRACE_TO_KTERM, "0b%llb", va_arg(args, Uint64));     break;  // Extended (64-Bit)
280                 }
281                 if(pos != -1) {
282                         Debug_Puts(TRACE_TO_KTERM, ", ");
283                 }
284
285                 if(pos == -1)   break;
286                 ArgTypes = &ArgTypes[pos+1];
287         }
288
289         va_end(args);
290         Debug_Puts(TRACE_TO_KTERM, ")\r\n");
291         
292         #if LOCK_DEBUG_OUTPUT
293         SHORTREL(&glDebug_Lock);
294         #endif
295 }
296
297 void Debug_Log(const char *FuncName, const char *Fmt, ...)
298 {
299         va_list args;
300          int    i = gDebug_Level;
301         tTID    tid = Threads_GetTID();
302
303         #if LOCK_DEBUG_OUTPUT
304         SHORTLOCK(&glDebug_Lock);
305         #endif
306
307         Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
308         while(i--)      Debug_Puts(TRACE_TO_KTERM, " ");
309
310         Debug_Puts(TRACE_TO_KTERM, FuncName);
311         Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
312         Debug_Puts(TRACE_TO_KTERM, ": ");
313
314         va_start(args, Fmt);
315         Debug_Fmt(TRACE_TO_KTERM, Fmt, args);
316         va_end(args);
317
318         Debug_Puts(TRACE_TO_KTERM, "\r\n");
319         
320         #if LOCK_DEBUG_OUTPUT
321         SHORTREL(&glDebug_Lock);
322         #endif
323 }
324
325 void Debug_Leave(const char *FuncName, char RetType, ...)
326 {
327         va_list args;
328          int    i;
329         tTID    tid = Threads_GetTID();
330
331         #if LOCK_DEBUG_OUTPUT
332         SHORTLOCK(&glDebug_Lock);
333         #endif
334         
335         i = --gDebug_Level;
336
337         va_start(args, RetType);
338
339         if( i == -1 ) {
340                 gDebug_Level = 0;
341                 i = 0;
342         }
343         Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
344         // Indenting
345         while(i--)      Debug_Puts(TRACE_TO_KTERM, " ");
346
347         Debug_Puts(TRACE_TO_KTERM, FuncName);
348         Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
349         Debug_Puts(TRACE_TO_KTERM, ": RETURN");
350
351         // No Return
352         if(RetType == '-') {
353                 Debug_Puts(TRACE_TO_KTERM, "\r\n");
354                 #if LOCK_DEBUG_OUTPUT
355                 SHORTREL(&glDebug_Lock);
356                 #endif
357                 return;
358         }
359
360         switch(RetType)
361         {
362         case 'n':       Debug_Puts(TRACE_TO_KTERM, " NULL");    break;
363         case 'p':       Debug_Fmt(TRACE_TO_KTERM, " %p", args); break;
364         case 'P':       Debug_Fmt(TRACE_TO_KTERM, " %P", args); break;  // PAddr
365         case 's':       Debug_Fmt(TRACE_TO_KTERM, " '%s'", args);       break;
366         case 'i':       Debug_Fmt(TRACE_TO_KTERM, " %i", args); break;
367         case 'u':       Debug_Fmt(TRACE_TO_KTERM, " %u", args); break;
368         case 'x':       Debug_Fmt(TRACE_TO_KTERM, " 0x%x", args);       break;
369         // Extended (64-Bit)
370         case 'X':       Debug_Fmt(TRACE_TO_KTERM, " 0x%llx", args);     break;
371         }
372         Debug_Puts(TRACE_TO_KTERM, "\r\n");
373
374         va_end(args);
375         
376         #if LOCK_DEBUG_OUTPUT
377         SHORTREL(&glDebug_Lock);
378         #endif
379 }
380
381 void Debug_HexDump(const char *Header, const void *Data, Uint Length)
382 {
383         const Uint8     *cdat = Data;
384         Uint    pos = 0;
385         LogF("%014lli ", now());
386         Debug_Puts(1, Header);
387         LogF(" (Hexdump of %p)\r\n", Data);
388
389         #define CH(n)   ((' '<=cdat[(n)]&&cdat[(n)]<0x7F) ? cdat[(n)] : '.')
390
391         while(Length >= 16)
392         {
393                 LogF("%014lli Log: %04x:"
394                         " %02x %02x %02x %02x %02x %02x %02x %02x"
395                         " %02x %02x %02x %02x %02x %02x %02x %02x"
396                         "  %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\r\n",
397                         now(),
398                         pos,
399                         cdat[ 0], cdat[ 1], cdat[ 2], cdat[ 3], cdat[ 4], cdat[ 5], cdat[ 6], cdat[ 7],
400                         cdat[ 8], cdat[ 9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
401                         CH(0),  CH(1),  CH(2),  CH(3),  CH(4),  CH(5),  CH(6),  CH(7),
402                         CH(8),  CH(9),  CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
403                         );
404                 Length -= 16;
405                 cdat += 16;
406                 pos += 16;
407         }
408
409         {
410                  int    i ;
411                 LogF("%014lli Log: %04x: ", now(), pos);
412                 for(i = 0; i < Length; i ++)
413                 {
414                         LogF("%02x ", cdat[i]);
415                 }
416                 for( ; i < 16; i ++)    LogF("   ");
417                 LogF(" ");
418                 for(i = 0; i < Length; i ++)
419                 {
420                         if( i == 8 )    LogF(" ");
421                         LogF("%c", CH(i));
422                 }
423         
424                 Debug_Putchar('\r');
425                 Debug_Putchar('\n');
426         }
427 }
428
429 // --- EXPORTS ---
430 EXPORT(Debug);
431 EXPORT(Log);
432 EXPORT(Warning);
433 EXPORT(Debug_Enter);
434 EXPORT(Debug_Log);
435 EXPORT(Debug_Leave);

UCC git Repository :: git.ucc.asn.au