X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fthreads.c;h=9aefeabfe81b826ecac1fb53f8ba15a6a95cc1e6;hb=bdab8e5cebaf249d291d19523d0358f8c1c98008;hp=8762a7c49fc9d9f67f9a1d5c18c6870258f4815e;hpb=b3f1b61b3c93caecfbfafeda11adac4080faf445;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/threads.c b/KernelLand/Kernel/threads.c index 8762a7c4..9aefeabf 100644 --- a/KernelLand/Kernel/threads.c +++ b/KernelLand/Kernel/threads.c @@ -4,6 +4,7 @@ * threads.c * - Common Thread Control */ +#define DEBUG 0 #include #include #include @@ -198,7 +199,7 @@ void Threads_Delete(tThread *Thread) proc->Next->Prev = proc->Prev; // VFS Cleanup - VFS_CloseAllUserHandles(); + VFS_CloseAllUserHandles( proc ); // Architecture cleanup Proc_ClearProcess( proc ); // VFS Configuration strings @@ -329,11 +330,10 @@ void Threads_SetPriority(tThread *Thread, int Pri) */ tThread *Threads_CloneTCB(Uint Flags) { - tThread *cur, *new; - cur = Proc_GetCurThread(); + tThread *cur = Proc_GetCurThread(); // Allocate and duplicate - new = malloc(sizeof(tThread)); + tThread *new = malloc(sizeof(tThread)); if(new == NULL) { errno = -ENOMEM; return NULL; } memcpy(new, cur, sizeof(tThread)); @@ -480,22 +480,36 @@ tTID Threads_WaitTID(int TID, int *Status) tTID ret = -1; if( ev & THREAD_EVENT_DEADCHILD ) { + tThread * const us = Proc_GetCurThread(); // A child died, get the TID - tThread *us = Proc_GetCurThread(); ASSERT(us->LastDeadChild); - ret = us->LastDeadChild->TID; + tThread *dead_thread = us->LastDeadChild; + us->LastDeadChild = dead_thread->Next; + if( us->LastDeadChild ) + Threads_PostEvent( us, THREAD_EVENT_DEADCHILD ); + else + Threads_ClearEvent( THREAD_EVENT_DEADCHILD ); + Mutex_Release(&us->DeadChildLock); + + ret = dead_thread->TID; // - Mark as dead (as opposed to undead) - ASSERT(us->LastDeadChild->Status == THREAD_STAT_ZOMBIE); - us->LastDeadChild->Status = THREAD_STAT_DEAD; + if( dead_thread->Status != THREAD_STAT_ZOMBIE ) { + Log_Error("Thread", "Thread %p(%i %s) is not ZOMBIE, instead %s", + dead_thread, dead_thread->TID, dead_thread->ThreadName, + (dead_thread->Status < ciTHREAD_STAT_COUNT ? casTHREAD_STAT[dead_thread->Status] : "?") + ); + ASSERTC(dead_thread->Status, ==, THREAD_STAT_ZOMBIE); + } + dead_thread->Status = THREAD_STAT_DEAD; // - Set return status if(Status) - *Status = us->LastDeadChild->RetStatus; - us->LastDeadChild = NULL; - Mutex_Release(&us->DeadChildLock); + *Status = dead_thread->RetStatus; + + Threads_Delete( dead_thread ); } else { - Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child"); + Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Woken with no child"); } return ret; } @@ -619,17 +633,13 @@ void Threads_Exit(int TID, int Status) */ void Threads_Kill(tThread *Thread, int Status) { - tMsg *msg; int isCurThread = Thread == Proc_GetCurThread(); // TODO: Disown all children? #if 1 { - tThread *child; // TODO: I should keep a .Children list - for(child = gAllThreads; - child; - child = child->GlobalNext) + for(tThread* child = gAllThreads; child; child = child->GlobalNext) { if(child->Parent == Thread) child->Parent = &gThreadZero; @@ -645,7 +655,7 @@ void Threads_Kill(tThread *Thread, int Status) // Clear Message Queue while( Thread->Messages ) { - msg = Thread->Messages->Next; + tMsg *msg = Thread->Messages->Next; free( Thread->Messages ); Thread->Messages = msg; } @@ -693,8 +703,8 @@ void Threads_Kill(tThread *Thread, int Status) if( !Threads_int_DelFromQueue( &gSleepingThreads, Thread ) ) { Log_Warning("Threads", - "Threads_Kill - Thread %p(%i,%s) marked as sleeping, but not on list", - Thread, Thread->TID, Thread->ThreadName + "Threads_Kill - Thread "PRIthread_fmt" marked as sleeping, but not on list", + PRIthread_args(Thread) ); } break; @@ -716,16 +726,19 @@ void Threads_Kill(tThread *Thread, int Status) // Save exit status Thread->RetStatus = Status; - SHORTREL( &Thread->IsLocked ); - Thread->Status = THREAD_STAT_ZOMBIE; SHORTREL( &glThreadListLock ); // TODO: It's possible that we could be timer-preempted here, should disable that... somehow Mutex_Acquire( &Thread->Parent->DeadChildLock ); // released by parent + Thread->Next = Thread->Parent->LastDeadChild; Thread->Parent->LastDeadChild = Thread; Threads_PostEvent( Thread->Parent, THREAD_EVENT_DEADCHILD ); - Log("Thread %i went *hurk* (%i)", Thread->TID, Status); + // Process cleanup happens on reaping + Log("Thread "PRIthread_fmt" went *hurk* (%i) (isCurThread=%B)", PRIthread_args(Thread), Status, isCurThread); + //Log("Thread status = %i %s", Thread->Status, casTHREAD_STAT[Thread->Status]); + + SHORTREL( &Thread->IsLocked ); // And, reschedule if(isCurThread) @@ -750,6 +763,7 @@ void Threads_Yield(void) void Threads_int_WaitForStatusEnd(enum eThreadStatus Status) { tThread *us = Proc_GetCurThread(); + LOG("us = %p(%i %s), status=%i", us, us->TID, us->ThreadName, Status); ASSERT(Status != THREAD_STAT_ACTIVE); ASSERT(Status != THREAD_STAT_DEAD); while( us->Status == Status ) @@ -1246,17 +1260,20 @@ int *Threads_GetErrno(void) } // --- Configuration --- -int *Threads_GetMaxFD(void) +int *Threads_GetMaxFD(tProcess *Process) { - return &Proc_GetCurThread()->Process->MaxFD; + if(!Process) Process = Proc_GetCurThread()->Process; + return &Process->MaxFD; } -char **Threads_GetChroot(void) +char **Threads_GetChroot(tProcess *Process) { - return &Proc_GetCurThread()->Process->RootDir; + if(!Process) Process = Proc_GetCurThread()->Process; + return &Process->RootDir; } -char **Threads_GetCWD(void) +char **Threads_GetCWD(tProcess *Process) { - return &Proc_GetCurThread()->Process->CurrentWorkingDir; + if(!Process) Process = Proc_GetCurThread()->Process; + return &Process->CurrentWorkingDir; } // --- @@ -1459,6 +1476,7 @@ tThread *Threads_int_GetRunnable(void) // Single-list round-robin // ----------------------------------- tThread *thread = gActiveThreads.Head; + LOG("thread = %p", thread); if( thread ) { gActiveThreads.Head = thread->Next; @@ -1480,23 +1498,20 @@ tThread *Threads_int_GetRunnable(void) */ tThread *Threads_GetNextToRun(int CPU, tThread *Last) { - // If this CPU has the lock, we must let it complete - if( CPU_HAS_LOCK( &glThreadListLock ) ) - return Last; + ASSERT( CPU_HAS_LOCK(&glThreadListLock) ); // Don't change threads if the current CPU has switches disabled - if( gaThreads_NoTaskSwitch[CPU] ) + if( gaThreads_NoTaskSwitch[CPU] ) { + LOG("- Denied"); return Last; - - // Lock thread list - SHORTLOCK( &glThreadListLock ); + } // Make sure the current (well, old) thread is marked as de-scheduled if(Last) Last->CurCPU = -1; // No active threads, just take a nap if(giNumActiveThreads == 0) { - SHORTREL( &glThreadListLock ); + LOG("- No active"); #if DEBUG_TRACE_TICKETS Log("No active threads"); #endif @@ -1539,7 +1554,7 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) // Call actual scheduler tThread *thread = Threads_int_GetRunnable(); - + // Anything to do? if( thread ) { @@ -1565,8 +1580,6 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) Warning("No runnable thread for CPU%i", CPU); } - SHORTREL( &glThreadListLock ); - return thread; }