X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fthreads.c;h=54438c32a79db339f7df6db0f9b19e08f24f4752;hb=eb80b37c619769496f3fca58d54c4a4b8d8fac4a;hp=fb14f4d7f07117cf226d189e7725a7301335cfdc;hpb=f119d0e5b18b7286d04fc536a94e0f96e3c51714;p=tpg%2Facess2.git diff --git a/Kernel/threads.c b/Kernel/threads.c index fb14f4d7..54438c32 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -13,21 +13,25 @@ // === IMPORTS === extern void ArchThreads_Init(); +extern void Proc_Start(); extern tThread *Proc_GetCurThread(); extern int Proc_Clone(Uint *Err, Uint Flags); // === PROTOTYPES === void Threads_Init(); void Threads_SetName(char *NewName); +char *Threads_GetName(int ID); void Threads_SetTickets(int Num); int Threads_WaitTID(int TID, int *status); tThread *Threads_GetThread(Uint TID); +void Threads_AddToDelete(tThread *Thread); tThread *Threads_int_GetPrev(tThread **List, tThread *Thread); void Threads_Exit(int TID, int Status); void Threads_Kill(tThread *Thread, int Status); void Threads_Yield(); void Threads_Sleep(); void Threads_Wake(tThread *Thread); +void Threads_AddActive(tThread *Thread); int Threads_GetPID(); int Threads_GetTID(); int Threads_GetUID(); @@ -91,9 +95,14 @@ void Threads_Init() cur->ThreadName = "Idle Thread"; Threads_SetTickets(0); // Never called randomly cur->Quantum = 1; // 1 slice quantum - for(;;) __asm__ __volatile__ ("hlt"); // Just yeilds + HALT(); + for(;;) { + HALT(); // Just yeilds + } } #endif + + Proc_Start(); } /** @@ -109,6 +118,18 @@ void Threads_SetName(char *NewName) strcpy(cur->ThreadName, NewName); } +/** + * \fn char *Threads_GetName(int ID) + * \brief Gets a thread's name + */ +char *Threads_GetName(int ID) +{ + if(ID == -1) { + return Proc_GetCurThread()->ThreadName; + } + return NULL; +} + /** * \fn void Threads_SetTickets(int Num) * \brief Sets the 'priority' of a task @@ -132,7 +153,7 @@ void Threads_SetTickets(int Num) * \brief Wait for a task to change state */ int Threads_WaitTID(int TID, int *status) -{ +{ // Any Child if(TID == -1) { @@ -161,10 +182,11 @@ int Threads_WaitTID(int TID, int *status) { case THREAD_STAT_ZOMBIE: t->Status = THREAD_STAT_DEAD; - *status = 0; + if(status) *status = 0; + Threads_AddToDelete( t ); break; default: - *status = -1; + if(status) *status = -1; break; } return ret; @@ -202,6 +224,22 @@ tThread *Threads_GetThread(Uint TID) return NULL; } +/** + * \fn void Threads_AddToDelete(tThread *Thread) + * \brief Adds a thread to the delete queue + */ +void Threads_AddToDelete(tThread *Thread) +{ + // Add to delete queue + if(gDeleteThreads) { + Thread->Next = gDeleteThreads; + gDeleteThreads = Thread; + } else { + Thread->Next = NULL; + gDeleteThreads = Thread; + } +} + /** * \fn tThread *Threads_int_GetPrev(tThread *List, tThread *Thread) * \brief Gets the previous entry in a thead linked list @@ -231,7 +269,10 @@ tThread *Threads_int_GetPrev(tThread **List, tThread *Thread) */ void Threads_Exit(int TID, int Status) { - Threads_Kill( Proc_GetCurThread(), (Uint)Status & 0xFF ); + if( TID == 0 ) + Threads_Kill( Proc_GetCurThread(), (Uint)Status & 0xFF ); + else + Threads_Kill( Threads_GetThread(TID), (Uint)Status & 0xFF ); } /** @@ -252,7 +293,7 @@ void Threads_Kill(tThread *Thread, int Status) child; child = child->Next) { - if(child->PTID == gCurrentThread->TID) + if(child->PTID == Thread->TID) Threads_Kill(child, -1); } } @@ -295,14 +336,7 @@ void Threads_Kill(tThread *Thread, int Status) if(Status == -1) { Thread->Status = THREAD_STAT_DEAD; - // Add to delete queue - if(gDeleteThreads) { - Thread->Next = gDeleteThreads; - gDeleteThreads = Thread; - } else { - Thread->Next = NULL; - gDeleteThreads = Thread; - } + Threads_AddToDelete( Thread ); } else { Thread->Status = THREAD_STAT_ZOMBIE; } @@ -319,7 +353,7 @@ void Threads_Kill(tThread *Thread, int Status) */ void Threads_Yield() { - Proc_GetCurThread()->Quantum = 0; + Proc_GetCurThread()->Remaining = 0; HALT(); } @@ -332,7 +366,7 @@ void Threads_Sleep() tThread *cur = Proc_GetCurThread(); tThread *thread; - //Log("Proc_Sleep: %i going to sleep", gCurrentThread->TID); + Log("Proc_Sleep: %i going to sleep", cur->TID); // Acquire Spinlock LOCK( &giThreadListLock ); @@ -405,6 +439,74 @@ void Threads_Wake(tThread *Thread) } } +/** + * \fn void Threads_AddActive(tThread *Thread) + * \brief Adds a thread to the active queue + */ +void Threads_AddActive(tThread *Thread) +{ + LOCK( &giThreadListLock ); + Thread->Next = gActiveThreads; + gActiveThreads = Thread; + giNumActiveThreads ++; + giTotalTickets += Thread->NumTickets; + //Log("Threads_AddActive: giNumActiveThreads = %i, giTotalTickets = %i", + // giNumActiveThreads, giTotalTickets); + RELEASE( &giThreadListLock ); +} + +#if 0 +/** + * \fn void Threads_SetSignalHandler(int Num, void *Handler) + * \brief Sets the signal handler for a signal + */ +void Threads_SetSignalHandler(int Num, void *Handler) +{ + if(Num < 0 || Num >= NSIG) return; + + gCurrentThread->SignalHandlers[Num] = Handler; +} + +/** + * \fn void Threads_SendSignal(int TID, int Num) + * \brief Send a signal to a thread + */ +void Threads_SendSignal(int TID, int Num) +{ + tThread *thread = Proc_GetThread(TID); + void *handler; + + if(!thread) return ; + + handler = thread->SignalHandlers[Num]; + + // Panic? + if(handler == SIG_ERR) { + Proc_Kill(TID); + return ; + } + // Dump Core? + if(handler == -2) { + Proc_Kill(TID); + return ; + } + // Ignore? + if(handler == -2) return; + + // Check the type and handle if the thread is already in a signal + if(thread->CurSignal != 0) { + if(Num < _SIGTYPE_FATAL) + Proc_Kill(TID); + } else { + while(thread->CurSignal != 0) + Proc_Yield(); + } + } + + //TODO: +} +#endif + // --- Process Structure Access Functions --- int Threads_GetPID() { @@ -446,3 +548,57 @@ void Threads_Dump() Log(" KStack 0x%x", thread->KernelStack); } } + +/** + * \fn tThread *Threads_GetNextToRun(int CPU) + * \brief Gets the next thread to run + */ +tThread *Threads_GetNextToRun(int CPU) +{ + tThread *thread; + int ticket; + int number; + + // Special case: 1 thread + if(giNumActiveThreads == 1) + { + return gActiveThreads; + } + + //Log(" Threads_GetNextToRun: giNumActiveThreads=%i,giTotalTickets=%i", + // giNumActiveThreads, giTotalTickets); + // Get the ticket number + ticket = number = rand() % giTotalTickets; + + //Log(" Threads_GetNextToRun: ticket = %i", ticket); + + // Find the next thread + for(thread=gActiveThreads;thread;thread=thread->Next) + { + if(thread->NumTickets > number) break; + number -= thread->NumTickets; + } + + // Error Check + if(thread == NULL) + { + number = 0; + for(thread=gActiveThreads;thread;thread=thread->Next) + number += thread->NumTickets; + Panic("Bookeeping Failed - giTotalTicketCount (%i) != true count (%i)", + giTotalTickets, number); + } + + return thread; +} + +/** + * \fn void Threads_SegFault(tVAddr Addr) + * \brief Called when a Segment Fault occurs + */ +void Threads_SegFault(tVAddr Addr) +{ + //Threads_SendSignal( Proc_GetCurThread()->TID, SIGSEGV ); + Log("Thread #%i committed a segfault at address %p\n", Proc_GetCurThread()->TID, Addr); + Threads_Exit( 0, 0 ); +}