extern int giNextTID;
extern int giTotalTickets;
extern int giNumActiveThreads;
+extern tThread gThreadZero;
extern tThread *gActiveThreads;
extern tThread *gSleepingThreads;
extern tThread *gDeleteThreads;
+extern tThread *Threads_GetNextToRun(int CPU);
// === PROTOTYPES ===
void ArchThreads_Init();
// === GLOBALS ===
// --- Current State ---
#if USE_MP
-tThread **gCurrentThread = NULL;
+tThread *gCurrentThread[MAX_CPUS] = {NULL};
#else
tThread *gCurrentThread = NULL;
#endif
}
#endif
+ #if USE_MP
+ gCurrentThread[0] = &gThreadZero;
+ #else
+ gCurrentThread = &gThreadZero;
+ #endif
+
+ #if USE_PAE
+ gThreadZero.MemState.PDP[0] = 0;
+ gThreadZero.MemState.PDP[1] = 0;
+ gThreadZero.MemState.PDP[2] = 0;
+ #else
+ gThreadZero.MemState.CR3 = (Uint)gaInitPageDir - KERNEL_BASE;
+ #endif
+
// Set timer frequency
outb(0x43, 0x34); // Set Channel 0, Low/High, Rate Generator
outb(0x40, TIMER_DIVISOR&0xFF); // Low Byte of Divisor
// Change Stacks
Proc_ChangeStack();
-
+}
+
+/**
+ * \fn void Proc_Start()
+ * \brief Start process scheduler
+ */
+void Proc_Start()
+{
// Start Interrupts (and hence scheduler)
__asm__ __volatile__("sti");
}
return;
}
- curBase = gCurrentThread->KernelStack;
+ curBase = (Uint)&Kernel_Stack_Top;
LOG("curBase = 0x%x, newBase = 0x%x", curBase, newBase);
return newThread->TID;
}
-#if 0
-/**
- * \fn void Proc_SetSignalHandler(int Num, void *Handler)
- * \brief Sets the signal handler for a signal
- */
-void Proc_SetSignalHandler(int Num, void *Handler)
-{
- if(Num < 0 || Num >= NSIG) return;
-
- gCurrentThread->SignalHandlers[Num] = Handler;
-}
-
-/**
- * \fn void Proc_SendSignal(int TID, int Num)
- */
-void Proc_SendSignal(int TID, int Num)
-{
- tThread *thread = Proc_GetThread(TID);
- void *handler;
-
- if(!thread) return ;
-
- handler = thread->SignalHandlers[Num];
-
- // Panic?
- if(handler == SIG_ERR) {
- Proc_Kill(TID);
- return ;
- }
- // Dump Core?
- if(handler == -2) {
- Proc_Kill(TID);
- return ;
- }
- // Ignore?
- if(handler == -2) return;
-
- // Check the type and handle if the thread is already in a signal
- if(thread->CurSignal != 0) {
- if(Num < _SIGTYPE_FATAL)
- Proc_Kill(TID);
- } else {
- while(thread->CurSignal != 0)
- Proc_Yield();
- }
- }
-
- //TODO:
-}
-
-#endif
-
/**
* \fn Uint Proc_MakeUserStack()
* \brief Creates a new user stack
void Proc_Scheduler(int CPU)
{
Uint esp, ebp, eip;
- Uint number, ticket;
tThread *thread;
// If the spinlock is set, let it complete
return;
}
- // Reduce remaining quantum
+ // Reduce remaining quantum and continue timeslice if non-zero
if(gCurrentThread->Remaining--) return;
// Reset quantum for next call
gCurrentThread->Remaining = gCurrentThread->Quantum;
gCurrentThread->SavedState.EBP = ebp;
gCurrentThread->SavedState.EIP = eip;
- // Special case: 1 thread
- if(giNumActiveThreads == 1)
- {
- // Check if a switch is needed (NumActive can be 1 after a sleep)
- if(gActiveThreads == gCurrentThread) return;
- // Switch processes
- gCurrentThread = gActiveThreads;
- goto performSwitch;
- }
-
- // Get the ticket number
- ticket = number = rand() % giTotalTickets;
-
- // Find the next thread
- for(thread=gActiveThreads;thread;thread=thread->Next)
- {
- if(thread->NumTickets > number) break;
- number -= thread->NumTickets;
- }
+ // Get next thread
+ thread = Threads_GetNextToRun(CPU);
// Error Check
- if(thread == NULL)
- {
- number = 0;
- for(thread=gActiveThreads;thread;thread=thread->Next)
- number += thread->NumTickets;
- Panic("Bookeeping Failed - giTotalTicketCount (%i) != true count (%i)",
- giTotalTickets, number);
+ if(thread == NULL) {
+ Warning("Hmm... Threads_GetNextToRun returned NULL, I don't think this should happen.\n");
+ return;
}
// Set current thread
// Update Kernel Stack pointer
gTSSs[CPU].ESP0 = thread->KernelStack;
-performSwitch:
// Set address space
- //MM_SetCR3( gCurrentThread->CR3 );
__asm__ __volatile__ ("mov %0, %%cr3"::"a"(gCurrentThread->MemState.CR3));
// Switch threads
__asm__ __volatile__ (