Kernel/threads - Cleaning out delete queue
authorJohn Hodge <[email protected]>
Fri, 11 Nov 2011 10:20:39 +0000 (18:20 +0800)
committerJohn Hodge <[email protected]>
Fri, 11 Nov 2011 10:20:39 +0000 (18:20 +0800)
- No (well, for now) chance of deadlock in scheduler
- Also added a way for thread resources to be cleared properly

Kernel/arch/armv7/proc.c
Kernel/arch/x86/proc.c
Kernel/arch/x86_64/proc.c
Kernel/include/threads_int.h
Kernel/semaphore.c
Kernel/threads.c

index 0b4627a..54951e1 100644 (file)
@@ -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;
index cdb51b6..5ec3676 100644 (file)
@@ -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;
        }
 
index e6ada78..75778c2 100644 (file)
@@ -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
  */
index 64b2986..4cc11ec 100644 (file)
@@ -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);
index b73ce02..d4583e7 100644 (file)
@@ -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;
index d1f3a75..6933dd6 100644 (file)
@@ -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;
 

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