2 * AcessOS Microkernel Version
8 #define DEBUG_MAX_LINE_LEN 256
9 #define LOCK_DEBUG_OUTPUT 1 // Avoid interleaving of output lines?
10 #define TRACE_TO_KTERM 0 // Send ENTER/DEBUG/LEAVE to debug?
13 extern void Threads_Dump(void);
14 extern void KernelPanic_SetMode(void);
15 extern void KernelPanic_PutChar(char Ch);
18 static void Debug_Putchar(char ch);
19 static void Debug_Puts(int bUseKTerm, const char *Str);
20 void Debug_DbgOnlyFmt(const char *format, va_list args);
21 void Debug_FmtS(int bUseKTerm, const char *format, ...);
22 void Debug_Fmt(int bUseKTerm, const char *format, va_list args);
23 void Debug_SetKTerminal(const char *File);
27 int giDebug_KTerm = -1;
28 int gbDebug_IsKPanic = 0;
29 volatile int gbInPutChar = 0;
31 tShortSpinlock glDebug_Lock;
35 static void Debug_Putchar(char ch)
37 Debug_PutCharDebug(ch);
38 if( !gbDebug_IsKPanic )
40 if(gbInPutChar) return ;
42 if(giDebug_KTerm != -1)
43 VFS_Write(giDebug_KTerm, 1, &ch);
47 KernelPanic_PutChar(ch);
50 static void Debug_Puts(int UseKTerm, const char *Str)
54 Debug_PutStringDebug(Str);
56 if( gbDebug_IsKPanic )
58 for( len = 0; Str[len]; len ++ )
59 KernelPanic_PutChar( Str[len] );
62 for( len = 0; Str[len]; len ++ );
64 // Output to the kernel terminal
65 if( UseKTerm && !gbDebug_IsKPanic && giDebug_KTerm != -1)
67 if(gbInPutChar) return ;
69 VFS_Write(giDebug_KTerm, len, Str);
74 void Debug_DbgOnlyFmt(const char *format, va_list args)
76 Debug_Fmt(0, format, args);
79 void Debug_Fmt(int bUseKTerm, const char *format, va_list args)
81 char buf[DEBUG_MAX_LINE_LEN];
83 buf[DEBUG_MAX_LINE_LEN-1] = 0;
84 len = vsnprintf(buf, DEBUG_MAX_LINE_LEN-1, format, args);
85 //if( len < DEBUG_MAX_LINE )
87 Debug_Puts(bUseKTerm, buf);
91 void Debug_FmtS(int bUseKTerm, const char *format, ...)
94 va_start(args, format);
95 Debug_Fmt(bUseKTerm, format, args);
99 void Debug_KernelPanic(void)
101 #if LOCK_DEBUG_OUTPUT
102 SHORTREL(&glDebug_Lock);
104 gbDebug_IsKPanic = 1;
105 KernelPanic_SetMode();
109 * \fn void LogF(const char *Msg, ...)
110 * \brief Raw debug log (no new line, no prefix)
112 void LogF(const char *Fmt, ...)
116 #if LOCK_DEBUG_OUTPUT
117 SHORTLOCK(&glDebug_Lock);
122 Debug_Fmt(1, Fmt, args);
126 #if LOCK_DEBUG_OUTPUT
127 SHORTREL(&glDebug_Lock);
131 * \fn void Debug(const char *Msg, ...)
132 * \brief Print only to the debug channel (not KTerm)
134 void Debug(const char *Fmt, ...)
138 #if LOCK_DEBUG_OUTPUT
139 SHORTLOCK(&glDebug_Lock);
142 Debug_Puts(0, "Debug: ");
144 Debug_DbgOnlyFmt(Fmt, args);
146 Debug_PutCharDebug('\r');
147 Debug_PutCharDebug('\n');
148 #if LOCK_DEBUG_OUTPUT
149 SHORTREL(&glDebug_Lock);
153 * \fn void Log(const char *Msg, ...)
155 void Log(const char *Fmt, ...)
159 #if LOCK_DEBUG_OUTPUT
160 SHORTLOCK(&glDebug_Lock);
163 Debug_Puts(1, "Log: ");
165 Debug_Fmt(1, Fmt, args);
167 Debug_Puts(1, "\r\n");
169 #if LOCK_DEBUG_OUTPUT
170 SHORTREL(&glDebug_Lock);
173 void Warning(const char *Fmt, ...)
177 #if LOCK_DEBUG_OUTPUT
178 SHORTLOCK(&glDebug_Lock);
181 Debug_Puts(1, "Warning: ");
183 Debug_Fmt(1, Fmt, args);
188 #if LOCK_DEBUG_OUTPUT
189 SHORTREL(&glDebug_Lock);
192 void Panic(const char *Fmt, ...)
196 #if LOCK_DEBUG_OUTPUT
197 SHORTLOCK(&glDebug_Lock);
199 // And never SHORTREL
203 Debug_Puts(1, "Panic: ");
205 Debug_Fmt(1, Fmt, args);
215 void Debug_SetKTerminal(const char *File)
218 if(giDebug_KTerm != -1) {
223 tmp = VFS_Open(File, VFS_OPENFLAG_WRITE);
224 // Log_Log("Debug", "Opened '%s' as 0x%x", File, tmp);
226 // Log_Log("Debug", "Returning to %p", __builtin_return_address(0));
229 void Debug_Enter(const char *FuncName, const char *ArgTypes, ...)
234 tTID tid = Threads_GetTID();
236 #if LOCK_DEBUG_OUTPUT
237 SHORTLOCK(&glDebug_Lock);
242 va_start(args, ArgTypes);
244 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
245 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
247 Debug_Puts(TRACE_TO_KTERM, FuncName);
248 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
249 Debug_Puts(TRACE_TO_KTERM, ": (");
253 pos = strpos(ArgTypes, ' ');
254 if(pos == -1 || pos > 1) {
256 Debug_Puts(TRACE_TO_KTERM, ArgTypes+1);
258 Debug_FmtS(TRACE_TO_KTERM, "%.*s", pos-1, ArgTypes+1);
260 Debug_Puts(TRACE_TO_KTERM, "=");
264 case 'p': Debug_FmtS(TRACE_TO_KTERM, "%p", va_arg(args, void*)); break;
265 case 'P': Debug_FmtS(TRACE_TO_KTERM, "%P", va_arg(args, tPAddr)); break;
266 case 's': Debug_FmtS(TRACE_TO_KTERM, "'%s'", va_arg(args, char*)); break;
267 case 'i': Debug_FmtS(TRACE_TO_KTERM, "%i", va_arg(args, int)); break;
268 case 'u': Debug_FmtS(TRACE_TO_KTERM, "%u", va_arg(args, Uint)); break;
269 case 'x': Debug_FmtS(TRACE_TO_KTERM, "0x%x", va_arg(args, Uint)); break;
270 case 'b': Debug_FmtS(TRACE_TO_KTERM, "0b%b", va_arg(args, Uint)); break;
271 case 'X': Debug_FmtS(TRACE_TO_KTERM, "0x%llx", va_arg(args, Uint64)); break; // Extended (64-Bit)
272 case 'B': Debug_FmtS(TRACE_TO_KTERM, "0b%llb", va_arg(args, Uint64)); break; // Extended (64-Bit)
275 Debug_Puts(TRACE_TO_KTERM, ", ");
279 ArgTypes = &ArgTypes[pos+1];
283 Debug_Puts(TRACE_TO_KTERM, ")\r\n");
285 #if LOCK_DEBUG_OUTPUT
286 SHORTREL(&glDebug_Lock);
290 void Debug_Log(const char *FuncName, const char *Fmt, ...)
293 int i = gDebug_Level;
294 tTID tid = Threads_GetTID();
296 #if LOCK_DEBUG_OUTPUT
297 SHORTLOCK(&glDebug_Lock);
300 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
301 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
303 Debug_Puts(TRACE_TO_KTERM, FuncName);
304 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
305 Debug_Puts(TRACE_TO_KTERM, ": ");
308 Debug_Fmt(TRACE_TO_KTERM, Fmt, args);
311 Debug_Puts(TRACE_TO_KTERM, "\r\n");
313 #if LOCK_DEBUG_OUTPUT
314 SHORTREL(&glDebug_Lock);
318 void Debug_Leave(const char *FuncName, char RetType, ...)
322 tTID tid = Threads_GetTID();
324 #if LOCK_DEBUG_OUTPUT
325 SHORTLOCK(&glDebug_Lock);
330 va_start(args, RetType);
336 Debug_FmtS(TRACE_TO_KTERM, "%014lli ", now());
338 while(i--) Debug_Puts(TRACE_TO_KTERM, " ");
340 Debug_Puts(TRACE_TO_KTERM, FuncName);
341 Debug_FmtS(TRACE_TO_KTERM, "[%i]", tid);
342 Debug_Puts(TRACE_TO_KTERM, ": RETURN");
346 Debug_Puts(TRACE_TO_KTERM, "\r\n");
347 #if LOCK_DEBUG_OUTPUT
348 SHORTREL(&glDebug_Lock);
355 case 'n': Debug_Puts(TRACE_TO_KTERM, " NULL"); break;
356 case 'p': Debug_Fmt(TRACE_TO_KTERM, " %p", args); break;
357 case 'P': Debug_Fmt(TRACE_TO_KTERM, " %P", args); break; // PAddr
358 case 's': Debug_Fmt(TRACE_TO_KTERM, " '%s'", args); break;
359 case 'i': Debug_Fmt(TRACE_TO_KTERM, " %i", args); break;
360 case 'u': Debug_Fmt(TRACE_TO_KTERM, " %u", args); break;
361 case 'x': Debug_Fmt(TRACE_TO_KTERM, " 0x%x", args); break;
363 case 'X': Debug_Fmt(TRACE_TO_KTERM, " 0x%llx", args); break;
365 Debug_Puts(TRACE_TO_KTERM, "\r\n");
369 #if LOCK_DEBUG_OUTPUT
370 SHORTREL(&glDebug_Lock);
374 void Debug_HexDump(const char *Header, const void *Data, Uint Length)
376 const Uint8 *cdat = Data;
378 LogF("%014lli ", now());
379 Debug_Puts(1, Header);
380 LogF(" (Hexdump of %p)\r\n", Data);
382 #define CH(n) ((' '<=cdat[(n)]&&cdat[(n)]<0x7F) ? cdat[(n)] : '.')
386 LogF("%014lli Log: %04x:"
387 " %02x %02x %02x %02x %02x %02x %02x %02x"
388 " %02x %02x %02x %02x %02x %02x %02x %02x"
389 " %c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c\r\n",
392 cdat[ 0], cdat[ 1], cdat[ 2], cdat[ 3], cdat[ 4], cdat[ 5], cdat[ 6], cdat[ 7],
393 cdat[ 8], cdat[ 9], cdat[10], cdat[11], cdat[12], cdat[13], cdat[14], cdat[15],
394 CH(0), CH(1), CH(2), CH(3), CH(4), CH(5), CH(6), CH(7),
395 CH(8), CH(9), CH(10), CH(11), CH(12), CH(13), CH(14), CH(15)
404 LogF("%014lli Log: %04x: ", now(), pos);
405 for(i = 0; i < Length; i ++)
407 LogF("%02x ", cdat[i]);
409 for( ; i < 16; i ++) LogF(" ");
411 for(i = 0; i < Length; i ++)
413 if( i == 8 ) LogF(" ");