extern tThread *Threads_CloneTCB(Uint Flags);
extern tThread *Threads_CloneThreadZero(void);
+extern int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock);
extern void Threads_int_WaitForStatusEnd(enum eThreadStatus Status);
extern void Semaphore_ForceWake(tThread *Thread);
// Check if the lock is already held
if( Mutex->Owner ) {
- SHORTLOCK( &glThreadListLock );
- // - Remove from active list
- us = Threads_RemActive();
- us->Next = NULL;
- // - Mark as sleeping
- us->Status = THREAD_STAT_MUTEXSLEEP;
- us->WaitPointer = Mutex;
-
- // - Add to waiting
- if(Mutex->LastWaiting) {
- Mutex->LastWaiting->Next = us;
- Mutex->LastWaiting = us;
- }
- else {
- Mutex->Waiting = us;
- Mutex->LastWaiting = us;
- }
-
- #if DEBUG_TRACE_STATE
- Log("%p (%i %s) waiting on mutex %p",
- us, us->TID, us->ThreadName, Mutex);
- #endif
-
- #if 0
- {
- int i = 0;
- tThread *t;
- for( t = Mutex->Waiting; t; t = t->Next, i++ )
- Log("[%i] (tMutex)%p->Waiting[%i] = %p (%i %s)", us->TID, Mutex, i,
- t, t->TID, t->ThreadName);
- }
- #endif
-
- SHORTREL( &glThreadListLock );
- SHORTREL( &Mutex->Protector );
- Threads_int_WaitForStatusEnd(THREAD_STAT_MUTEXSLEEP);
- // We're only woken when we get the lock
- us->WaitPointer = NULL;
+ // Sleep on the lock
+ Threads_int_Sleep(THREAD_STAT_MUTEXSLEEP,
+ Mutex, 0,
+ &Mutex->Waiting, &Mutex->LastWaiting, &Mutex->Protector);
+ // - We're only woken when we get the lock
}
- // Ooh, let's take it!
else {
+ // If not, just obtain it
Mutex->Owner = us;
SHORTREL( &Mutex->Protector );
}
//
int RWLock_AcquireRead(tRWLock *Lock)
{
- tThread *us;
LOG("Acquire RWLock Read %p", Lock);
// Get protector
SHORTLOCK( &Lock->Protector );
if( Lock->Owner )
{
LOG("Waiting");
- SHORTLOCK( &glThreadListLock );
-
- // - Remove from active list
- us = Threads_RemActive();
- us->Next = NULL;
- // - Mark as sleeping
- us->Status = THREAD_STAT_RWLOCKSLEEP;
- us->WaitPointer = Lock;
-
- // - Add to waiting
- if(Lock->ReaderWaiting)
- Lock->ReaderWaitingLast->Next = us;
- else
- Lock->ReaderWaiting = us;
- Lock->ReaderWaitingLast = us;
-
- #if DEBUG_TRACE_STATE
- Log("%p (%i %s) waiting on rwlock %p",
- us, us->TID, us->ThreadName, Lock);
- #endif
-
- SHORTREL( &glThreadListLock );
- SHORTREL( &Lock->Protector );
- Threads_int_WaitForStatusEnd(THREAD_STAT_RWLOCKSLEEP);
- // We're only woken when we get the lock
- // TODO: Handle when this isn't the case
- us->WaitPointer = NULL;
+ Threads_int_Sleep(THREAD_STAT_RWLOCKSLEEP, Lock, 0,
+ &Lock->ReaderWaiting, &Lock->ReaderWaitingLast,
+ &Lock->Protector);
}
// Ooh, no problems then!
else
int RWLock_AcquireWrite(tRWLock *Lock)
{
- tThread *us;
-
LOG("Acquire RWLock Write %p", Lock);
SHORTLOCK(&Lock->Protector);
if( Lock->Owner || Lock->Level != 0 )
{
LOG("Waiting");
- SHORTLOCK(&glThreadListLock);
-
- us = Threads_RemActive();
- us->Next = NULL;
- us->Status = THREAD_STAT_RWLOCKSLEEP;
- us->WaitPointer = Lock;
-
- if( Lock->WriterWaiting )
- Lock->WriterWaitingLast->Next = us;
- else
- Lock->WriterWaiting = us;
- Lock->WriterWaitingLast = us;
-
- SHORTREL( &glThreadListLock );
- SHORTREL( &Lock->Protector );
-
- Threads_int_WaitForStatusEnd(THREAD_STAT_RWLOCKSLEEP);
- us->WaitPointer = NULL;
+ Threads_int_Sleep(THREAD_STAT_RWLOCKSLEEP, Lock, 0,
+ &Lock->WriterWaiting, &Lock->WriterWaitingLast,
+ &Lock->Protector);
}
else
{
//
int Semaphore_Wait(tSemaphore *Sem, int MaxToTake)
{
- tThread *us;
int taken;
if( MaxToTake < 0 ) {
Log_Warning("Threads", "Semaphore_Wait: User bug - MaxToTake(%i) < 0, Sem=%p(%s)",
}
else
{
- #if 0
- Threads_int_Sleep(THREAD_STAT_SEMAPHORESLEEP,
+ taken = Threads_int_Sleep(THREAD_STAT_SEMAPHORESLEEP,
Sem, MaxToTake,
&Sem->Waiting, &Sem->LastWaiting, &Sem->Protector);
- #endif
- SHORTLOCK( &glThreadListLock );
-
- // - Remove from active list
- us = Threads_RemActive();
- us->Next = NULL;
- // - Mark as sleeping
- us->Status = THREAD_STAT_SEMAPHORESLEEP;
- us->WaitPointer = Sem;
- us->RetStatus = MaxToTake; // Use RetStatus as a temp variable
-
- // - Add to waiting
- if(Sem->LastWaiting) {
- Sem->LastWaiting->Next = us;
- Sem->LastWaiting = us;
- }
- else {
- Sem->Waiting = us;
- Sem->LastWaiting = us;
- }
-
- #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 );
- SHORTREL( &glThreadListLock );
- // NOTE: This can break in SMP
- // 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 from wait", Sem, Sem->ModName, Sem->Name);
- #endif
- us->WaitPointer = NULL;
-
- taken = us->RetStatus;
// Get the lock again
SHORTLOCK( &Sem->Protector );
// Check if we have to block
if( Sem->MaxValue && Sem->Value == Sem->MaxValue )
{
- tThread *us;
#if 0
Log_Debug("Threads", "Semaphore_Signal: IDLE Sem = %s:%s", Sem->ModName, Sem->Name);
Log_Debug("Threads", "Semaphore_Signal: Sem->Value(%i) == Sem->MaxValue(%i)", Sem->Value, Sem->MaxValue);
#endif
-
- SHORTLOCK( &glThreadListLock );
- // - Remove from active list
- us = Threads_RemActive();
- us->Next = NULL;
- // - Mark as sleeping
- us->Status = THREAD_STAT_SEMAPHORESLEEP;
- us->WaitPointer = Sem;
- us->RetStatus = AmmountToAdd; // Use RetStatus as a temp variable
-
- // - Add to waiting
- if(Sem->LastSignaling) {
- Sem->LastSignaling->Next = us;
- Sem->LastSignaling = us;
- }
- else {
- Sem->Signaling = us;
- Sem->LastSignaling = us;
- }
-
- #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);
- #endif
-
- SHORTREL( &glThreadListLock );
- SHORTREL( &Sem->Protector );
- Threads_int_WaitForStatusEnd(THREAD_STAT_SEMAPHORESLEEP);
- // We're only woken when there's something avaliable
- us->WaitPointer = NULL;
-
- added = us->RetStatus;
+ added = Threads_int_Sleep(THREAD_STAT_SEMAPHORESLEEP,
+ Sem, AmmountToAdd,
+ &Sem->Signaling, &Sem->LastSignaling, &Sem->Protector);
// Get the lock again
SHORTLOCK( &Sem->Protector );
void Threads_Kill(tThread *Thread, int Status);
void Threads_Yield(void);
#endif
-void Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock);
+ int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock);
#if 0
void Threads_Sleep(void);
int Threads_Wake(tThread *Thread);
}
}
-void Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
+int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
{
SHORTLOCK( &glThreadListLock );
tThread *us = Threads_RemActive();
if( ListTail ) {
if(*ListTail) {
(*ListTail)->Next = us;
- *ListTail = us;
}
else {
*ListHead = us;
- *ListTail = us;
}
+ *ListTail = us;
}
else {
*ListHead = us;
// return ;
SHORTREL( &glThreadListLock );
if( Lock )
- SHORTLOCK( Lock );
+ SHORTREL( Lock );
Threads_int_WaitForStatusEnd(Status);
+ us->WaitPointer = NULL;
+ return us->RetStatus;
}
/**
void *Workqueue_GetWork(tWorkqueue *Queue)
{
- tThread *us;
-
for( ;; )
{
// Check for work
return ret;
}
- #if 0
Threads_int_Sleep(THREAD_STAT_QUEUESLEEP,
Queue, 0,
&Queue->Sleeper, NULL, &Queue->Protector);
- #endif
- // Go to sleep
- SHORTLOCK(&glThreadListLock);
- us = Threads_RemActive();
- us->WaitPointer = Queue;
- us->Status = THREAD_STAT_QUEUESLEEP;
- Queue->Sleeper = us;
-
- SHORTREL(&Queue->Protector);
- SHORTREL(&glThreadListLock);
-
- // Yield and sleep
- Threads_int_WaitForStatusEnd(THREAD_STAT_QUEUESLEEP);
-
- us->WaitPointer = NULL;
}
}