Kernel - Added (possibly buggy) support for WaitTID(TID>0)
authorJohn Hodge (sonata) <[email protected]>
Sat, 19 Jan 2013 14:09:45 +0000 (22:09 +0800)
committerJohn Hodge (sonata) <[email protected]>
Sat, 19 Jan 2013 14:09:45 +0000 (22:09 +0800)
KernelLand/Kernel/include/events.h
KernelLand/Kernel/include/threads_int.h
KernelLand/Kernel/threads.c

index dc9d654..17143e8 100644 (file)
@@ -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
index 578fdcf..4845264 100644 (file)
@@ -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;
index 92a7a57..a8697d6 100644 (file)
@@ -11,6 +11,7 @@
 #include <hal_proc.h>
 #include <semaphore.h>
 #include <vfs_threads.h>       // VFS Handle maintainence
+#include <events.h>
 
 // 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);
        

UCC git Repository :: git.ucc.asn.au