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;
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;
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
//