X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fthreads.c;h=fa6f6e0f57b4350c8120496861b9001c9dfcae46;hb=952891ddb96a341c0e24ecb7dec6361c7bbeaece;hp=ecddf94552f9bff3a4c9762c4a7501dbcd0a498b;hpb=9c61cf12758c0977ee1dc5791cba638fd3437ba6;p=tpg%2Facess2.git diff --git a/Kernel/threads.c b/Kernel/threads.c index ecddf945..fa6f6e0f 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -7,11 +7,13 @@ #include #include #include +#include #include // Configuration #define DEBUG_TRACE_TICKETS 0 // Trace ticket counts #define DEBUG_TRACE_STATE 0 // Trace state changes (sleep/wake) +#define SEMAPHORE_DEBUG 0 // --- Schedulers --- #define SCHED_UNDEF 0 @@ -19,10 +21,10 @@ #define SCHED_RR_SIM 2 // Single Queue Round Robin #define SCHED_RR_PRI 3 // Multi Queue Round Robin // Set scheduler type -#define SCHEDULER_TYPE SCHED_LOTTERY +#define SCHEDULER_TYPE SCHED_RR_PRI // === CONSTANTS === -#define DEFAULT_QUANTUM 10 +#define DEFAULT_QUANTUM 5 #define DEFAULT_PRIORITY 5 #define MIN_PRIORITY 10 const enum eConfigTypes cCONFIG_TYPES[] = { @@ -754,6 +756,56 @@ int Threads_Wake(tThread *Thread) SHORTREL( &glThreadListLock ); return -EOK; + case THREAD_STAT_SEMAPHORESLEEP: { + tSemaphore *sem; + tThread *th, *prev=NULL; + + sem = Thread->WaitPointer; + + SHORTLOCK( &sem->Protector ); + + // Remove from sleeping queue + for( th = sem->Waiting; th; prev = th, th = th->Next ) + if( th == Thread ) break; + if( th ) + { + if(prev) + prev->Next = Thread->Next; + else + sem->Waiting = Thread->Next; + if(sem->LastWaiting == Thread) + sem->LastWaiting = prev; + } + else + { + prev = NULL; + for( th = sem->Signaling; th; prev = th, th = th->Next ) + if( th == Thread ) break; + if( !th ) { + Log_Warning("Threads", "Thread %p(%i %s) is not on semaphore %p(%s:%s)", + Thread, Thread->TID, Thread->ThreadName, + sem, sem->ModName, sem->Name); + return -EINTERNAL; + } + + if(prev) + prev->Next = Thread->Next; + else + sem->Signaling = Thread->Next; + if(sem->LastSignaling == Thread) + sem->LastSignaling = prev; + } + + SHORTLOCK( &glThreadListLock ); + Threads_AddActive( Thread ); + SHORTREL( &glThreadListLock ); + + #if DEBUG_TRACE_STATE + Log("Threads_Sleep: %p(%i %s) woken from semaphore", Thread, Thread->TID, Thread->ThreadName); + #endif + SHORTREL( &sem->Protector ); + } return -EOK; + case THREAD_STAT_WAITING: Warning("Threads_Wake - Waiting threads are not currently supported"); return -ENOTIMPL; @@ -808,14 +860,25 @@ void Threads_AddActive(tThread *Thread) // Set state Thread->Status = THREAD_STAT_ACTIVE; +// Thread->CurCPU = -1; // Add to active list - #if SCHEDULER_TYPE == SCHED_RR_PRI - Thread->Next = gaActiveThreads[Thread->Priority]; - gaActiveThreads[Thread->Priority] = Thread; - #else - Thread->Next = gActiveThreads; - gActiveThreads = Thread; - #endif + { + tThread *tmp, *prev = NULL; + #if SCHEDULER_TYPE == SCHED_RR_PRI + for( tmp = gaActiveThreads[Thread->Priority]; tmp; prev = tmp, tmp = tmp->Next ); + if(prev) + prev->Next = Thread; + else + gaActiveThreads[Thread->Priority] = Thread; + #else + for( tmp = gActiveThreads; tmp; prev = tmp, tmp = tmp->Next ); + if(prev) + prev->Next = Thread; + else + gActiveThreads = Thread; + #endif + Thread->Next = NULL; + } // Update bookkeeping giNumActiveThreads ++; @@ -861,6 +924,9 @@ tThread *Threads_RemActive(void) #endif { SHORTREL( &glThreadListLock ); + Log_Warning("Threads", "Current thread %p(%i %s) is not on active queue", + ret, ret->TID, ret->ThreadName + ); return NULL; } @@ -898,8 +964,6 @@ void Threads_Fault(int Num) { tThread *thread = Proc_GetCurThread(); - Log_Log("Threads", "Threads_Fault: thread = %p", thread); - if(!thread) return ; Log_Log("Threads", "Threads_Fault: thread->FaultHandler = %p", thread->FaultHandler); @@ -1082,6 +1146,7 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) // 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; @@ -1102,7 +1167,10 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) } gDeleteThreads = thread; } - + + // Make sure the current (well, old) thread is marked as de-scheduled + if(Last) Last->CurCPU = -1; + // No active threads, just take a nap if(giNumActiveThreads == 0) { SHORTREL( &glThreadListLock ); @@ -1223,7 +1291,7 @@ tThread *Threads_GetNextToRun(int CPU, tThread *Last) } // If we fall onto the same queue again, special handling is // needed - if( i == Last->Priority ) { + if( Last && i == Last->Priority ) { tThread *savedThread = thread; // Find the next unscheduled thread in the list @@ -1417,7 +1485,6 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) else taken = Sem->Value; Sem->Value -= taken; - SHORTREL( &Sem->Protector ); } else { @@ -1441,16 +1508,16 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) Sem->LastWaiting = us; } - #if DEBUG_TRACE_STATE + #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG Log("%p (%i %s) waiting on semaphore %p %s:%s", us, us->TID, us->ThreadName, Sem, Sem->ModName, Sem->Name); #endif + SHORTREL( &Sem->Protector ); // Release first to make sure it is released SHORTREL( &glThreadListLock ); - SHORTREL( &Sem->Protector ); while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield(); - // We're only woken when there's something avaliable + // We're only woken when there's something avaliable (or a signal arrives) us->WaitPointer = NULL; taken = us->RetStatus; @@ -1479,7 +1546,7 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) Sem->Value -= given; - #if DEBUG_TRACE_STATE + #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG Log("%p (%i %s) woken by wait on %p %s:%s", toWake, toWake->TID, toWake->ThreadName, Sem, Sem->ModName, Sem->Name); @@ -1541,7 +1608,7 @@ int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd) Sem->LastSignaling = us; } - #if DEBUG_TRACE_STATE + #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG Log("%p (%i %s) signaling semaphore %p %s:%s", us, us->TID, us->ThreadName, Sem, Sem->ModName, Sem->Name); @@ -1593,7 +1660,7 @@ int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd) if(toWake->bInstrTrace) Log("%s(%i) given %i from %p", toWake->ThreadName, toWake->TID, given, Sem); - #if DEBUG_TRACE_STATE + #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG Log("%p (%i %s) woken by signal on %p %s:%s", toWake, toWake->TID, toWake->ThreadName, Sem, Sem->ModName, Sem->Name); @@ -1603,6 +1670,8 @@ int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd) SHORTLOCK( &glThreadListLock ); if( toWake->Status != THREAD_STAT_ACTIVE ) Threads_AddActive(toWake); + else + Warning("Thread %p (%i %s) is already awake", toWake, toWake->TID, toWake->ThreadName); SHORTREL( &glThreadListLock ); } SHORTREL( &Sem->Protector );