Kernel - Converted most blocking states to use Threads_int_Sleep
[tpg/acess2.git] / KernelLand / Kernel / threads.c
index a86eba0..a1d3cdb 100644 (file)
@@ -31,6 +31,7 @@
 #define MIN_PRIORITY           10
 
 // === IMPORTS ===
+extern void    User_Signal_Kill(int SigNum);
 
 // === TYPE ===
 typedef struct
@@ -58,6 +59,9 @@ void  Threads_int_AddToList(tThreadList *List, tThread *Thread);
 void   Threads_Exit(int TID, int Status);
 void   Threads_Kill(tThread *Thread, int Status);
 void   Threads_Yield(void);
+#endif
+ int   Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock);
+#if 0
 void   Threads_Sleep(void);
  int   Threads_Wake(tThread *Thread);
 void   Threads_AddActive(tThread *Thread);
@@ -66,6 +70,14 @@ tThread      *Threads_RemActive(void);
 void   Threads_ToggleTrace(int TID);
 void   Threads_Fault(int Num);
 void   Threads_SegFault(tVAddr Addr);
+void   Threads_PostSignalTo(tThread *Thread, int SignalNum);
+#if 0
+void   Threads_PostSignal(int SignalNum);
+void   Threads_SignalGroup(tPGID PGID, int SignalNum);
+#endif
+ int   Threads_GetPendingSignal(void);
+void   Threads_SetSignalHandler(int SignalNum, void *Handler);
+void   *Threads_GetSignalHandler(int SignalNum);
 #if 0
  int   Threads_GetPID(void);
  int   Threads_GetTID(void);
@@ -80,7 +92,7 @@ void  Threads_DumpActive(void);
 
 // === GLOBALS ===
 // -- Core Thread --
