From 6488590bbc291c99612e1efee0070b73109a1b3c Mon Sep 17 00:00:00 2001 From: John Hodge Date: Wed, 28 Jul 2010 22:47:23 +0800 Subject: [PATCH] Bugfixed MP scheduling code in MP build --- Kernel/arch/x86/proc.c | 79 +++++++++++++++++++++++++++++------------- Kernel/threads.c | 57 +++++++++++------------------- 2 files changed, 75 insertions(+), 61 deletions(-) diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index 04331213..bee311aa 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -29,6 +29,7 @@ typedef struct sCPU Uint8 State; // 0: Unavaliable, 1: Idle, 2: Active Uint16 Resvd; tThread *Current; + tThread *IdleThread; } tCPU; #endif @@ -427,23 +428,51 @@ void Proc_Start(void) 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 } @@ -829,29 +858,33 @@ void Proc_Scheduler(int CPU) 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 @@ -864,9 +897,7 @@ void Proc_Scheduler(int CPU) // Set current thread #if USE_MP - gaCPUs[CPU].Current->bIsRunning = 0; gaCPUs[CPU].Current = thread; - thread->bIsRunning = 1; #else gCurrentThread = thread; #endif diff --git a/Kernel/threads.c b/Kernel/threads.c index 58100b69..53756edb 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -52,24 +52,10 @@ void Threads_Dump(void); // -- 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 --- @@ -98,19 +84,7 @@ void Threads_Init(void) 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(); } @@ -121,11 +95,13 @@ void Threads_Init(void) 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; } @@ -182,6 +158,7 @@ tThread *Threads_CloneTCB(Uint *Err, Uint Flags) 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) @@ -736,7 +713,13 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) 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; -- 2.20.1