X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=KernelLand%2FKernel%2Fsemaphore.c;h=ce7d4ba05f4ef40f37583a47ec5c310658c39fe1;hb=2db551c69841b4fb5a70ae05e08d54b1a016364b;hp=2c9fc94b47303e90f0ffe6827f5e9256cb1a6c81;hpb=f0e63fc3dd8dd2a6a82b855c89a1b8106e297a68;p=tpg%2Facess2.git diff --git a/KernelLand/Kernel/semaphore.c b/KernelLand/Kernel/semaphore.c index 2c9fc94b..ce7d4ba0 100644 --- a/KernelLand/Kernel/semaphore.c +++ b/KernelLand/Kernel/semaphore.c @@ -78,6 +78,7 @@ int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) SHORTREL( &Sem->Protector ); // Release first to make sure it is released SHORTREL( &glThreadListLock ); + // Sleep until woken (either by getting what we need, or a timer event) while( us->Status == THREAD_STAT_SEMAPHORESLEEP ) { Threads_Yield(); @@ -244,13 +245,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 //