X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fthreads.c;h=5d15c929c431324cbacffb06acd3ed8dbf29df2e;hb=270e5fe88b0666021a7a6393334db7feeb8245f8;hp=b76fe592f220901f9f749b102a538bfc205fb300;hpb=d5834686ad14b66420060192445f06bce85db389;p=tpg%2Facess2.git diff --git a/Kernel/threads.c b/Kernel/threads.c index b76fe592..5d15c929 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -35,10 +35,11 @@ extern void Proc_Start(void); extern tThread *Proc_GetCurThread(void); extern int Proc_Clone(Uint *Err, Uint Flags); extern void Proc_CallFaultHandler(tThread *Thread); +extern int GetCPUNum(void); // === PROTOTYPES === void Threads_Init(void); - int Threads_SetName(char *NewName); + int Threads_SetName(const char *NewName); char *Threads_GetName(int ID); void Threads_SetPriority(tThread *Thread, int Pri); tThread *Threads_CloneTCB(Uint *Err, Uint Flags); @@ -61,6 +62,7 @@ tGID Threads_GetGID(void); int Threads_SetGID(Uint *Errno, tUID ID); void Threads_Dump(void); void Threads_DumpActive(void); + void Mutex_Acquire(tMutex *Mutex); void Mutex_Release(tMutex *Mutex); int Mutex_IsLocked(tMutex *Mutex); @@ -123,12 +125,12 @@ void Threads_Init(void) } /** - * \fn void Threads_SetName(char *NewName) + * \fn void Threads_SetName(const char *NewName) * \brief Sets the current thread's name * \param NewName New name for the thread * \return Boolean Failure */ -int Threads_SetName(char *NewName) +int Threads_SetName(const char *NewName) { tThread *cur = Proc_GetCurThread(); char *oldname = cur->ThreadName; @@ -277,6 +279,7 @@ tThread *Threads_CloneTCB(Uint *Err, Uint Flags) SHORTLOCK( &glThreadListLock ); new->GlobalPrev = NULL; // Protect against bugs new->GlobalNext = gAllThreads; + gAllThreads->GlobalPrev = new; gAllThreads = new; SHORTREL( &glThreadListLock ); @@ -464,15 +467,15 @@ void Threads_Kill(tThread *Thread, int Status) tMsg *msg; // TODO: Kill all children - #if 0 + #if 1 { tThread *child; // TODO: I should keep a .Parent pointer, and a .Children list - for(child = gActiveThreads; + for(child = gAllThreads; child; - child = child->Next) + child = child->GlobalNext) { - if(child->PTID == Thread->TID) + if(child->Parent == Thread) Threads_Kill(child, -1); } } @@ -494,29 +497,52 @@ void Threads_Kill(tThread *Thread, int Status) // Lock thread list SHORTLOCK( &glThreadListLock ); - // Delete from active list - #if SCHEDULER_TYPE == SCHED_RR_PRI - if( !Threads_int_DelFromQueue( &gaActiveThreads[Thread->Priority], Thread ) ) - #else - if( !Threads_int_DelFromQueue( &gActiveThreads, Thread ) ) - #endif + switch(Thread->Status) { - Warning("Proc_Exit - Current thread is not on the active queue"); - SHORTREL( &glThreadListLock ); - SHORTREL( &Thread->IsLocked ); - return; - } - - // Ensure that we are not rescheduled - Thread->Remaining = 0; // Clear Remaining Quantum - Thread->Quantum = 0; // Clear Quantum to indicate dead thread + case THREAD_STAT_PREINIT: // Only on main list + break; - // Update bookkeeping - giNumActiveThreads --; - #if SCHEDULER_TYPE == SCHED_LOTTERY - if( Thread != Proc_GetCurThread() ) - giFreeTickets -= caiTICKET_COUNTS[ Thread->Priority ]; - #endif + // Currently active thread + case THREAD_STAT_ACTIVE: + #if SCHEDULER_TYPE == SCHED_RR_PRI + if( Threads_int_DelFromQueue( &gaActiveThreads[Thread->Priority], Thread ) ) + #else + if( Threads_int_DelFromQueue( &gActiveThreads, Thread ) ) + #endif + { + // Ensure that we are not rescheduled + Thread->Remaining = 0; // Clear Remaining Quantum + Thread->Quantum = 0; // Clear Quantum to indicate dead thread + + // Update bookkeeping + giNumActiveThreads --; + #if SCHEDULER_TYPE == SCHED_LOTTERY + if( Thread != Proc_GetCurThread() ) + giFreeTickets -= caiTICKET_COUNTS[ Thread->Priority ]; + #endif + } + else + { + Log_Warning("Threads", + "Threads_Kill - Thread %p(%i,%s) marked as active, but not on list", + Thread, Thread->TID, Thread->ThreadName + ); + } + break; + case THREAD_STAT_SLEEPING: + if( !Threads_int_DelFromQueue( &gSleepingThreads, Thread ) ) + { + Log_Warning("Threads", + "Threads_Kill - Thread %p(%i,%s) marked as sleeping, but not on list", + Thread, Thread->TID, Thread->ThreadName + ); + } + break; + default: + Log_Warning("Threads", "Threads_Kill - BUG Un-checked status (%i)", + Thread->Status); + break; + } // Save exit status Thread->RetStatus = Status; @@ -532,7 +558,7 @@ void Threads_Kill(tThread *Thread, int Status) Threads_Wake( Thread->Parent ); } - Log("Thread %i went *hurk* (%i)", Thread->TID, Thread->Status); + Log("Thread %i went *hurk* (%i)", Thread->TID, Status); // Release spinlocks SHORTREL( &glThreadListLock ); @@ -662,6 +688,12 @@ void Threads_AddActive(tThread *Thread) { SHORTLOCK( &glThreadListLock ); + if( Thread->Status == THREAD_STAT_ACTIVE ) { + tThread *cur = Proc_GetCurThread(); + Warning("WTF, CPU%i %p (%i %s) is adding %p (%i %s) when it is active", + GetCPUNum(), cur, cur->TID, cur->ThreadName, Thread, Thread->TID, Thread->ThreadName); + } + // Set state Thread->Status = THREAD_STAT_ACTIVE; Thread->CurCPU = -1; @@ -680,8 +712,8 @@ void Threads_AddActive(tThread *Thread) #if SCHEDULER_TYPE == SCHED_LOTTERY giFreeTickets += caiTICKET_COUNTS[ Thread->Priority ]; # if DEBUG_TRACE_TICKETS - Log("Threads_AddActive: %p %i (%s) added, new giFreeTickets = %i", - Thread, Thread->TID, Thread->ThreadName, giFreeTickets); + Log("Threads_AddActive: CPU%i %p %i (%s) added, new giFreeTickets = %i", + GetCPUNum(), Thread, Thread->TID, Thread->ThreadName, giFreeTickets); # endif #endif @@ -718,8 +750,8 @@ tThread *Threads_RemActive(void) // no need to decrement tickets, scheduler did it for us #if SCHEDULER_TYPE == SCHED_LOTTERY && DEBUG_TRACE_TICKETS - Log("Threads_RemActive: %p %i (%s) removed, giFreeTickets = %i", - ret, ret->TID, ret->ThreadName, giFreeTickets); + Log("Threads_RemActive: CPU%i %p %i (%s) removed, giFreeTickets = %i", + GetCPUNum(), ret, ret->TID, ret->ThreadName, giFreeTickets); #endif SHORTREL( &glThreadListLock ); @@ -836,8 +868,8 @@ void Threads_DumpActive(void) for(thread=gActiveThreads;thread;thread=thread->Next) #endif { - Log(" %i (%i) - %s (CPU %i)", - thread->TID, thread->TGID, thread->ThreadName, thread->CurCPU); + Log(" %p %i (%i) - %s (CPU %i)", + thread, thread->TID, thread->TGID, thread->ThreadName, thread->CurCPU); if(thread->Status != THREAD_STAT_ACTIVE) Log(" ERROR State (%i) != THREAD_STAT_ACTIVE (%i)", thread->Status, THREAD_STAT_ACTIVE); Log(" Priority %i, Quantum %i", thread->Priority, thread->Quantum); @@ -863,8 +895,8 @@ void Threads_Dump(void) Log("All Threads:"); for(thread=gAllThreads;thread;thread=thread->GlobalNext) { - Log(" %i (%i) - %s (CPU %i)", - thread->TID, thread->TGID, thread->ThreadName, thread->CurCPU); + Log(" %p %i (%i) - %s (CPU %i)", + thread, thread->TID, thread->TGID, thread->ThreadName, thread->CurCPU); Log(" State %i (%s)", thread->Status, casTHREAD_STAT[thread->Status]); switch(thread->Status) { @@ -907,7 +939,9 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) while(gDeleteThreads) { thread = gDeleteThreads->Next; - if( IS_LOCKED(&gDeleteThreads->IsLocked) ) { // Only free if structure is unused + // Only free if structure is unused + if( !IS_LOCKED(&gDeleteThreads->IsLocked) ) + { // Set to dead gDeleteThreads->Status = THREAD_STAT_BURIED; // Free name @@ -1167,6 +1201,12 @@ void Mutex_Acquire(tMutex *Mutex) Mutex->Owner = us; SHORTREL( &Mutex->Protector ); } + + #if 0 + extern tMutex glPhysAlloc; + if( Mutex != &glPhysAlloc ) + LogF("Mutex %p taken by %i %p\n", Mutex, us->TID, __builtin_return_address(0)); + #endif } /** @@ -1197,6 +1237,12 @@ void Mutex_Release(tMutex *Mutex) Mutex->Owner = NULL; } SHORTREL( &Mutex->Protector ); + + #if 0 + extern tMutex glPhysAlloc; + if( Mutex != &glPhysAlloc ) + LogF("Mutex %p released by %i %p\n", Mutex, Threads_GetTID(), __builtin_return_address(0)); + #endif } /** @@ -1208,6 +1254,86 @@ int Mutex_IsLocked(tMutex *Mutex) return Mutex->Owner != NULL; } +/** + * \brief Initialise the semaphore + * \param Value Initial value of the semaphore + * \param Label Symbolic name + */ +void Semaphore_Init(tSemaphore *Sem, int Value, const char *Label) +{ + Sem->Value = Value; + Sem->Name = Label; +} + +/** + * \brief Acquire a "item" from the semaphore + */ +void Semaphore_Wait(tSemaphore *Sem) +{ + tThread *us; + + SHORTLOCK( &Sem->Protector ); + if( Sem->Value > 0 ) { + Sem->Value --; + SHORTREL( &Sem->Protector ); + return ; + } + + SHORTLOCK( &glThreadListLock ); + + // - Remove from active list + us = Threads_RemActive(); + us->Next = NULL; + // - Mark as sleeping + us->Status = THREAD_STAT_SEMAPHORESLEEP; + us->WaitPointer = Sem; + + // - Add to waiting + if(Sem->LastWaiting) { + Sem->LastWaiting->Next = us; + Sem->LastWaiting = us; + } + else { + Sem->Waiting = us; + Sem->LastWaiting = us; + } + + SHORTREL( &glThreadListLock ); + SHORTREL( &Sem->Protector ); + while(us->Status == THREAD_STAT_MUTEXSLEEP) Threads_Yield(); + // We're only woken when there's something avaliable + us->WaitPointer = NULL; +} + +/** + * \brief Add an "item" to the semaphore + */ +void Semaphore_Signal(tSemaphore *Sem) +{ + SHORTLOCK( &Sem->Protector ); + Sem->Value ++; + + if( Sem->Waiting ) + { + tThread *toWake = Sem->Waiting; + + Sem->Waiting = Sem->Waiting->Next; // Next! + // Reset ->LastWaiting to NULL if we have just removed the last waiting thread + if( Sem->Waiting == NULL ) + Sem->LastWaiting = NULL; + + // Wake new owner + SHORTLOCK( &glThreadListLock ); + if( toWake->Status != THREAD_STAT_ACTIVE ) + Threads_AddActive(toWake); + SHORTREL( &glThreadListLock ); + + // Decrement (the value is now "owned" by `toWake`) + Sem->Value --; + } + SHORTREL( &Sem->Protector ); +} + // === EXPORTS === EXPORT(Threads_GetUID); EXPORT(Threads_GetGID);