-struct sProcess        gProcessZero = {
+tProcess       gProcessZero = {
        };
 // Only used for the core kernel
 tThread        gThreadZero = {
@@ -91,6 +103,7 @@ tThread      gThreadZero = {
        .Priority       = DEFAULT_PRIORITY      // Number of tickets
        };
 // -- Processes --
+tProcess       *gAllProcesses = &gProcessZero;
 // --- Locks ---
 tShortSpinlock glThreadListLock;       ///\note NEVER use a heap function while locked
 // --- Current State ---
@@ -166,6 +179,16 @@ void Threads_Delete(tThread *Thread)
        if( Thread->Process->nThreads == 0 )
        {
                tProcess        *proc = Thread->Process;
+
+               // Remove from global process list
+               // TODO: RWLock
+               if(proc->Prev)
+                       proc->Prev->Next = proc->Next;
+               else
+                       gAllProcesses = proc->Next;
+               if(proc->Next)
+                       proc->Next->Prev = proc->Prev;
+
                // VFS Cleanup
                VFS_CloseAllUserHandles();
                // Architecture cleanup
@@ -212,7 +235,7 @@ int Threads_SetName(const char *NewName)
        if( IsHeap(oldname) )   free( oldname );        
        cur->ThreadName = strdup(NewName);
 
-//     Log_Debug("Threads", "Thread renamed to '%s'", NewName);        
+       Log_Debug("Threads", "Thread renamed to '%s'", NewName);        
 
        return 0;
 }
@@ -334,17 +357,17 @@ tThread *Threads_CloneTCB(Uint Flags)
                newproc->UID = oldproc->UID;
                newproc->GID = oldproc->GID;
                newproc->MaxFD = oldproc->MaxFD;
-               if( oldproc->CurrentWorkingDir )
-                       newproc->CurrentWorkingDir = strdup( oldproc->CurrentWorkingDir );
-               else
-                       newproc->CurrentWorkingDir = NULL;
-               if( oldproc->RootDir )
-                       newproc->RootDir = strdup( oldproc->RootDir );
-               else
-                       newproc->RootDir = NULL;
+               newproc->CurrentWorkingDir = oldproc->CurrentWorkingDir ? strdup( oldproc->CurrentWorkingDir ) : NULL;
+               newproc->RootDir = oldproc->RootDir ? strdup( oldproc->RootDir ) : NULL;
                newproc->nThreads = 1;
                // Reference all handles in the VFS
                VFS_ReferenceUserHandles();
+               
+               // Add to global list
+               newproc->Prev = NULL;
+               // TODO: RWLock
+               newproc->Next = gAllProcesses;
+               gAllProcesses = newproc;
 
                newproc->FirstThread = new;
                new->ProcessNext = NULL;
@@ -712,6 +735,59 @@ void Threads_Yield(void)
        Proc_Reschedule();
 }
 
+/**
+ * \breif Wait for the thread status to not be a specified value
+ */
+void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
+{
+       tThread *us = Proc_GetCurThread();
+       ASSERT(Status != THREAD_STAT_ACTIVE);
+       ASSERT(Status != THREAD_STAT_DEAD);
+       while( us->Status == Status )
+       {
+               Proc_Reschedule();
+               if( us->Status == Status )
+                       Debug("Thread %p(%i %s) rescheduled while in %s state for %p",
+                               us, us->TID, us->ThreadName,
+                               casTHREAD_STAT[Status],
+                               __builtin_return_address(0));
+       }
+}
+
+int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
+{
+       SHORTLOCK( &glThreadListLock );
+       tThread *us = Threads_RemActive();
+       us->Next = NULL;
+       // - Mark as sleeping
+       us->Status = Status;
+       us->WaitPointer = Ptr;
+       us->RetStatus = Num;    // Use RetStatus as a temp variable
+               
+       // - Add to waiting
+       if( ListTail ) {
+               if(*ListTail) {
+                       (*ListTail)->Next = us;
+               }
+               else {
+                       *ListHead = us;
+               }
+               *ListTail = us;
+       }
+       else {
+               *ListHead = us;
+       }
+       
+       //if( Proc_ThreadSync(us) )
+       //      return ;
+       SHORTREL( &glThreadListLock );
+       if( Lock )
+               SHORTREL( Lock );
+       Threads_int_WaitForStatusEnd(Status);
+       us->WaitPointer = NULL;
+       return us->RetStatus;
+}
+
 /**
  * \fn void Threads_Sleep(void)
  * \brief Take the current process off the run queue
@@ -743,12 +819,7 @@ void Threads_Sleep(void)
        
        // Release Spinlock
        SHORTREL( &glThreadListLock );
-
-       while(cur->Status != THREAD_STAT_ACTIVE) {
-               Proc_Reschedule();
-               if( cur->Status != THREAD_STAT_ACTIVE )
-                       Log("%i - Huh? why am I up? zzzz...", cur->TID);
-       }
+       Threads_int_WaitForStatusEnd(THREAD_STAT_SLEEPING);
 }
 
 
@@ -993,6 +1064,105 @@ void Threads_SegFault(tVAddr Addr)
        //Threads_Exit( 0, -1 );
 }
 
+
+void Threads_PostSignalTo(tThread *Thread, int SignalNum)
+{
+       ASSERT(Thread);
+       Log_Debug("Threads", "Signalling %i(%s) with %i", Thread->TID, Thread->ThreadName, SignalNum);
+       Thread->PendingSignal = SignalNum;
+       Threads_PostEvent(Thread, THREAD_EVENT_SIGNAL);
+}
+void Threads_PostSignal(int SignalNum)
+{
+       Threads_PostSignalTo( Proc_GetCurThread(), SignalNum );
+}
+
+void Threads_SignalGroup(tPGID PGID, int Signal)
+{
+       for( tProcess *proc = gAllProcesses; proc; proc = proc->Next )
+       {
+               if(proc->PGID == PGID)
+               {
+                       Threads_PostSignalTo(proc->FirstThread, Signal);
+               }
+       }
+}
+
+/**
+ */
+int Threads_GetPendingSignal(void)
+{
+       tThread *cur = Proc_GetCurThread();
+       
+       // Atomic AND with 0 fetches and clears in one operation
+       int ret = __sync_fetch_and_and( &cur->PendingSignal, 0 );
+       if( ret )
+       {
+               Log_Debug("Threads", "Thread %i(%s) has signal %i pending",
+                       cur->TID, cur->ThreadName, ret);
+       }
+       return ret;
+}
+
+/*
+ * \brief Update the current thread's signal handler
+ */
+void Threads_SetSignalHandler(int SignalNum, void *Handler)
+{
+       if( SignalNum <= 0 || SignalNum >= NSIGNALS )
+               return ;
+       if( !MM_IsUser(Handler) )
+               return ;
+       Proc_GetCurThread()->Process->SignalHandlers[SignalNum] = Handler;
+}
+
+/**
+ * \brief Gets the registered (or default, if none set) handler for a signal.
+ * \return Handler function pointer, OR NULL if no signal to be ignored
+ */
+void *Threads_GetSignalHandler(int SignalNum)
+{
+       // TODO: Core dump
+       void *User_Signal_Core = User_Signal_Kill;
+       
+       if( SignalNum <= 0 || SignalNum >= NSIGNALS )
+               return NULL;
+       void *ret = Proc_GetCurThread()->Process->SignalHandlers[SignalNum];
+       if( !ret || (SignalNum == SIGKILL || SignalNum == SIGSTOP) )
+       {
+               // Defaults
+               switch(SignalNum)
+               {
+               case SIGHUP:
+               case SIGINT:
+                       ret = User_Signal_Kill;
+                       break;
+               case SIGQUIT:
+               case SIGILL:
+               case SIGABRT:
+               case SIGFPE:
+                       ret = User_Signal_Core;
+                       break;
+               case SIGKILL:
+                       ret = User_Signal_Kill;
+                       break;
+               case SIGSEGV:
+                       ret = User_Signal_Core;
+                       break;
+               case SIGPIPE:
+               case SIGALRM:
+               case SIGTERM:
+                       ret = User_Signal_Kill;
+                       break;
+               default:
+                       ret = NULL;
+                       break;
+               }
+       }
+       Log_Debug("Threads", "Handler %p for signal %i", ret, SignalNum);
+       return ret;
+}
+
 // --- Process Structure Access Functions ---
 tPGID Threads_GetPGID(void)
 {
@@ -1062,9 +1232,20 @@ char **Threads_GetCWD(void)
 
 void Threads_int_DumpThread(tThread *thread)
 {
+       if( !thread ) {
+               Log(" %p NULL", thread);
+               return ;
+       }
+       if( !CheckMem(thread, sizeof(tThread)) ) {
+               Log(" %p INVAL", thread);
+               return ;
+       }
+       tPID    pid = (thread->Process ? thread->Process->PID : -1);
+       const char      *statstr = (thread->Status < sizeof(casTHREAD_STAT)/sizeof(casTHREAD_STAT[0])
+               ? casTHREAD_STAT[thread->Status] : "");
        Log(" %p %i (%i) - %s (CPU %i) - %i (%s)",
-               thread, thread->TID, thread->Process->PID, thread->ThreadName, thread->CurCPU,
-               thread->Status, casTHREAD_STAT[thread->Status]
+               thread, thread->TID, pid, thread->ThreadName, thread->CurCPU,
+               thread->Status, statstr
                );
        switch(thread->Status)
        {
@@ -1078,6 +1259,9 @@ void Threads_int_DumpThread(tThread *thread)
                        ((tSemaphore*)thread->WaitPointer)->Name
                        );
                break;
+       case THREAD_STAT_EVENTSLEEP:
+               Log("  Event Mask: %x", thread->RetStatus);
+               break;
        case THREAD_STAT_ZOMBIE:
                Log("  Return Status: %i", thread->RetStatus);
                break;
@@ -1129,13 +1313,11 @@ void Threads_DumpActive(void)
  */
 void Threads_Dump(void)
 {
-       tThread *thread;
-       
        Log("--- Thread Dump ---");
        Threads_DumpActive();
        
        Log("All Threads:");
-       for(thread=gAllThreads;thread;thread=thread->GlobalNext)
+       for(tThread *thread = gAllThreads; thread; thread = thread->GlobalNext)
        {
                Threads_int_DumpThread(thread);
        }

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