#define DEBUG_TRACE_SWITCH 0
#define DEBUG_DISABLE_DOUBLEFAULT 1
#define DEBUG_VERY_SLOW_PERIOD 0
+#define DEBUG_NOPREEMPT 1
// === CONSTANTS ===
// Base is 1193182
Uint8 State; // 0: Unavaliable, 1: Idle, 2: Active
Uint16 Resvd;
tThread *Current;
+ tThread *LastTimerThread; // Used to do preeemption
} tCPU;
// === IMPORTS ===
*/
void Proc_Start(void)
{
- int tid;
#if USE_MP
int i;
#endif
if(i) 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 ) {
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;
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;
// 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;
__asm__ __volatile__ ("mov %%ebp, %0" : "=r" (stack));
while( maxBacktraceDistance -- )
{
+ if( !CheckMem(stack, 8) ) {
+ regs = NULL;
+ break;
+ }
// [ebp] = oldEbp
// [ebp+4] = retaddr
// 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) );
*/
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 ===