Uint8 State; // 0: Unavaliable, 1: Idle, 2: Active
Uint16 Resvd;
tThread *Current;
+ tThread *IdleThread;
} tCPU;
#endif
int i;
#endif
- // Start Interrupts (and hence scheduler)
- __asm__ __volatile__("sti");
-
#if USE_MP
// Start APs
for( i = 0; i < giNumCPUs; i ++ )
{
+ // Create Idle Task
+ if(Proc_Clone(0, 0) == 0)
+ {
+ gaCPUs[i].IdleThread = Proc_GetCurThread();
+ gaCPUs[i].IdleThread->ThreadName = "Idle Thread";
+ gaCPUs[i].IdleThread->NumTickets = 0; // Never called randomly
+ gaCPUs[i].IdleThread->Quantum = 1; // 1 slice quantum
+ for(;;) HALT(); // Just yeilds
+ }
gaCPUs[i].Current = NULL;
+
+ // 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("Waiting for APs to come up\n");
- //__asm__ __volatile__ ("sti");
+ __asm__ __volatile__ ("sti");
while( giNumInitingCPUs ) __asm__ __volatile__ ("hlt");
MM_FinishVirtualInit();
+ #else
+ // Create Idle Task
+ if(Proc_Clone(0, 0) == 0)
+ {
+ tThread *cur = Proc_GetCurThread();
+ cur->ThreadName = "Idle Thread";
+ Threads_SetTickets(0); // Never called randomly
+ cur->Quantum = 1; // 1 slice quantum
+ for(;;) HALT(); // Just yeilds
+ }
+
+ // Set current task
+ gCurrentThread = &gThreadZero;
+
+ // Start Interrupts (and hence scheduler)
+ __asm__ __volatile__("sti");
#endif
}
thread = gCurrentThread;
#endif
- // Reduce remaining quantum and continue timeslice if non-zero
- if(thread->Remaining--) return;
- // Reset quantum for next call
- thread->Remaining = thread->Quantum;
-
- // Get machine state
- __asm__ __volatile__ ("mov %%esp, %0":"=r"(esp));
- __asm__ __volatile__ ("mov %%ebp, %0":"=r"(ebp));
- eip = GetEIP();
- if(eip == SWITCH_MAGIC) return; // Check if a switch happened
-
- // Save machine state
- thread->SavedState.ESP = esp;
- thread->SavedState.EBP = ebp;
- thread->SavedState.EIP = eip;
+ if( thread )
+ {
+ // Reduce remaining quantum and continue timeslice if non-zero
+ if(thread->Remaining--) return;
+ // Reset quantum for next call
+ thread->Remaining = thread->Quantum;
+
+ // Get machine state
+ __asm__ __volatile__ ("mov %%esp, %0":"=r"(esp));
+ __asm__ __volatile__ ("mov %%ebp, %0":"=r"(ebp));
+ eip = GetEIP();
+ if(eip == SWITCH_MAGIC) return; // Check if a switch happened
+
+ // Save machine state
+ thread->SavedState.ESP = esp;
+ thread->SavedState.EBP = ebp;
+ thread->SavedState.EIP = eip;
+ }
// Get next thread to run
thread = Threads_GetNextToRun(CPU, thread);
- // Error Check
+ // No avaliable tasks, just go into low power mode
if(thread == NULL) {
- Warning("Hmm... Threads_GetNextToRun returned NULL, I don't think this should happen.\n");
- return;
+ //HALT();
+ //return;
+ thread = gaCPUs[CPU].IdleThread;
}
#if DEBUG_TRACE_SWITCH
// Set current thread
#if USE_MP
- gaCPUs[CPU].Current->bIsRunning = 0;
gaCPUs[CPU].Current = thread;
- thread->bIsRunning = 1;
#else
gCurrentThread = thread;
#endif
// -- Core Thread --
// Only used for the core kernel
tThread gThreadZero = {
- NULL, 0, // Next, Lock
- THREAD_STAT_ACTIVE, // Status
- 0, // Exit Status
- 0, 0, // TID, TGID
- 0, 0, // UID, GID
- 0, // Parent Thread ID
- "ThreadZero", // Name
-
- 0, // Kernel Stack
- {0}, // Saved State
- {0}, // VM State
-
- 0, 0, // Current Fault, Fault Handler
-
- NULL, NULL, // Messages, Last Message
- DEFAULT_QUANTUM, DEFAULT_QUANTUM, // Quantum, Remaining
- DEFAULT_TICKETS,
- {0} // Default config to zero
+ Status: THREAD_STAT_ACTIVE, // Status
+ ThreadName: "ThreadZero", // Name
+ Quantum: DEFAULT_QUANTUM, Remaining: DEFAULT_QUANTUM, // Quantum, Remaining
+ NumTickets: DEFAULT_TICKETS
};
// -- Processes --
// --- Locks ---
gActiveThreads = &gThreadZero;
//giFreeTickets = gThreadZero.NumTickets;
giNumActiveThreads = 1;
-
- #if 1
- // Create Idle Task
- if(Proc_Clone(0, 0) == 0)
- {
- tThread *cur = Proc_GetCurThread();
- cur->ThreadName = "Idle Thread";
- Threads_SetTickets(0); // Never called randomly
- cur->Quantum = 1; // 1 slice quantum
- for(;;) HALT(); // Just yeilds
- }
- #endif
-
+
Proc_Start();
}
int Threads_SetName(char *NewName)
{
tThread *cur = Proc_GetCurThread();
- if( IsHeap(cur->ThreadName) )
- free( cur->ThreadName );
- // TODO: Possible concurrency issue
- cur->ThreadName = malloc(strlen(NewName)+1);
- strcpy(cur->ThreadName, NewName);
+ char *oldname = cur->ThreadName;
+
+ cur->ThreadName = NULL;
+
+ if( IsHeap(oldname) ) free( oldname );
+
+ cur->ThreadName = strdup(NewName);
return 0;
}
new->PTID = cur->TID;
// Clone Name
+ Log("Threads_CloneTCB: cur (%p) ->ThreadName = %p", cur, cur->ThreadName);
new->ThreadName = strdup(cur->ThreadName);
// Set Thread Group ID (PID)
giFreeTickets += Last->NumTickets;
Last->CurCPU = -1;
}
-
+
+ // No free tickets (all tasks delegated to cores)
+ if( giFreeTickets == 0 ) {
+ RELEASE(&glThreadListLock);
+ return NULL;
+ }
+
// Get the ticket number
ticket = number = rand() % giFreeTickets;