2 * AcessOS Microkernel Version
5 * TODO: Move the Debug_putchar methods out to the arch/ tree
10 #define DEBUG_MAX_LINE_LEN 256
12 #define LOCK_DEBUG_OUTPUT 1
15 extern void Threads_Dump(void);
16 extern void KernelPanic_SetMode(void);
17 extern void KernelPanic_PutChar(char Ch);
20 static void Debug_Putchar(char ch);
21 static void Debug_Puts(int DbgOnly, const char *Str);
22 void Debug_DbgOnlyFmt(const char *format, va_list args);
23 void Debug_FmtS(const char *format, ...);
24 void Debug_Fmt(const char *format, va_list args);
25 void Debug_SetKTerminal(const char *File);
29 int giDebug_KTerm = -1;
30 int gbDebug_IsKPanic = 0;
31 volatile int gbInPutChar = 0;
33 tShortSpinlock glDebug_Lock;
37 static void Debug_Putchar(char ch)
39 Debug_PutCharDebug(ch);
40 if( !gbDebug_IsKPanic )
42 if(gbInPutChar) return ;
44 if(giDebug_KTerm != -1)
45 VFS_Write(giDebug_KTerm, 1, &ch);
49 KernelPanic_PutChar(ch);
52 static void Debug_Puts(int UseKTerm, const char *Str)
56 Debug_PutStringDebug(Str);
58 if( gbDebug_IsKPanic )
60 for( len = 0; Str[len]; len ++ )
61 KernelPanic_PutChar( Str[len] );
64 for( len = 0; Str[len]; len ++ );
66 // Output to the kernel terminal
67 if( UseKTerm && !gbDebug_IsKPanic && giDebug_KTerm != -1)
69 if(gbInPutChar) return ;
71 VFS_Write(giDebug_KTerm, len, Str);
76 void Debug_DbgOnlyFmt(const char *format, va_list args)
78 char buf[DEBUG_MAX_LINE_LEN];
80 buf[DEBUG_MAX_LINE_LEN-1] = 0;
81 len = vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
82 //if( len < DEBUG_MAX_LINE )
87 void Debug_Fmt(const char *format, va_list args)
89 char buf[DEBUG_MAX_LINE_LEN];
91 buf[DEBUG_MAX_LINE_LEN-1] = 0;
92 len = vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
93 //if( len < DEBUG_MAX_LINE )
99 void Debug_FmtS(const char *format, ...)
102 va_start(args, format);
103 Debug_Fmt(format, args);
107 void Debug_KernelPanic()
109 gbDebug_IsKPanic = 1;
110 KernelPanic_SetMode();
114 * \fn void LogF(const char *Msg, ...)
115 * \brief Raw debug log (no new line, no prefix)
117 void LogF(const char *Fmt, ...)
121 #if LOCK_DEBUG_OUTPUT
122 SHORTLOCK(&glDebug_Lock);
127 Debug_Fmt(Fmt, args);
131 #if LOCK_DEBUG_OUTPUT
132 SHORTREL(&glDebug_Lock);
136 * \fn void Debug(const char *Msg, ...)
137 * \brief Print only to the debug channel (not KTerm)
139 void Debug(const char *Fmt, ...)
143 #if LOCK_DEBUG_OUTPUT
144 SHORTLOCK(&glDebug_Lock);
147 Debug_Puts(0, "Debug: ");
149 Debug_DbgOnlyFmt(Fmt, args);
151 Debug_PutCharDebug('\r');
152 Debug_PutCharDebug('\n');
153 #if LOCK_DEBUG_OUTPUT
154 SHORTREL(&glDebug_Lock);
158 * \fn void Log(const char *Msg, ...)
160 void Log(const char *Fmt, ...)
164 #if LOCK_DEBUG_OUTPUT
165 SHORTLOCK(&glDebug_Lock);
168 Debug_Puts(1, "Log: ");
170 Debug_Fmt(Fmt, args);
175 #if LOCK_DEBUG_OUTPUT
176 SHORTREL(&glDebug_Lock);
179 void Warning(const char *Fmt, ...)
183 #if LOCK_DEBUG_OUTPUT
184 SHORTLOCK(&glDebug_Lock);
187 Debug_Puts(1, "Warning: ");
189 Debug_Fmt(Fmt, args);
194 #if LOCK_DEBUG_OUTPUT
195 SHORTREL(&glDebug_Lock);
198 void Panic(const char *Fmt, ...)
202 #if LOCK_DEBUG_OUTPUT
203 SHORTLOCK(&glDebug_Lock);
205 // And never SHORTREL
209 Debug_Puts(1, "Panic: ");
211 Debug_Fmt(Fmt, args);
218 // __asm__ __volatile__ ("xchg %bx, %bx");
219 // __asm__ __volatile__ ("cli;\n\thlt");
220 // for(;;) __asm__ __volatile__ ("hlt");
224 void Debug_SetKTerminal(const char *File)
227 if(giDebug_KTerm != -1) {
232 tmp = VFS_Open(File, VFS_OPENFLAG_WRITE);
233 Log_Log("Debug", "Opened '%s' as 0x%x", File, tmp);
235 Log_Log("Debug", "Returning to %p", __builtin_return_address(0));
238 void Debug_Enter(const char *FuncName, const char *ArgTypes, ...)
243 tTID tid = Threads_GetTID();
245 #if LOCK_DEBUG_OUTPUT
246 SHORTLOCK(&glDebug_Lock);
251 va_start(args, ArgTypes);
253 LogF("%014lli ", now());
254 while(i--) Debug_Putchar(' ');
256 Debug_Puts(1, FuncName);
257 Debug_FmtS("[%i]", tid);
258 Debug_Puts(1, ": (");
262 pos = strpos(ArgTypes, ' ');
263 if(pos == -1 || pos > 1) {
265 Debug_Puts(1, ArgTypes+1);
267 for( i = 1; i < pos; i ++ )
268 Debug_Putchar(ArgTypes[i]);
274 case 'p': LogF("%p", va_arg(args, void*)); break;
275 case 's': LogF("'%s'", va_arg(args, char*)); break;
276 case 'i': LogF("%i", va_arg(args, int)); break;
277 case 'u': LogF("%u", va_arg(args, Uint)); break;
278 case 'x': LogF("0x%x", va_arg(args, Uint)); break;
279 case 'b': LogF("0b%b", va_arg(args, Uint)); break;
280 case 'X': LogF("0x%llx", va_arg(args, Uint64)); break; // Extended (64-Bit)
281 case 'B': LogF("0b%llb", va_arg(args, Uint64)); break; // Extended (64-Bit)
284 Debug_Putchar(','); Debug_Putchar(' ');
288 ArgTypes = &ArgTypes[pos+1];
292 Debug_Putchar(')'); Debug_Putchar('\r'); Debug_Putchar('\n');
294 #if LOCK_DEBUG_OUTPUT
295 SHORTREL(&glDebug_Lock);
299 void Debug_Log(const char *FuncName, const char *Fmt, ...)
302 int i = gDebug_Level;
303 tTID tid = Threads_GetTID();
305 #if LOCK_DEBUG_OUTPUT
306 SHORTLOCK(&glDebug_Lock);
311 LogF("%014lli ", now());
312 while(i--) Debug_Putchar(' ');
314 Debug_Puts(1, FuncName);
315 Debug_FmtS("[%i]", tid);
317 Debug_Fmt(Fmt, args);
323 #if LOCK_DEBUG_OUTPUT
324 SHORTREL(&glDebug_Lock);
328 void Debug_Leave(const char *FuncName, char RetType, ...)
332 tTID tid = Threads_GetTID();
334 #if LOCK_DEBUG_OUTPUT
335 SHORTLOCK(&glDebug_Lock);
340 va_start(args, RetType);
346 LogF("%014lli ", now());
348 while(i--) Debug_Putchar(' ');
350 Debug_Puts(1, FuncName);
351 Debug_FmtS("[%i]", tid);
352 Debug_Puts(1, ": RETURN");
358 #if LOCK_DEBUG_OUTPUT
359 SHORTREL(&glDebug_Lock);
367 case 'n': Debug_Puts(1, "NULL"); break;
368 case 'p': Debug_Fmt("%p", args); break;
369 case 's': Debug_Fmt("'%s'", args); break;
370 case 'i': Debug_Fmt("%i", args); break;
371 case 'u': Debug_Fmt("%u", args); break;
372 case 'x': Debug_Fmt("0x%x", args); break;
374 case 'X': Debug_Fmt("0x%llx", args); break;
381 #if LOCK_DEBUG_OUTPUT
382 SHORTREL(&glDebug_Lock);
386 void Debug_HexDump(const char *Header, const void *Data, Uint Length)
388 const Uint8 *cdat = Data;
390 LogF("%014lli ", now());
391 Debug_Puts(1, Header);
392 LogF(" (Hexdump of %p)\n", Data);
394 #define CH(n) ((' '<=cdat[(n)]&&cdat[(n)]<0x7F) ? cdat[(n)] : '.')
398 LogF("%014lli Log: %04x:"
399 " %02x %02x %02x %02x %02x %02x %02x %02x"
400 " %02x %02x %02x %02x %02x %02x %02x %02x"
401 " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\n",
404 cdat[ 0], cdat[ 1], cdat[ 2], cdat[ 3], cdat[ 4], cdat[ 5], cdat[ 6], cdat[ 7],
405 cdat[ 8], cdat[ 9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
406 CH(0), CH(1), CH(2), CH(3), CH(4), CH(5), CH(6), CH(7),
407 CH(8), CH(9), CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
416 LogF("%014lli Log: %04x: ", now(), pos);
417 for(i = 0; i < Length; i ++)
419 LogF("%02x ", cdat[i]);
421 for( ; i < 16; i ++) LogF(" ");
423 for(i = 0; i < Length; i ++)
425 if( i == 8 ) LogF(" ");