From 9d64454b70e47aa5c29077e4dd59d28e14ca3bf2 Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Sat, 19 Jan 2013 22:09:45 +0800 Subject: [PATCH] Kernel - Added (possibly buggy) support for WaitTID(TID>0) --- KernelLand/Kernel/include/events.h | 2 + KernelLand/Kernel/include/threads_int.h | 5 +- KernelLand/Kernel/threads.c | 64 +++++++++++++------------ 3 files changed, 40 insertions(+), 31 deletions(-) diff --git a/KernelLand/Kernel/include/events.h b/KernelLand/Kernel/include/events.h index dc9d6543..17143e86 100644 --- a/KernelLand/Kernel/include/events.h +++ b/KernelLand/Kernel/include/events.h @@ -25,6 +25,8 @@ //! General purpose event for short waits //! e.g. waiting for an IRQ in a Read() call #define THREAD_EVENT_SHORTWAIT 0x00000010 +//! Fired when a child process quits +#define THREAD_EVENT_DEADCHILD 0x00000020 #define THREAD_EVENT_USER1 0x10000000 #define THREAD_EVENT_USER2 0x20000000 diff --git a/KernelLand/Kernel/include/threads_int.h b/KernelLand/Kernel/include/threads_int.h index 578fdcf1..48452649 100644 --- a/KernelLand/Kernel/include/threads_int.h +++ b/KernelLand/Kernel/include/threads_int.h @@ -71,7 +71,10 @@ struct sThread struct sProcess *Process; //!< Thread Group / Process struct sThread *Parent; //!< Parent Thread char *ThreadName; //!< Name of thread - + + struct sThread *LastDeadChild; //!< Last child to die (will have the \a DeadChildren lock) + tMutex DeadChildLock; //!< Lock to prevent clobbering of \a LastDeadChild, acquired by child, released by parent + // --- arch/proc.c's responsibility //! Kernel Stack Base tVAddr KernelStack; diff --git a/KernelLand/Kernel/threads.c b/KernelLand/Kernel/threads.c index 92a7a576..a8697d63 100644 --- a/KernelLand/Kernel/threads.c +++ b/KernelLand/Kernel/threads.c @@ -11,6 +11,7 @@ #include #include #include // VFS Handle maintainence +#include // Configuration #define DEBUG_TRACE_TICKETS 0 // Trace ticket counts @@ -442,9 +443,30 @@ tThread *Threads_CloneThreadZero(void) tTID Threads_WaitTID(int TID, int *Status) { // Any Child - if(TID == -1) { - Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child"); - return -1; + if(TID == -1) + { + Uint32 ev = Threads_WaitEvents(THREAD_EVENT_DEADCHILD); + tTID ret = -1; + if( ev & THREAD_EVENT_DEADCHILD ) + { + // A child died, get the TID + tThread *us = Proc_GetCurThread(); + ASSERT(us->LastDeadChild); + ret = us->LastDeadChild->TID; + // - Mark as dead (as opposed to undead) + ASSERT(us->LastDeadChild->Status == THREAD_STAT_ZOMBIE); + us->LastDeadChild->Status = THREAD_STAT_DEAD; + // - Set return status + if(Status) + *Status = us->LastDeadChild->RetStatus; + us->LastDeadChild = NULL; + Mutex_Release(&us->DeadChildLock); + } + else + { + Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child"); + } + return ret; } // Any peer/child thread @@ -460,33 +482,13 @@ tTID Threads_WaitTID(int TID, int *Status) } // Specific Thread - if(TID > 0) { - tThread *t = Threads_GetThread(TID); + if(TID > 0) + { tTID ret; - - // Wait for the thread to die! - // TODO: Handle child also being suspended if wanted - while(t->Status != THREAD_STAT_ZOMBIE) { - Threads_Sleep(); - Log_Debug("Threads", "%i waiting for %i, t->Status = %i", - Threads_GetTID(), t->TID, t->Status); - } - - // Set return status - ret = t->TID; - switch(t->Status) + while( (ret = Threads_WaitTID(-1, Status)) != TID ) { - case THREAD_STAT_ZOMBIE: - // Kill the thread - t->Status = THREAD_STAT_DEAD; - // TODO: Child return value? - if(Status) *Status = t->RetStatus; - // add to delete queue - Threads_Delete( t ); - break; - default: - if(Status) *Status = -1; - break; + if( ret == -1 ) + break; } return ret; } @@ -685,8 +687,10 @@ void Threads_Kill(tThread *Thread, int Status) Thread->Status = THREAD_STAT_ZOMBIE; SHORTREL( &glThreadListLock ); - // TODO: Send something like SIGCHLD - Threads_Wake( Thread->Parent ); + // TODO: It's possible that we could be timer-preempted here, should disable that... somehow + Mutex_Acquire( &Thread->Parent->DeadChildLock ); // released by parent + Thread->Parent->LastDeadChild = Thread; + Threads_PostEvent( Thread->Parent, THREAD_EVENT_DEADCHILD ); Log("Thread %i went *hurk* (%i)", Thread->TID, Status); -- 2.20.1