X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Farch%2Fx86%2Fproc.c;h=d3aea161011985734aa65e030ecd54754e849c46;hb=be5123fe1f4aa66b76ce8ef589362ad21b6bbf72;hp=82a3f40908fb821f08d893ac86cb6d94e10a4cec;hpb=51ab5f489bc356940c95cc936fd0508e8f07ea97;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/arch/x86/proc.c b/KernelLand/Kernel/arch/x86/proc.c index 82a3f409..d3aea161 100644 --- a/KernelLand/Kernel/arch/x86/proc.c +++ b/KernelLand/Kernel/arch/x86/proc.c @@ -18,6 +18,7 @@ #define DEBUG_TRACE_SWITCH 0 #define DEBUG_DISABLE_DOUBLEFAULT 1 #define DEBUG_VERY_SLOW_PERIOD 0 +#define DEBUG_NOPREEMPT 1 // === CONSTANTS === // Base is 1193182 @@ -35,6 +36,7 @@ typedef struct sCPU Uint8 State; // 0: Unavaliable, 1: Idle, 2: Active Uint16 Resvd; tThread *Current; + tThread *LastTimerThread; // Used to do preeemption } tCPU; // === IMPORTS === @@ -402,21 +404,42 @@ void MP_StartAP(int CPU) *(Uint16*)(KERNEL_BASE|0x469) = 0xFFFF; outb(0x70, 0x0F); outb(0x71, 0x0A); // Set warm reset flag MP_SendIPI(gaCPUs[CPU].APICID, 0, 5); // Init IPI - - // Delay - inb(0x80); inb(0x80); inb(0x80); inb(0x80); - + + // Take a quick nap (20ms) + Time_Delay(20); + // TODO: Use a better address, preferably registered with the MM // - MM_AllocDMA mabye? // Create a far jump *(Uint8*)(KERNEL_BASE|0x11000) = 0xEA; // Far JMP - *(Uint16*)(KERNEL_BASE|0x11001) = (Uint)&APStartup - (KERNEL_BASE|0xFFFF0); // IP + *(Uint16*)(KERNEL_BASE|0x11001) = (Uint16)&APStartup + 0x10; // IP *(Uint16*)(KERNEL_BASE|0x11003) = 0xFFFF; // CS + + giNumInitingCPUs ++; + // Send a Startup-IPI to make the CPU execute at 0x11000 (which we // just filled) MP_SendIPI(gaCPUs[CPU].APICID, 0x11, 6); // StartupIPI - giNumInitingCPUs ++; + tTime timeout = now() + 2; + while( giNumInitingCPUs && now() > timeout ) + HALT(); + + if( giNumInitingCPUs == 0 ) + return ; + + // First S-IPI failed, send again + MP_SendIPI(gaCPUs[CPU].APICID, 0x11, 6); + timeout = now() + 2; + while( giNumInitingCPUs && now() > timeout ) + HALT(); + if( giNumInitingCPUs == 0 ) + return ; + + Log_Notice("Proc", "CPU %i (APIC %x) didn't come up", CPU, gaCPUs[CPU].APICID); + + // Oh dammit. + giNumInitingCPUs = 0; } void MP_SendIPIVector(int CPU, Uint8 Vector) @@ -437,11 +460,9 @@ void MP_SendIPI(Uint8 APICID, int Vector, int DeliveryMode) // Hi val = (Uint)APICID << 24; -// Log("%p = 0x%08x", &gpMP_LocalAPIC->ICR[1], val); gpMP_LocalAPIC->ICR[1].Val = val; // Low (and send) val = ((DeliveryMode & 7) << 8) | (Vector & 0xFF); -// Log("%p = 0x%08x", &gpMP_LocalAPIC->ICR[0], val); gpMP_LocalAPIC->ICR[0].Val = val; } #endif @@ -465,37 +486,29 @@ void Proc_IdleThread(void *Ptr) */ void Proc_Start(void) { - int tid; #if USE_MP - int i; - #endif + // BSP still should run the current task + gaCPUs[giProc_BootProcessorID].Current = &gThreadZero; + + __asm__ __volatile__ ("sti"); - #if USE_MP // Start APs - for( i = 0; i < giNumCPUs; i ++ ) + for( int i = 0; i < giNumCPUs; i ++ ) { - if(i) gaCPUs[i].Current = NULL; - + if(i != giProc_BootProcessorID) + gaCPUs[i].Current = NULL; + // Create Idle Task - tid = Proc_NewKThread(Proc_IdleThread, &gaCPUs[i]); + Proc_NewKThread(Proc_IdleThread, &gaCPUs[i]); // Start the AP if( i != giProc_BootProcessorID ) { MP_StartAP( i ); } } - - // BSP still should run the current task - gaCPUs[0].Current = &gThreadZero; - - // Start interrupts and wait for APs to come up - Log_Debug("Proc", "Waiting for APs to come up"); - __asm__ __volatile__ ("sti"); - while( giNumInitingCPUs ) __asm__ __volatile__ ("hlt"); #else // Create Idle Task - tid = Proc_NewKThread(Proc_IdleThread, &gaCPUs[0]); -// gaCPUs[0].IdleThread = Threads_GetThread(tid); + Proc_NewKThread(Proc_IdleThread, &gaCPUs[0]); // Set current task gaCPUs[0].Current = &gThreadZero; @@ -586,9 +599,8 @@ void Proc_ClearThread(tThread *Thread) tTID Proc_NewKThread(void (*Fcn)(void*), void *Data) { Uint esp; - tThread *newThread, *cur; + tThread *newThread; - cur = Proc_GetCurThread(); newThread = Threads_CloneTCB(0); if(!newThread) return -1; @@ -664,7 +676,7 @@ tPID Proc_Clone(Uint Flags) * \fn int Proc_SpawnWorker(void) * \brief Spawns a new worker thread */ -int Proc_SpawnWorker(void (*Fcn)(void*), void *Data) +tThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data) { tThread *new; Uint stack_contents[4]; @@ -673,7 +685,7 @@ int Proc_SpawnWorker(void (*Fcn)(void*), void *Data) new = Threads_CloneThreadZero(); if(!new) { Warning("Proc_SpawnWorker - Out of heap space!\n"); - return -1; + return NULL; } // Create the stack contents @@ -695,7 +707,7 @@ int Proc_SpawnWorker(void (*Fcn)(void*), void *Data) new->Status = THREAD_STAT_PREINIT; Threads_AddActive( new ); - return new->TID; + return new; } /** @@ -709,7 +721,7 @@ Uint Proc_MakeUserStack(void) // Check Prospective Space for( i = USER_STACK_SZ >> 12; i--; ) - if( MM_GetPhysAddr( base + (i<<12) ) != 0 ) + if( MM_GetPhysAddr( (void*)(base + (i<<12)) ) != 0 ) break; if(i != -1) return 0; @@ -861,6 +873,10 @@ void Proc_DumpThreadCPUState(tThread *Thread) __asm__ __volatile__ ("mov %%ebp, %0" : "=r" (stack)); while( maxBacktraceDistance -- ) { + if( !CheckMem(stack, 8) ) { + regs = NULL; + break; + } // [ebp] = oldEbp // [ebp+4] = retaddr @@ -939,6 +955,7 @@ void Proc_Reschedule(void) // Update CPU state gaCPUs[cpu].Current = nextthread; + gaCPUs[cpu].LastTimerThread = NULL; gTSSs[cpu].ESP0 = nextthread->KernelStack-4; __asm__ __volatile__("mov %0, %%db0\n\t" : : "r"(nextthread) ); @@ -976,49 +993,26 @@ void Proc_Reschedule(void) */ void Proc_Scheduler(int CPU) { -#if 0 - tThread *thread; - - // If the spinlock is set, let it complete - if(IS_LOCKED(&glThreadListLock)) return; - - // Get current thread - thread = gaCPUs[CPU].Current; - - if( thread ) - { - tRegs *regs; - Uint ebp; - // Reduce remaining quantum and continue timeslice if non-zero - if( thread->Remaining-- ) - return; - // Reset quantum for next call - thread->Remaining = thread->Quantum; - - // TODO: Make this more stable somehow - __asm__ __volatile__("mov %%ebp, %0" : "=r" (ebp)); - 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 - } - - // TODO: Ack timer? #if USE_MP if( GetCPUNum() ) gpMP_LocalAPIC->EOI.Val = 0; else #endif outb(0x20, 0x20); - __asm__ __volatile__ ("sti"); - Proc_Reschedule(); -#endif + __asm__ __volatile__ ("sti"); + + // Call the timer update code + Timer_CallTimers(); + + #if !DEBUG_NOPREEMPT + // If two ticks happen within the same task, and it's not an idle task, swap + if( gaCPUs[CPU].Current->TID > giNumCPUs && gaCPUs[CPU].Current == gaCPUs[CPU].LastTimerThread ) + { + Proc_Reschedule(); + } + + gaCPUs[CPU].LastTimerThread = gaCPUs[CPU].Current; + #endif } // === EXPORTS ===