From: John Hodge Date: Fri, 11 Nov 2011 10:20:39 +0000 (+0800) Subject: Kernel/threads - Cleaning out delete queue X-Git-Tag: rel0.14~118 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=6c86cb7a9c4b01daadf3e8624845ab35b55ee73a;p=tpg%2Facess2.git Kernel/threads - Cleaning out delete queue - No (well, for now) chance of deadlock in scheduler - Also added a way for thread resources to be cleared properly --- diff --git a/Kernel/arch/armv7/proc.c b/Kernel/arch/armv7/proc.c index 0b4627a7..54951e11 100644 --- a/Kernel/arch/armv7/proc.c +++ b/Kernel/arch/armv7/proc.c @@ -99,6 +99,11 @@ void Proc_StartUser(Uint Entrypoint, Uint Base, int ArgC, char **ArgV, int DataS } } +void Proc_ClearThread(tThread *Thread) +{ + Log_Warning("Proc", "TODO: Nuke address space etc"); +} + tTID Proc_Clone(Uint Flags) { tThread *new; diff --git a/Kernel/arch/x86/proc.c b/Kernel/arch/x86/proc.c index cdb51b66..5ec3676d 100644 --- a/Kernel/arch/x86/proc.c +++ b/Kernel/arch/x86/proc.c @@ -57,7 +57,6 @@ extern char scheduler_return[]; // Return address in SchedulerBase extern char IRQCommon[]; // Common IRQ handler code extern char IRQCommon_handled[]; // IRQCommon call return location extern char GetEIP_Sched_ret[]; // GetEIP call return location -extern void Threads_AddToDelete(tThread *Thread); extern void SwitchTasks(Uint NewSP, Uint *OldSP, Uint NewIP, Uint *OldIO, Uint CR3); extern void Proc_InitialiseSSE(void); extern void Proc_SaveSSE(Uint DestPtr); @@ -558,6 +557,7 @@ void Proc_ChangeStack(void) void Proc_ClearThread(tThread *Thread) { + Log_Warning("Proc", "TODO: Nuke address space etc"); if(Thread->SavedState.SSE) { free(Thread->SavedState.SSE); Thread->SavedState.SSE = NULL; @@ -636,7 +636,7 @@ int Proc_Clone(Uint Flags) // Check for errors if( newThread->MemState.CR3 == 0 ) { Log_Error("Proc", "Proc_Clone: MM_Clone failed"); - Threads_AddToDelete(newThread); + Threads_Delete(newThread); return -1; } diff --git a/Kernel/arch/x86_64/proc.c b/Kernel/arch/x86_64/proc.c index e6ada788..75778c2f 100644 --- a/Kernel/arch/x86_64/proc.c +++ b/Kernel/arch/x86_64/proc.c @@ -41,7 +41,6 @@ extern Uint Proc_CloneInt(Uint *RSP, Uint *CR3); extern void NewTaskHeader(void); // Actually takes cdecl args extern Uint64 gInitialPML4[512]; // start.asm -extern tShortSpinlock glThreadListLock; extern int giNumCPUs; extern int giNextTID; extern int giTotalTickets; @@ -429,6 +428,14 @@ tThread *Proc_GetCurThread(void) #endif } +/* + * + */ +void Proc_ClearThread(tThread *Thread) +{ + Log_Warning("Proc", "TODO: Nuke address space etc"); +} + /** * \brief Create a new kernel thread */ diff --git a/Kernel/include/threads_int.h b/Kernel/include/threads_int.h index 64b29868..4cc11ec6 100644 --- a/Kernel/include/threads_int.h +++ b/Kernel/include/threads_int.h @@ -110,6 +110,7 @@ extern int Threads_Wake(tThread *Thread); extern void Threads_Kill(tThread *Thread, int Status); extern void Threads_AddActive(tThread *Thread); extern tThread *Threads_RemActive(void); +extern void Threads_Delete(tThread *Thread); extern tThread *Threads_GetNextToRun(int CPU, tThread *Last); extern tThread *Threads_CloneTCB(Uint Flags); diff --git a/Kernel/semaphore.c b/Kernel/semaphore.c index b73ce02b..d4583e74 100644 --- a/Kernel/semaphore.c +++ b/Kernel/semaphore.c @@ -38,7 +38,8 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) SHORTLOCK( &Sem->Protector ); // Check if there's already items avaliable - if( Sem->Value > 0 ) { + if( Sem->Value > 0 ) + { // Take what we need if( MaxToTake && Sem->Value > MaxToTake ) taken = MaxToTake; diff --git a/Kernel/threads.c b/Kernel/threads.c index d1f3a754..6933dd60 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -37,6 +37,7 @@ const enum eConfigTypes cCONFIG_TYPES[] = { // === PROTOTYPES === void Threads_Init(void); #if 0 +void Threads_Delete(tThread *Thread); int Threads_SetName(const char *NewName); #endif char *Threads_GetName(int ID); @@ -46,7 +47,6 @@ tThread *Threads_CloneTCB(Uint *Err, Uint Flags); int Threads_WaitTID(int TID, int *status); tThread *Threads_GetThread(Uint TID); #endif -void Threads_AddToDelete(tThread *Thread); tThread *Threads_int_DelFromQueue(tThread **List, tThread *Thread); #if 0 void Threads_Exit(int TID, int Status); @@ -90,7 +90,6 @@ volatile Uint giNextTID = 1; // Next TID to allocate // --- Thread Lists --- tThread *gAllThreads = NULL; // All allocated threads tThread *gSleepingThreads = NULL; // Sleeping Threads -tThread *gDeleteThreads = NULL; // Threads to delete int giNumCPUs = 1; // Number of CPUs BOOL gaThreads_NoTaskSwitch[MAX_CPUS]; // Disables task switches for each core (Pseudo-IF) // --- Scheduler Types --- @@ -132,6 +131,25 @@ void Threads_Init(void) Proc_Start(); } +void Threads_Delete(tThread *Thread) +{ + // Set to dead + Thread->Status = THREAD_STAT_BURIED; + + // Free name + if( IsHeap(Thread->ThreadName) ) + free(Thread->ThreadName); + + // Remove from global list + // TODO: Lock this too + if( Thread == gAllThreads ) + gAllThreads = Thread->GlobalNext; + else + Thread->GlobalPrev->GlobalNext = Thread->GlobalNext; + + free(Thread); +} + /** * \fn void Threads_SetName(const char *NewName) * \brief Sets the current thread's name @@ -425,7 +443,7 @@ tTID Threads_WaitTID(int TID, int *Status) // TODO: Child return value? if(Status) *Status = t->RetStatus; // add to delete queue - Threads_AddToDelete( t ); + Threads_Delete( t ); break; default: if(Status) *Status = -1; @@ -460,23 +478,6 @@ tThread *Threads_GetThread(Uint TID) return NULL; } -/** - * \brief Adds a thread to the delete queue - * \param Thread Thread to delete - */ -void Threads_AddToDelete(tThread *Thread) -{ - // Add to delete queue - // TODO: Is locking needed? - if(gDeleteThreads) { - Thread->Next = gDeleteThreads; - gDeleteThreads = Thread; - } else { - Thread->Next = NULL; - gDeleteThreads = Thread; - } -} - /** * \brief Deletes an entry from a list * \param List Pointer to the list head @@ -537,17 +538,17 @@ void Threads_Kill(tThread *Thread, int Status) tMsg *msg; int isCurThread = Thread == Proc_GetCurThread(); - // TODO: Kill all children + // TODO: Disown all children? #if 1 { tThread *child; - // TODO: I should keep a .Parent pointer, and a .Children list + // TODO: I should keep a .Children list for(child = gAllThreads; child; child = child->GlobalNext) { if(child->Parent == Thread) - Threads_Kill(child, -1); + child->Parent = &gThreadZero; } } #endif @@ -629,19 +630,13 @@ void Threads_Kill(tThread *Thread, int Status) Thread->RetStatus = Status; SHORTREL( &Thread->IsLocked ); + // Clear out process state + Proc_ClearThread(Thread); - // Don't Zombie if we are being killed because our parent is - if(Status == -1) - { - Thread->Status = THREAD_STAT_DEAD; - Threads_AddToDelete( Thread ); - SHORTREL( &glThreadListLock ); - } else { - Thread->Status = THREAD_STAT_ZOMBIE; - SHORTREL( &glThreadListLock ); - // Wake parent - Threads_Wake( Thread->Parent ); - } + Thread->Status = THREAD_STAT_ZOMBIE; + SHORTREL( &glThreadListLock ); + // TODO: Send something like SIGCHLD + Threads_Wake( Thread->Parent ); Log("Thread %i went *hurk* (%i)", Thread->TID, Status); @@ -1125,31 +1120,6 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) // Lock thread list SHORTLOCK( &glThreadListLock ); - // Clear Delete Queue - // - I should probably put this in a worker thread to avoid calling free() in the scheduler - // DEFINITELY - free() can deadlock in this case - // I'll do it when it becomes an issue - while(gDeleteThreads) - { - thread = gDeleteThreads->Next; - // Only free if structure is unused - if( !IS_LOCKED(&gDeleteThreads->IsLocked) ) - { - // Set to dead - gDeleteThreads->Status = THREAD_STAT_BURIED; - // Free name - if( IsHeap(gDeleteThreads->ThreadName) ) - free(gDeleteThreads->ThreadName); - // Remove from global list - if( gDeleteThreads == gAllThreads ) - gAllThreads = gDeleteThreads->GlobalNext; - else - gDeleteThreads->GlobalPrev->GlobalNext = gDeleteThreads->GlobalNext; - free( gDeleteThreads ); - } - gDeleteThreads = thread; - } - // Make sure the current (well, old) thread is marked as de-scheduled if(Last) Last->CurCPU = -1;