X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fthreads.c;h=1781f69923440ef8a4e4f8f0ff2c84a170fef726;hb=986a763a1f3ee23b2fe3e809e2b5f023d9df6898;hp=67a2f637462e5b86252c40978b9cecee18cb21de;hpb=ae10b503726e8a125298f3588806a87d3772e6eb;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/threads.c b/KernelLand/Kernel/threads.c index 67a2f637..1781f699 100644 --- a/KernelLand/Kernel/threads.c +++ b/KernelLand/Kernel/threads.c @@ -31,6 +31,7 @@ #define MIN_PRIORITY 10 // === IMPORTS === +extern void User_Signal_Kill(int SigNum); // === TYPE === typedef struct @@ -48,7 +49,7 @@ void Threads_Delete(tThread *Thread); char *Threads_GetName(tTID ID); #if 0 void Threads_SetPriority(tThread *Thread, int Pri); -tThread *Threads_CloneTCB(Uint *Err, Uint Flags); +tThread *Threads_CloneTCB(Uint Flags); int Threads_WaitTID(int TID, int *status); tThread *Threads_GetThread(Uint TID); #endif @@ -58,6 +59,7 @@ 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); + int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock); void Threads_Sleep(void); int Threads_Wake(tThread *Thread); void Threads_AddActive(tThread *Thread); @@ -66,7 +68,11 @@ 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); @@ -84,7 +90,7 @@ void Threads_DumpActive(void); // === GLOBALS === // -- Core Thread -- -struct sProcess gProcessZero = { +tProcess gProcessZero = { }; // Only used for the core kernel tThread gThreadZero = { @@ -95,6 +101,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 --- @@ -170,6 +177,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 @@ -338,17 +355,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; @@ -728,10 +745,47 @@ void Threads_int_WaitForStatusEnd(enum eThreadStatus Status) { Proc_Reschedule(); if( us->Status == Status ) - Debug("Thread %p(%i %s) rescheduled while in %s state", casTHREAD_STAT[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 @@ -1009,11 +1063,27 @@ void Threads_SegFault(tVAddr Addr) } +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) { - tThread *cur = Proc_GetCurThread(); - cur->PendingSignal = SignalNum; - Threads_PostEvent(cur, THREAD_EVENT_SIGNAL); + 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); + } + } } /** @@ -1023,7 +1093,13 @@ int Threads_GetPendingSignal(void) tThread *cur = Proc_GetCurThread(); // Atomic AND with 0 fetches and clears in one operation - return __sync_fetch_and_and( &cur->PendingSignal, 0 ); + 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; } /* @@ -1039,28 +1115,49 @@ void Threads_SetSignalHandler(int SignalNum, void *Handler) } /** - * \return 0 Ignore + * \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 ) + 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_Kill; + 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; } @@ -1161,7 +1258,7 @@ void Threads_int_DumpThread(tThread *thread) ); break; case THREAD_STAT_EVENTSLEEP: - // TODO: Event mask + Log(" Event Mask: %x", thread->RetStatus); break; case THREAD_STAT_ZOMBIE: Log(" Return Status: %i", thread->RetStatus);