X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fsemaphore.c;h=1111967a46ae4ecc22676fbee7de50aeaa505a0f;hb=950126c76c539e76574f6349b833f41c70ed6573;hp=2c9fc94b47303e90f0ffe6827f5e9256cb1a6c81;hpb=479d0634670b58da044bc58149662adba0ad1d0b;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/semaphore.c b/KernelLand/Kernel/semaphore.c index 2c9fc94b..1111967a 100644 --- a/KernelLand/Kernel/semaphore.c +++ b/KernelLand/Kernel/semaphore.c @@ -78,17 +78,12 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) SHORTREL( &Sem->Protector ); // Release first to make sure it is released SHORTREL( &glThreadListLock ); - while( us->Status == THREAD_STAT_SEMAPHORESLEEP ) - { - Threads_Yield(); - if(us->Status == THREAD_STAT_SEMAPHORESLEEP) - Log_Warning("Threads", "Semaphore %p %s:%s re-schedulued while asleep", - Sem, Sem->ModName, Sem->Name); - } + // Sleep until woken (either by getting what we need, or a timer event) + Threads_int_WaitForStatusEnd( THREAD_STAT_SEMAPHORESLEEP ); + // We're only woken when there's something avaliable (or a signal arrives) #if DEBUG_TRACE_STATE || SEMAPHORE_DEBUG - Log("Semaphore %p %s:%s woken", Sem, Sem->ModName, Sem->Name); + Log("Semaphore %p %s:%s woken from wait", Sem, Sem->ModName, Sem->Name); #endif - // We're only woken when there's something avaliable (or a signal arrives) us->WaitPointer = NULL; taken = us->RetStatus; @@ -190,7 +185,7 @@ int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd) SHORTREL( &glThreadListLock ); SHORTREL( &Sem->Protector ); - while(us->Status == THREAD_STAT_SEMAPHORESLEEP) Threads_Yield(); + Threads_int_WaitForStatusEnd(THREAD_STAT_SEMAPHORESLEEP); // We're only woken when there's something avaliable us->WaitPointer = NULL; @@ -244,13 +239,44 @@ int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd) if( toWake->Status != THREAD_STAT_ACTIVE ) Threads_AddActive(toWake); else - Warning("Thread %p (%i %s) is already awake", toWake, toWake->TID, toWake->ThreadName); + Warning("Thread %p (%i %s) is already awake", + toWake, toWake->TID, toWake->ThreadName); } SHORTREL( &Sem->Protector ); return added; } +void Semaphore_ForceWake(tThread *Thread) +{ + if( !CPU_HAS_LOCK(&Thread->IsLocked) ) { + Log_Error("Semaphore", "Force wake should be called with the thread lock held"); + return ; + } + if( Thread->Status != THREAD_STAT_SEMAPHORESLEEP ) { + Log_Error("Semaphore", "_ForceWake called on non-semaphore thread"); + return ; + } + + tSemaphore *sem = Thread->WaitPointer; + SHORTLOCK( &sem->Protector ); + tThread *prev = NULL; + if( sem->Waiting == Thread ) + sem->Waiting = sem->Waiting->Next; + else + { + for( prev = sem->Waiting; prev && prev->Next != Thread; prev = prev->Next ) + ; + if( prev ) + prev->Next = Thread->Next; + } + if( sem->LastWaiting == Thread ) + sem->LastWaiting = prev; + SHORTREL( &sem->Protector ); + Thread->RetStatus = 0; + Threads_AddActive(Thread); +} + // // Get the current value of a semaphore //