From: John Hodge Date: Sat, 7 May 2011 13:29:33 +0000 (+0800) Subject: Cleaning up and Debugging (Exposed by AcessNative mostly) X-Git-Tag: rel0.10~121 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=54bf151b1a05b74debdb5f3baec02c18406b74d1;p=tpg%2Facess2.git Cleaning up and Debugging (Exposed by AcessNative mostly) - Removed x86 specific code form debug.c (now in arch/x86/lib.c) - Fixed some bugs in vterm / drvutil that caused some graphical glitches - Added improved process state logging (for user state) - Added instruction tracing (via x86 EFLAGS.TF) - Fixed some possible bugs in the x86 task switch code (DR0 may not be set correctly) - Cleaned up keyboard driver a bit - Fixed some bugs shown by clang's static analyser - Changed how VTerm determines IO devices (now with fallbacks) - Fixed bug in VTerm with line not updating when text wraps - Moved mutex.h to its own header - Moved strdup to heap.h (makes AcessNative easier) - Better debug and handling of errors in threads.c --- diff --git a/Kernel/arch/x86/include/arch.h b/Kernel/arch/x86/include/arch.h index 8d8a14a0..66d7a792 100644 --- a/Kernel/arch/x86/include/arch.h +++ b/Kernel/arch/x86/include/arch.h @@ -123,9 +123,13 @@ typedef struct { typedef struct { Uint EIP, ESP, EBP; + Uint32 UserCS, UserEIP; } tTaskState; // === FUNCTIONS === +extern void Debug_PutCharDebug(char ch); +extern void Debug_PutStringDebug(const char *String); + extern int IS_LOCKED(struct sShortSpinlock *Lock); extern int CPU_HAS_LOCK(struct sShortSpinlock *Lock); extern void SHORTLOCK(struct sShortSpinlock *Lock); diff --git a/Kernel/arch/x86/include/proc.h b/Kernel/arch/x86/include/proc.h index 2b04b757..e31c76d0 100644 --- a/Kernel/arch/x86/include/proc.h +++ b/Kernel/arch/x86/include/proc.h @@ -5,7 +5,7 @@ #ifndef _PROC_H #define _PROC_H -#include +#include // === TYPES == typedef struct sTSS { diff --git a/Kernel/arch/x86/lib.c b/Kernel/arch/x86/lib.c index 5fa9d12e..969332b0 100644 --- a/Kernel/arch/x86/lib.c +++ b/Kernel/arch/x86/lib.c @@ -3,21 +3,29 @@ * lib.c */ #include -#include +#include #define TRACE_LOCKS 0 +#define DEBUG_TO_E9 1 +#define DEBUG_TO_SERIAL 1 +#define SERIAL_PORT 0x3F8 +#define GDB_SERIAL_PORT 0x2F8 + +// === IMPRORTS === #if TRACE_LOCKS extern struct sShortSpinlock glDebug_Lock; #endif - -// === IMPRORTS === extern int GetCPUNum(void); // === PROTOTYPES == Uint64 __udivdi3(Uint64 Num, Uint64 Den); Uint64 __umoddi3(Uint64 Num, Uint64 Den); +// === GLOBALS === + int gbDebug_SerialSetup = 0; + int gbGDB_SerialSetup = 0; + // === CODE === /** * \brief Determine if a short spinlock is locked @@ -158,6 +166,69 @@ void SHORTREL(struct sShortSpinlock *Lock) #endif } +// === DEBUG IO === +#if USE_GDB_STUB +int putDebugChar(char ch) +{ + if(!gbGDB_SerialSetup) { + outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts + outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud + outb(GDB_SERIAL_PORT + 1, 0x00); // (base is (hi byte) + outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit (8N1) + outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it + outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set + gbDebug_SerialSetup = 1; + } + while( (inb(GDB_SERIAL_PORT + 5) & 0x20) == 0 ); + outb(GDB_SERIAL_PORT, ch); + return 0; +} +int getDebugChar(void) +{ + if(!gbGDB_SerialSetup) { + outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts + outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud + outb(GDB_SERIAL_PORT + 1, 0x00); // (hi byte) + outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit + outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it + outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set + gbDebug_SerialSetup = 1; + } + while( (inb(GDB_SERIAL_PORT + 5) & 1) == 0) ; + return inb(GDB_SERIAL_PORT); +} +#endif /* USE_GDB_STUB */ + +void Debug_PutCharDebug(char ch) +{ + #if DEBUG_TO_E9 + __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) ); + #endif + + #if DEBUG_TO_SERIAL + if(!gbDebug_SerialSetup) { + outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts + outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud + outb(SERIAL_PORT + 1, 0x00); // (hi byte) + outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit + outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it + outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set + gbDebug_SerialSetup = 1; + } + while( (inb(SERIAL_PORT + 5) & 0x20) == 0 ); + outb(SERIAL_PORT, ch); + #endif +} + +void Debug_PutStringDebug(const char *String) +{ + while(*String) + Debug_PutCharDebug(*String++); +} + // === IO Commands === void outb(Uint16 Port, Uint8 Data) { diff --git a/Kernel/arch/x86/proc.asm b/Kernel/arch/x86/proc.asm index 87dcd61b..944b24dd 100644 --- a/Kernel/arch/x86/proc.asm +++ b/Kernel/arch/x86/proc.asm @@ -74,6 +74,10 @@ SchedulerBase: push fs push gs + pushf + and BYTE [esp+1], 0xFE ; Clear Trap Flag + popf + mov eax, dr0 push eax ; Debug Register 0, Current Thread @@ -121,7 +125,7 @@ scheduler_return: ; Used by some hackery in Proc_DumpThreadCPUState pop ds popa - add esp, 4 ; CPU ID + add esp, 4*2 ; CPU ID + Dummy error code ; No Error code / int num iret @@ -142,9 +146,10 @@ SpawnTask: ; In child, so now set up stack frame mov ebx, [esp+4] ; Child Function mov edx, [esp+8] ; Argument - ; Child + ; Child Function push edx ; Argument call ebx ; Function + ; Kill thread once done push eax ; Exit Code push 0 ; Kill this thread call Threads_Exit ; Kill Thread @@ -237,7 +242,7 @@ Proc_ReturnToUser: .justKillIt: xor eax, eax xor ebx, ebx - dec ebx + dec ebx ; EBX = -1 int 0xAC [global GetCPUNum] @@ -249,6 +254,15 @@ GetCPUNum: ; TODO: Store in debug registers mov eax, dr1 ret +[extern GetEIP] +[global GetEIP_Sched] +[global GetEIP_Sched_ret] +GetEIP_Sched_ret equ GetEIP_Sched.ret +GetEIP_Sched: + call GetEIP +GetEIP_Sched.ret: + ret + ; Usermode code exported by the kernel [section .usertext] ; Export a place for the user to jump to to call a syscall diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index a85b0ca5..ea8f8ad9 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -13,7 +13,7 @@ #endif // === FLAGS === -#define DEBUG_TRACE_SWITCH 0 +#define DEBUG_TRACE_SWITCH 1 #define DEBUG_DISABLE_DOUBLEFAULT 1 // === CONSTANTS === @@ -40,6 +40,7 @@ extern tIDT gIDT[]; extern void APWait(void); // 16-bit AP pause code extern void APStartup(void); // 16-bit AP startup code extern Uint GetEIP(void); // start.asm +extern Uint GetEIP_Sched(void); // proc.asm extern int GetCPUNum(void); // start.asm extern Uint32 gaInitPageDir[1024]; // start.asm extern char Kernel_Stack_Top[]; @@ -51,6 +52,8 @@ extern void Isr8(void); // Double Fault extern void Proc_ReturnToUser(tVAddr Handler, Uint Argument, tVAddr KernelStack); extern void scheduler_return; // Return address in SchedulerBase extern void IRQCommon; // Common IRQ handler code +extern void IRQCommon_handled; // IRQCommon call return location +extern void GetEIP_Sched_ret; // GetEIP call return location // === PROTOTYPES === void ArchThreads_Init(void); @@ -289,7 +292,6 @@ void ArchThreads_Init(void) #else giNumCPUs = 1; gTSSs = &gTSS0; - MM_FinishVirtualInit(); #endif #if !DEBUG_DISABLE_DOUBLEFAULT @@ -621,7 +623,7 @@ int Proc_Clone(Uint *Err, Uint Flags) newThread->SavedState.EBP = ebp; eip = GetEIP(); if(eip == SWITCH_MAGIC) { - __asm__ __volatile__ ("mov %0, %%db0" : : "r" (newThread) ); + //__asm__ __volatile__ ("mov %0, %%db0" : : "r" (newThread) ); #if USE_MP // ACK the interrupt if( GetCPUNum() ) @@ -674,7 +676,7 @@ int Proc_SpawnWorker(void) new->SavedState.EBP = ebp; eip = GetEIP(); if(eip == SWITCH_MAGIC) { - __asm__ __volatile__ ("mov %0, %%db0" : : "r"(new)); + //__asm__ __volatile__ ("mov %0, %%db0" : : "r"(new)); #if USE_MP // ACK the interrupt if(GetCPUNum()) @@ -855,11 +857,40 @@ void Proc_CallFaultHandler(tThread *Thread) void Proc_DumpThreadCPUState(tThread *Thread) { - Uint32 *stack = (void *)Thread->SavedState.EBP; // EBP = ESP after call and PUSH - if( Thread->CurCPU > -1 ) { - Log(" Currently running"); + int maxBacktraceDistance = 6; + tRegs *regs = NULL; + Uint32 *stack; + + if( Thread->CurCPU != GetCPUNum() ) { + Log(" Currently running"); + return ; + } + + // Backtrace to find the IRQ entrypoint + // - This will usually only be called by an IRQ, so this should + // work + __asm__ __volatile__ ("mov %%ebp, %0" : "=r" (stack)); + while( maxBacktraceDistance -- ) + { + // [ebp] = oldEbp + // [ebp+4] = retaddr + + if( stack[1] == (tVAddr)&IRQCommon_handled ) { + regs = (void*)stack[2]; + break; + } + + stack = (void*)stack[0]; + } + + if( !regs ) { + Log(" Unable to find IRQ Entry"); + return ; + } + + Log(" at %04x:%08x", regs->cs, regs->eip); return ; } @@ -870,25 +901,25 @@ void Proc_DumpThreadCPUState(tThread *Thread) if( diffFromClone > 0 && diffFromClone < 512 ) // When I last checked, GetEIP was at .+0x183 { - // Just spawned full thread Log(" Creating full thread"); return ; } if( diffFromSpawn > 0 && diffFromSpawn < 512 ) // When I last checked, GetEIP was at .+0x99 { - // Just spawned worker thread Log(" Creating worker thread"); return ; } if( diffFromScheduler > 0 && diffFromScheduler < 256 ) // When I last checked, GetEIP was at .+0x60 #else - if( stack[1] == (Uint32)&IRQCommon + 25 ) + Uint32 data[3]; + MM_ReadFromAddrSpace(Thread->MemState.CR3, Thread->SavedState.EBP, data, 12); + if( data[1] == (Uint32)&IRQCommon + 25 ) { - tRegs *regs = (void *) stack[2]; + tRegs *regs = (void *) data[2]; Log(" oldebp = 0x%08x, ret = 0x%08x, regs = 0x%x", - stack[0], stack[1], stack[2] + data[0], data[1], data[2] ); // [EBP] = old EBP // [EBP+0x04] = Return Addr @@ -901,19 +932,11 @@ void Proc_DumpThreadCPUState(tThread *Thread) #endif { // Scheduled out - tRegs *regs = (void *) &stack[4]; - Log(" oldebp = 0x%08x, ret = 0x%08x, cpu = %i, thread = 0x%x", - stack[0], stack[1], stack[2], stack[3]); - // [EBP] = old EBP - // [EBP+0x04] = Return Addr - // [EBP+0x08] = Arg 1 (CPU Number) - // [EBP+0x0C] = Arg 2 (Thread) - // [EBP+0x10] = GS (start of tRegs) - Log(" At %02x:%08x", regs->cs, regs->eip); + Log(" At %04x:%08x", Thread->SavedState.UserCS, Thread->SavedState.UserEIP); return ; } - Log(" Just created"); + Log(" Just created (unknow %p)", Thread->SavedState.EIP); } /** @@ -935,8 +958,13 @@ void Proc_Scheduler(int CPU) thread = gCurrentThread; #endif + // NOTE: + // 2011-04-05 + // Bug may be caused by DR0 not being maintained somewhere, hence + // login is getting loaded with the idle state. if( thread ) { + tRegs *regs; // Reduce remaining quantum and continue timeslice if non-zero if( thread->Remaining-- ) return; @@ -953,6 +981,18 @@ void Proc_Scheduler(int CPU) thread->SavedState.ESP = esp; thread->SavedState.EBP = ebp; thread->SavedState.EIP = eip; + + // TODO: Make this more stable somehow + regs = (tRegs*)(ebp+(2+2)*4); // EBP,Ret + CPU,CurThread + thread->SavedState.UserCS = regs->cs; + thread->SavedState.UserEIP = regs->eip; + + if(thread->bInstrTrace) { + regs->eflags |= 0x100; // Set TF + Log("%p De-scheduled", thread); + } + else + regs->eflags &= ~0x100; // Clear TF } // Get next thread to run @@ -997,18 +1037,26 @@ void Proc_Scheduler(int CPU) } #endif + if( thread->bInstrTrace ) { + Log("%p Scheduled", thread); + } + #if USE_PAE # error "Todo: Implement PAE Address space switching" #else + // Set thread pointer + __asm__ __volatile__("mov %0, %%db0\n\t" : : "r"(thread) ); // Switch threads __asm__ __volatile__ ( "mov %4, %%cr3\n\t" // Set address space "mov %1, %%esp\n\t" // Restore ESP "mov %2, %%ebp\n\t" // and EBP + "or %5, 72(%%ebp)\n\t" // or trace flag to eflags (2+2+4+8+2)*4 "jmp *%3" : : // And return to where we saved state (Proc_Clone or Proc_Scheduler) "a"(SWITCH_MAGIC), "b"(thread->SavedState.ESP), "d"(thread->SavedState.EBP), "c"(thread->SavedState.EIP), - "r"(thread->MemState.CR3) + "r"(thread->MemState.CR3), + "r"(thread->bInstrTrace&&thread->SavedState.EIP==(Uint)&GetEIP_Sched_ret?0x100:0) ); #endif for(;;); // Shouldn't reach here diff --git a/Kernel/arch/x86_64/lib.c b/Kernel/arch/x86_64/lib.c index da9955c9..7402bdaf 100644 --- a/Kernel/arch/x86_64/lib.c +++ b/Kernel/arch/x86_64/lib.c @@ -3,10 +3,19 @@ #include #include +#define DEBUG_TO_E9 1 +#define DEBUG_TO_SERIAL 1 +#define SERIAL_PORT 0x3F8 +#define GDB_SERIAL_PORT 0x2F8 + // === IMPORTS === extern int GetCPUNum(void); extern void *Proc_GetCurThread(void); +// === GLOBALS === + int gbDebug_SerialSetup = 0; + int gbGDB_SerialSetup = 0; + // === CODE === /** * \brief Determine if a short spinlock is locked @@ -131,6 +140,62 @@ void SHORTREL(struct sShortSpinlock *Lock) #endif } +// === DEBUG IO === +int putDebugChar(char ch) +{ + if(!gbGDB_SerialSetup) { + outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts + outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud + outb(GDB_SERIAL_PORT + 1, 0x00); // (base is (hi byte) + outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit (8N1) + outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it + outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set + gbDebug_SerialSetup = 1; + } + while( (inb(GDB_SERIAL_PORT + 5) & 0x20) == 0 ); + outb(GDB_SERIAL_PORT, ch); + return 0; +} +int getDebugChar(void) +{ + if(!gbGDB_SerialSetup) { + outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts + outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud + outb(GDB_SERIAL_PORT + 1, 0x00); // (hi byte) + outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit + outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it + outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set + gbDebug_SerialSetup = 1; + } + while( (inb(GDB_SERIAL_PORT + 5) & 1) == 0) ; + return inb(GDB_SERIAL_PORT); +} + +void Debug_PutCharDebug(char ch) +{ + #if DEBUG_TO_E9 + __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) ); + #endif + + #if DEBUG_TO_SERIAL + if(!gbDebug_SerialSetup) { + outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts + outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) + outb(SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud + outb(SERIAL_PORT + 1, 0x00); // (hi byte) + outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit + outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it + outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set + gbDebug_SerialSetup = 1; + } + while( (inb(SERIAL_PORT + 5) & 0x20) == 0 ); + outb(SERIAL_PORT, ch); + #endif +} + +// === PORT IO === void outb(Uint16 Port, Uint8 Data) { __asm__ __volatile__ ("outb %%al, %%dx"::"d"(Port),"a"(Data)); diff --git a/Kernel/debug.c b/Kernel/debug.c index f59704ad..57964bde 100644 --- a/Kernel/debug.c +++ b/Kernel/debug.c @@ -7,10 +7,6 @@ #include #include -#define DEBUG_TO_E9 1 -#define DEBUG_TO_SERIAL 1 -#define SERIAL_PORT 0x3F8 -#define GDB_SERIAL_PORT 0x2F8 #define DEBUG_MAX_LINE_LEN 256 #define LOCK_DEBUG_OUTPUT 1 @@ -21,8 +17,6 @@ extern void KernelPanic_SetMode(void); extern void KernelPanic_PutChar(char Ch); // === PROTOTYPES === - int putDebugChar(char ch); - int getDebugChar(void); static void Debug_Putchar(char ch); static void Debug_Puts(int DbgOnly, const char *Str); void Debug_DbgOnlyFmt(const char *format, va_list args); @@ -33,8 +27,6 @@ void Debug_SetKTerminal(const char *File); // === GLOBALS === int gDebug_Level = 0; int giDebug_KTerm = -1; - int gbDebug_SerialSetup = 0; - int gbGDB_SerialSetup = 0; int gbDebug_IsKPanic = 0; volatile int gbInPutChar = 0; #if LOCK_DEBUG_OUTPUT @@ -42,60 +34,6 @@ tShortSpinlock glDebug_Lock; #endif // === CODE === -int putDebugChar(char ch) -{ - if(!gbGDB_SerialSetup) { - outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts - outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) - outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud - outb(GDB_SERIAL_PORT + 1, 0x00); // (base is (hi byte) - outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit (8N1) - outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it - outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set - gbDebug_SerialSetup = 1; - } - while( (inb(GDB_SERIAL_PORT + 5) & 0x20) == 0 ); - outb(GDB_SERIAL_PORT, ch); - return 0; -} -int getDebugChar(void) -{ - if(!gbGDB_SerialSetup) { - outb(GDB_SERIAL_PORT + 1, 0x00); // Disable all interrupts - outb(GDB_SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) - outb(GDB_SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud - outb(GDB_SERIAL_PORT + 1, 0x00); // (hi byte) - outb(GDB_SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit - outb(GDB_SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it - outb(GDB_SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set - gbDebug_SerialSetup = 1; - } - while( (inb(GDB_SERIAL_PORT + 5) & 1) == 0) ; - return inb(GDB_SERIAL_PORT); -} - -static void Debug_PutCharDebug(char ch) -{ - #if DEBUG_TO_E9 - __asm__ __volatile__ ( "outb %%al, $0xe9" :: "a"(((Uint8)ch)) ); - #endif - - #if DEBUG_TO_SERIAL - if(!gbDebug_SerialSetup) { - outb(SERIAL_PORT + 1, 0x00); // Disable all interrupts - outb(SERIAL_PORT + 3, 0x80); // Enable DLAB (set baud rate divisor) - outb(SERIAL_PORT + 0, 0x0C); // Set divisor to 12 (lo byte) 9600 baud - outb(SERIAL_PORT + 1, 0x00); // (hi byte) - outb(SERIAL_PORT + 3, 0x03); // 8 bits, no parity, one stop bit - outb(SERIAL_PORT + 2, 0xC7); // Enable FIFO with 14-byte threshold and clear it - outb(SERIAL_PORT + 4, 0x0B); // IRQs enabled, RTS/DSR set - gbDebug_SerialSetup = 1; - } - while( (inb(SERIAL_PORT + 5) & 0x20) == 0 ); - outb(SERIAL_PORT, ch); - #endif -} - static void Debug_Putchar(char ch) { Debug_PutCharDebug(ch); @@ -114,18 +52,18 @@ static void Debug_Putchar(char ch) static void Debug_Puts(int UseKTerm, const char *Str) { int len = 0; - while( *Str ) - { - Debug_PutCharDebug( *Str ); - - if( gbDebug_IsKPanic ) - KernelPanic_PutChar(*Str); - len ++; - Str ++; - } - Str -= len; + Debug_PutStringDebug(Str); + + if( gbDebug_IsKPanic ) + { + for( len = 0; Str[len]; len ++ ) + KernelPanic_PutChar( Str[len] ); + } + else + for( len = 0; Str[len]; len ++ ); + // Output to the kernel terminal if( UseKTerm && !gbDebug_IsKPanic && giDebug_KTerm != -1) { if(gbInPutChar) return ; @@ -196,7 +134,7 @@ void LogF(const char *Fmt, ...) } /** * \fn void Debug(const char *Msg, ...) - * \brief Print only to the debug channel + * \brief Print only to the debug channel (not KTerm) */ void Debug(const char *Fmt, ...) { diff --git a/Kernel/drv/kb.c b/Kernel/drv/kb.c index 07e07f5d..b67c8e31 100644 --- a/Kernel/drv/kb.c +++ b/Kernel/drv/kb.c @@ -14,8 +14,9 @@ #define USE_KERNEL_MAGIC 1 // === IMPORTS === -void Threads_Dump(void); -void Heap_Stats(void); +extern void Threads_ToggleTrace(int TID); +extern void Threads_Dump(void); +extern void Heap_Stats(void); // === PROTOTYPES === int KB_Install(char **Arguments); @@ -191,12 +192,19 @@ void KB_IRQHandler(int IRQNum) case '8': case '9': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': { - char str[2] = {ch,0}; - if(giKB_MagicAddressPos == BITS/4) break; + char str[4] = {'0', 'x', ch, 0}; + if(giKB_MagicAddressPos == BITS/4) return; giKB_MagicAddress |= atoi(str) << giKB_MagicAddressPos; giKB_MagicAddressPos ++; } - break; + return; + + // Instruction Tracing + case 't': + Log("Toggle instruction tracing on %i\n", giKB_MagicAddress); + Threads_ToggleTrace( giKB_MagicAddress ); + giKB_MagicAddress = 0; giKB_MagicAddressPos = 0; + return; // Thread List Dump case 'p': Threads_Dump(); return; @@ -208,10 +216,10 @@ void KB_IRQHandler(int IRQNum) } #endif - // Is shift pressed - // - Darn ugly hacks !!x means (bool)x - if( !!gbKB_ShiftState ^ gbKB_CapsState) + // Capitals required? + if( (gbKB_ShiftState != 0) != (gbKB_CapsState != 0)) { + // TODO: Move this to the keyboard map header switch(ch) { case 0: break; diff --git a/Kernel/drv/proc.c b/Kernel/drv/proc.c index c0ce6edc..0d1ae529 100644 --- a/Kernel/drv/proc.c +++ b/Kernel/drv/proc.c @@ -155,10 +155,10 @@ int SysFS_RegisterFile(const char *Path, const char *Data, int Length) child->Node.ReadDir = SysFS_Comm_ReadDir; child->Node.FindDir = SysFS_Comm_FindDir; if( !prev ) { - //if(ent) + if(ent) ent->Node.ImplPtr = child; - //else - // gSysFS_DriverInfo.RootNode.ImplPtr = child; + else + gSysFS_DriverInfo.RootNode.ImplPtr = child; // ^^^ Impossible (There is already /Version) } else @@ -184,7 +184,7 @@ int SysFS_RegisterFile(const char *Path, const char *Data, int Length) child = ent->Node.ImplPtr; else child = gSysFS_DriverInfo.RootNode.ImplPtr; - for( child = ent->Node.ImplPtr; child; prev = child, child = child->Next ) + for( ; child; child = child->Next ) { if( strcmp( &Path[start], child->Name ) == 0 ) break; @@ -283,7 +283,10 @@ int SysFS_RemoveFile(int ID) parent = file->Parent; // Remove from file list - prev->ListNext = file->ListNext; + if(prev) + prev->ListNext = file->ListNext; + else + gSysFS_FileList = file->ListNext; file->Node.Size = 0; file->Node.ImplPtr = NULL; diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index 31e7a500..ec5c1f54 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -11,7 +11,7 @@ #include #include -#define USE_CTRL_ALT 0 +#define USE_CTRL_ALT 1 // === CONSTANTS === #define VERSION ((0<<8)|(50)) @@ -57,7 +57,7 @@ typedef struct { int InputRead; //!< Input buffer read position int InputWrite; //!< Input buffer write position char InputBuffer[MAX_INPUT_CHARS8]; - tSemaphore InputSemaphore; +// tSemaphore InputSemaphore; tVT_Char *Text; Uint32 *Buffer; @@ -160,10 +160,12 @@ int VT_Install(char **Arguments) Log_Debug("VTerm", "Argument '%s'", arg); if( strcmp(opt, "Video") == 0 ) { - gsVT_OutputDevice = strdup(val); + if( !gsVT_OutputDevice && Modules_InitialiseBuiltin( val ) == 0 ) + gsVT_OutputDevice = strdup(val); } else if( strcmp(opt, "Input") == 0 ) { - gsVT_InputDevice = strdup(val); + if( !gsVT_InputDevice && Modules_InitialiseBuiltin( val ) == 0 ) + gsVT_InputDevice = strdup(val); } else if( strcmp(opt, "Width") == 0 ) { giVT_RealWidth = atoi( val ); @@ -177,9 +179,6 @@ int VT_Install(char **Arguments) } } - if(gsVT_OutputDevice) Modules_InitialiseBuiltin( gsVT_OutputDevice ); - if(gsVT_InputDevice) Modules_InitialiseBuiltin( gsVT_InputDevice ); - // Apply Defaults if(!gsVT_OutputDevice) gsVT_OutputDevice = strdup(DEFAULT_OUTPUT); if(!gsVT_InputDevice) gsVT_InputDevice = strdup(DEFAULT_INPUT); @@ -223,7 +222,7 @@ int VT_Install(char **Arguments) gVT_Terminals[i].Node.Read = VT_Read; gVT_Terminals[i].Node.Write = VT_Write; gVT_Terminals[i].Node.IOCtl = VT_Terminal_IOCtl; - Semaphore_Init(&gVT_Terminals[i].InputSemaphore, 0, MAX_INPUT_CHARS8, "VTerm", gVT_Terminals[i].Name); +// Semaphore_Init(&gVT_Terminals[i].InputSemaphore, 0, MAX_INPUT_CHARS8, "VTerm", gVT_Terminals[i].Name); } // Add to DevFS @@ -313,6 +312,9 @@ void VT_SetResolution(int Width, int Height) { if( gVT_Terminals[i].Mode != TERM_MODE_TEXT ) continue; + gVT_Terminals[i].TextWidth = giVT_RealWidth/giVT_CharWidth; + gVT_Terminals[i].TextHeight = giVT_RealHeight/giVT_CharHeight; + gVT_Terminals[i].Text = realloc( gVT_Terminals[i].Text, newBufSize*sizeof(tVT_Char) @@ -735,7 +737,7 @@ void VT_KBCallBack(Uint32 Codepoint) #else case KEY_LALT: gbVT_AltDown &= ~1; break; case KEY_RALT: gbVT_AltDown &= ~2; break; - case KEY_LCTRL: gbVT_CtrlDown &= ~1 break; + case KEY_LCTRL: gbVT_CtrlDown &= ~1; break; case KEY_RCTRL: gbVT_CtrlDown &= ~2; break; #endif } @@ -1101,6 +1103,9 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) default: Term->Text[ Term->WritePos ].Ch = Ch; Term->Text[ Term->WritePos ].Colour = Term->CurColour; + // Update the line before wrapping + if( (Term->WritePos + 1) % Term->TextWidth == 0 ) + VT_int_UpdateScreen( Term, 0 ); Term->WritePos ++; break; } @@ -1146,7 +1151,7 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) { //Debug("Term->WritePos (%i) >= %i", // Term->WritePos, - // Term->ViewPos + Term->Width*Term->Height + // Term->ViewPos + Term->TextWidth*Term->TextHeight // ); //Debug("Scrolling screen only"); @@ -1161,6 +1166,8 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) //Debug("Term->ViewPos = %i", Term->ViewPos); VT_int_ScrollFramebuffer( Term ); VT_int_UpdateScreen( Term, 0 ); + + //VT_int_UpdateScreen( Term, 1 ); // HACK! } //LEAVE('-'); diff --git a/Kernel/drvutil.c b/Kernel/drvutil.c index bac78948..a96e2227 100644 --- a/Kernel/drvutil.c +++ b/Kernel/drvutil.c @@ -57,7 +57,7 @@ Uint64 DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, break; case VIDEO_2DOP_BLIT: - if(rem < 16) return Length-rem; + if(rem < 12) return Length-rem; if(!Handlers->Blit) { Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver" @@ -73,7 +73,7 @@ Uint64 DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, ); rem -= 16; - stream = (void*)((tVAddr)stream + 16); + stream = (void*)((tVAddr)stream + 12); break; } diff --git a/Kernel/heap.c b/Kernel/heap.c index c440b183..07a3aad0 100644 --- a/Kernel/heap.c +++ b/Kernel/heap.c @@ -664,8 +664,8 @@ void Heap_Stats(void) // Print the block info? #if 1 - Log_Debug("Heap", "%p - 0x%x (%i) Owned by %s:%i", - head, head->Size, head->ValidSize, head->File, head->Line); + Log_Debug("Heap", "%p (0x%x) - 0x%x (%i) Owned by %s:%i", + head->Data, MM_GetPhysAddr((tVAddr)&head->Data), head->Size, head->ValidSize, head->File, head->Line); #endif } diff --git a/Kernel/include/acess.h b/Kernel/include/acess.h index a2d406b5..79c5062b 100644 --- a/Kernel/include/acess.h +++ b/Kernel/include/acess.h @@ -22,15 +22,6 @@ typedef Uint tGID; typedef Sint64 tTimestamp; typedef Sint64 tTime; typedef struct sShortSpinlock tShortSpinlock; -typedef struct sMutex tMutex; - -struct sMutex { - tShortSpinlock Protector; //!< Protector for the lock strucure - const char *Name; //!< Human-readable name - struct sThread *volatile Owner; //!< Owner of the lock (set upon getting the lock) - struct sThread *Waiting; //!< Waiting threads - struct sThread *LastWaiting; //!< Waiting threads -}; // --- Helper Macros --- /** @@ -337,8 +328,7 @@ extern char *strncpy(char *__dest, const char *__src, size_t max); extern int strcmp(const char *__str1, const char *__str2); extern int strncmp(const char *Str1, const char *Str2, size_t num); extern int strucmp(const char *Str1, const char *Str2); -//extern char *strdup(const char *Str); -#define strdup(Str) _strdup(_MODULE_NAME_"/"__FILE__, __LINE__, (Str)) +// strdup macro is defined in heap.h extern char *_strdup(const char *File, int Line, const char *Str); extern char **str_split(const char *__str, char __ch); extern char *strchr(const char *__s, int __c); @@ -428,9 +418,6 @@ extern tGID Threads_GetGID(void); extern int SpawnTask(tThreadFunction Function, void *Arg); extern Uint *Threads_GetCfgPtr(int Id); extern int Threads_SetName(const char *NewName); -extern int Mutex_Acquire(tMutex *Mutex); -extern void Mutex_Release(tMutex *Mutex); -extern int Mutex_IsLocked(tMutex *Mutex); /** * \} */ @@ -441,5 +428,6 @@ extern int DivUp(int num, int dem); #include #include #include +#include #endif diff --git a/Kernel/include/heap.h b/Kernel/include/heap.h index 28d33c0d..b058e8b4 100644 --- a/Kernel/include/heap.h +++ b/Kernel/include/heap.h @@ -20,4 +20,6 @@ extern void Heap_Validate(void); #define free(ptr) Heap_Deallocate((ptr)) #define IsHeap(ptr) Heap_IsHeapAddr((ptr)) +#define strdup(Str) _strdup(_MODULE_NAME_"/"__FILE__, __LINE__, (Str)) + #endif diff --git a/Kernel/include/mutex.h b/Kernel/include/mutex.h new file mode 100644 index 00000000..326dbd2c --- /dev/null +++ b/Kernel/include/mutex.h @@ -0,0 +1,48 @@ +/* + * Acess2 Kernel + * mutex.h + * - Mutual Exclusion syncronisation primitive + */ +#ifndef _MUTEX_H +#define _MUTEX_H + +#include + +typedef struct sMutex tMutex; + +struct sMutex +{ + tShortSpinlock Protector; //!< Protector for the lock strucure + const char *Name; //!< Human-readable name + struct sThread *volatile Owner; //!< Owner of the lock (set upon getting the lock) + struct sThread *Waiting; //!< Waiting threads + struct sThread *LastWaiting; //!< Waiting threads +}; + +/** + * \brief Acquire a heavy mutex + * \param Mutex Mutex to acquire + * \return zero on success, -1 if terminated + * + * This type of mutex checks if the mutex is avaliable, and acquires it + * if it is. Otherwise, the current thread is added to the mutex's wait + * queue and the thread suspends. When the holder of the mutex completes, + * the oldest thread (top thread) on the queue is given the lock and + * restarted. + */ +extern int Mutex_Acquire(tMutex *Mutex); + +/** + * \brief Release a held mutex + * \param Mutex Mutex to release + * \note Releasing a non-held mutex has no effect + */ +extern void Mutex_Release(tMutex *Mutex); + +/** + * \brief Is this mutex locked? + * \param Mutex Mutex pointer + */ +extern int Mutex_IsLocked(tMutex *Mutex); + +#endif diff --git a/Kernel/threads.c b/Kernel/threads.c index b4838308..7a8cbde7 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -59,6 +59,7 @@ void Threads_Sleep(void); void Threads_AddActive(tThread *Thread); tThread *Threads_RemActive(void); #endif +void Threads_ToggleTrace(int TID); void Threads_Fault(int Num); void Threads_SegFault(tVAddr Addr); #if 0 @@ -71,7 +72,6 @@ tGID Threads_GetGID(void); #endif void Threads_Dump(void); void Threads_DumpActive(void); - #if 0 int Mutex_Acquire(tMutex *Mutex); void Mutex_Release(tMutex *Mutex); @@ -122,6 +122,9 @@ void Threads_Init(void) { ArchThreads_Init(); + Log_Debug("Threads", "Offsets of tThread"); + Log_Debug("Threads", ".Priority = %i", offsetof(tThread, Priority)); + // Create Initial Task #if SCHEDULER_TYPE == SCHED_RR_PRI gaActiveThreads[gThreadZero.Priority] = &gThreadZero; @@ -184,6 +187,7 @@ void Threads_SetPriority(tThread *Thread, int Pri) if(Thread == NULL) Thread = Proc_GetCurThread(); // Bounds checking // - If < 0, set to lowest priority + // - Minumum priority is actualy a high number, 0 is highest if(Pri < 0) Pri = MIN_PRIORITY; if(Pri > MIN_PRIORITY) Pri = MIN_PRIORITY; @@ -208,7 +212,9 @@ void Threads_SetPriority(tThread *Thread, int Pri) #if SCHEDULER_TYPE == SCHED_LOTTERY giFreeTickets -= caiTICKET_COUNTS[Thread->Priority] - caiTICKET_COUNTS[Pri]; # if DEBUG_TRACE_TICKETS - Log("Threads_SetTickets: new giFreeTickets = %i", giFreeTickets); + Log("Threads_SetTickets: new giFreeTickets = %i [-%i+%i]", + giFreeTickets, + caiTICKET_COUNTS[Thread->Priority], caiTICKET_COUNTS[Pri]); # endif #endif Thread->Priority = Pri; @@ -217,6 +223,12 @@ void Threads_SetPriority(tThread *Thread, int Pri) else Thread->Priority = Pri; #endif + + #if DEBUG_TRACE_STATE + Log("Threads_SetPriority: %p(%i %s) pri set %i", + Thread, Thread->TID, Thread->ThreadName, + Pri); + #endif } /** @@ -233,10 +245,7 @@ tThread *Threads_CloneTCB(Uint *Err, Uint Flags) // Allocate and duplicate new = malloc(sizeof(tThread)); - if(new == NULL) { - *Err = -ENOMEM; - return NULL; - } + if(new == NULL) { *Err = -ENOMEM; return NULL; } memcpy(new, cur, sizeof(tThread)); new->CurCPU = -1; @@ -248,6 +257,7 @@ tThread *Threads_CloneTCB(Uint *Err, Uint Flags) // Get Thread ID new->TID = giNextTID++; new->Parent = cur; + new->bInstrTrace = 0; // Clone Name new->ThreadName = strdup(cur->ThreadName); @@ -334,6 +344,7 @@ tThread *Threads_CloneThreadZero(void) // Set State new->Remaining = new->Quantum = cur->Quantum; new->Priority = cur->Priority; + new->bInstrTrace = 0; // Set Signal Handlers new->CurFaultNum = 0; @@ -772,6 +783,13 @@ int Threads_WakeTID(tTID TID) return ret; } +void Threads_ToggleTrace(int TID) +{ + tThread *thread = Threads_GetThread(TID); + if(!thread) return ; + thread->bInstrTrace = !thread->bInstrTrace; +} + /** * \brief Adds a thread to the active queue */ @@ -987,6 +1005,8 @@ void Threads_DumpActive(void) Log(" ERROR State (%i) != THREAD_STAT_ACTIVE (%i)", thread->Status, THREAD_STAT_ACTIVE); Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum); Log(" KStack 0x%x", thread->KernelStack); + if( thread->bInstrTrace ) + Log(" Tracing Enabled"); Proc_DumpThreadCPUState(thread); } @@ -1031,6 +1051,9 @@ void Threads_Dump(void) } Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum); Log(" KStack 0x%x", thread->KernelStack); + if( thread->bInstrTrace ) + Log(" Tracing Enabled"); + Proc_DumpThreadCPUState(thread); } } @@ -1117,7 +1140,7 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) } #if SCHEDULER_TYPE == SCHED_LOTTERY && DEBUG_TRACE_TICKETS else - LogF("Log: CPU%i released %p (%i %s)->Status = %i (Released)\n", + LogF("Log: CPU%i released %p (%i %s)->Status = %i (Released,not in pool)\n", CPU, Last, Last->TID, Last->ThreadName, Last->Status); #endif Last->CurCPU = -1; @@ -1255,16 +1278,7 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) return thread; } -/** - * \brief Acquire a heavy mutex - * \param Mutex Mutex to acquire - * - * This type of mutex checks if the mutex is avaliable, and acquires it - * if it is. Otherwise, the current thread is added to the mutex's wait - * queue and the thread suspends. When the holder of the mutex completes, - * the oldest thread (top thread) on the queue is given the lock and - * restarted. - */ +// Acquire mutex (see mutex.h for documentation) int Mutex_Acquire(tMutex *Mutex) { tThread *us = Proc_GetCurThread(); @@ -1293,6 +1307,12 @@ int Mutex_Acquire(tMutex *Mutex) Mutex->Waiting = us; Mutex->LastWaiting = us; } + + #if DEBUG_TRACE_STATE + Log("%p (%i %s) waiting on mutex %p", + us, us->TID, us->ThreadName, Mutex); + #endif + #if 0 { int i = 0; @@ -1324,11 +1344,7 @@ int Mutex_Acquire(tMutex *Mutex) return 0; } -/** - * \brief Release a held mutex - * \param Mutex Mutex to release - * \note Releasing a non-held mutex has no effect - */ +// Release a mutex void Mutex_Release(tMutex *Mutex) { SHORTLOCK( &Mutex->Protector ); @@ -1361,10 +1377,7 @@ void Mutex_Release(tMutex *Mutex) #endif } -/** - * \brief Is this mutex locked? - * \param Mutex Mutex pointer - */ +// Check if a mutex is locked int Mutex_IsLocked(tMutex *Mutex) { return Mutex->Owner != NULL; @@ -1427,6 +1440,12 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) Sem->LastWaiting = us; } + #if DEBUG_TRACE_STATE + Log("%p (%i %s) waiting on semaphore %p %s:%s", + us, us->TID, us->ThreadName, + Sem, Sem->ModName, Sem->Name); + #endif + SHORTREL( &glThreadListLock ); SHORTREL( &Sem->Protector ); while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield(); @@ -1458,6 +1477,13 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) given = Sem->MaxValue - Sem->Value; Sem->Value -= given; + + #if DEBUG_TRACE_STATE + Log("%p (%i %s) woken by wait on %p %s:%s", + toWake, toWake->TID, toWake->ThreadName, + Sem, Sem->ModName, Sem->Name); + #endif + // Save the number we gave to the thread's status toWake->RetStatus = given; @@ -1514,6 +1540,12 @@ int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd) Sem->LastSignaling = us; } + #if DEBUG_TRACE_STATE + Log("%p (%i %s) signaling semaphore %p %s:%s", + us, us->TID, us->ThreadName, + Sem, Sem->ModName, Sem->Name); + #endif + SHORTREL( &glThreadListLock ); SHORTREL( &Sem->Protector ); while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield(); @@ -1542,12 +1574,13 @@ int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd) { tThread *toWake = Sem->Waiting; + // Remove thread from list (double ended, so clear LastWaiting if needed) Sem->Waiting = Sem->Waiting->Next; - // Reset ->LastWaiting to NULL if we have just removed the last waiting thread if( Sem->Waiting == NULL ) Sem->LastWaiting = NULL; - // Figure out how much to give + // Figure out how much to give to woken thread + // - Requested count is stored in ->RetStatus if( toWake->RetStatus && Sem->Value > toWake->RetStatus ) given = toWake->RetStatus; else @@ -1557,6 +1590,14 @@ int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd) // Save the number we gave to the thread's status toWake->RetStatus = given; + if(toWake->bInstrTrace) + Log("%s(%i) given %i from %p", toWake->ThreadName, toWake->TID, given, Sem); + #if DEBUG_TRACE_STATE + Log("%p (%i %s) woken by signal on %p %s:%s", + toWake, toWake->TID, toWake->ThreadName, + Sem, Sem->ModName, Sem->Name); + #endif + // Wake the sleeper SHORTLOCK( &glThreadListLock ); if( toWake->Status != THREAD_STAT_ACTIVE ) diff --git a/Kernel/vfs/fs/root.c b/Kernel/vfs/fs/root.c index e9c9f09c..4c3c6a27 100644 --- a/Kernel/vfs/fs/root.c +++ b/Kernel/vfs/fs/root.c @@ -155,7 +155,7 @@ char *Root_ReadDir(tVFS_Node *Node, int Pos) for( ; child && Pos--; child = child->Next ) ; - if(Pos) return strdup(child->Name); + if(child) return strdup(child->Name); return NULL; } diff --git a/Kernel/vfs/open.c b/Kernel/vfs/open.c index 08201025..600cedc6 100644 --- a/Kernel/vfs/open.c +++ b/Kernel/vfs/open.c @@ -78,7 +78,7 @@ char *VFS_GetAbsPath(const char *Path) strcpy(ret, cwd); ret[cwdLen] = '/'; strcpy(&ret[cwdLen+1], Path); - //Log("ret = '%s'\n", ret); + //Log("ret = '%s'", ret); } // Parse Path @@ -590,7 +590,7 @@ void VFS_Close(int FD) // Get handle h = VFS_GetHandle(FD); if(h == NULL) { - Log_Warning("VFS", "Invalid file handle passed to VFS_Close, 0x%x\n", FD); + Log_Warning("VFS", "Invalid file handle passed to VFS_Close, 0x%x", FD); return; } diff --git a/Kernel/vfs/select.c b/Kernel/vfs/select.c index 85c7d62f..22417c88 100644 --- a/Kernel/vfs/select.c +++ b/Kernel/vfs/select.c @@ -148,6 +148,7 @@ int VFS_Select(int MaxHandle, fd_set *ReadHandles, fd_set *WriteHandles, fd_set if( !Timeout || *Timeout > 0 ) { ret = Semaphore_Wait(&thread_info->SleepHandle, 1); + // TODO: Do something with ret } // Fill output (modify *Handles)