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);
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;
// Check for errors
if( newThread->MemState.CR3 == 0 ) {
Log_Error("Proc", "Proc_Clone: MM_Clone failed");
- Threads_AddToDelete(newThread);
+ Threads_Delete(newThread);
return -1;
}
// === PROTOTYPES ===
void Threads_Init(void);
#if 0
+void Threads_Delete(tThread *Thread);
int Threads_SetName(const char *NewName);
#endif
char *Threads_GetName(int ID);
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);
// --- 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 ---
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
// 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;
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
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
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);
// 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;