-/**
- * \fn void Threads_SegFault(tVAddr Addr)
- * \brief Called when a Segment Fault occurs
- */
-void Threads_SegFault(tVAddr Addr)
-{
- Warning("Thread #%i committed a segfault at address %p", Proc_GetCurThread()->TID, Addr);
- Threads_Fault( 1 );
- //Threads_Exit( 0, -1 );
-}
-
-/**
- * \brief Acquire a heavy mutex
- * \param Mutex Mutex to acquire
- *
- * This type of mutex checks if the mutex is avaliable, and acquires it
- * if it is. Otherwise, the current thread is added to the mutex's wait
- * queue and the thread suspends. When the holder of the mutex completes,
- * the oldest thread (top thread) on the queue is given the lock and
- * restarted.
- */
-void Mutex_Acquire(tMutex *Mutex)
-{
- tThread *us = Proc_GetCurThread();
-
- // Get protector
- SHORTLOCK( &Mutex->Protector );
-
- //Log("Mutex_Acquire: (%p)", Mutex);
-
- // 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 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 );
- while(us->Status == THREAD_STAT_MUTEXSLEEP) Threads_Yield();
- // We're only woken when we get the lock
- us->WaitPointer = NULL;
- }
- // Ooh, let's take it!
- else {
- Mutex->Owner = us;
- SHORTREL( &Mutex->Protector );
- }
-
- #if 0
- extern tMutex glPhysAlloc;
- if( Mutex != &glPhysAlloc )
- LogF("Mutex %p taken by %i %p\n", Mutex, us->TID, __builtin_return_address(0));
- #endif
-}
-
-/**
- * \brief Release a held mutex
- * \param Mutex Mutex to release
- */
-void Mutex_Release(tMutex *Mutex)
-{
- SHORTLOCK( &Mutex->Protector );
- //Log("Mutex_Release: (%p)", Mutex);
- if( Mutex->Waiting ) {
- Mutex->Owner = Mutex->Waiting; // Set owner
- Mutex->Waiting = Mutex->Waiting->Next; // Next!
- // Reset ->LastWaiting to NULL if we have just removed the last waiting thread
- // 2010-10-02 21:50 - Comemerating the death of the longest single
- // blocker in the Acess2 history. REMEMBER TO
- // FUCKING MAINTAIN YOUR FUCKING LISTS DIPWIT
- if( Mutex->LastWaiting == Mutex->Owner )
- Mutex->LastWaiting = NULL;
-
- // Wake new owner
- SHORTLOCK( &glThreadListLock );
- if( Mutex->Owner->Status != THREAD_STAT_ACTIVE )
- Threads_AddActive(Mutex->Owner);
- SHORTREL( &glThreadListLock );
- }
- else {
- Mutex->Owner = NULL;
- }
- SHORTREL( &Mutex->Protector );
-
- #if 0
- extern tMutex glPhysAlloc;
- if( Mutex != &glPhysAlloc )
- LogF("Mutex %p released by %i %p\n", Mutex, Threads_GetTID(), __builtin_return_address(0));
- #endif
-}
-
-/**
- * \brief Is this mutex locked?
- * \param Mutex Mutex pointer
- */
-int Mutex_IsLocked(tMutex *Mutex)
-{
- return Mutex->Owner != NULL;
-}
-
-/**
- * \brief Initialise the semaphore
- * \param Value Initial value of the semaphore
- * \param Label Symbolic name
- */
-void Semaphore_Init(tSemaphore *Sem, int Value, const char *Label)
-{
- Sem->Value = Value;
- Sem->Name = Label;
-}
-
-/**
- * \brief Acquire a "item" from the semaphore
- */
-void Semaphore_Wait(tSemaphore *Sem)
-{
- tThread *us;
-
- SHORTLOCK( &Sem->Protector );
- if( Sem->Value > 0 ) {
- Sem->Value --;
- SHORTREL( &Sem->Protector );
- return ;
- }
-
- SHORTLOCK( &glThreadListLock );
-
- // - Remove from active list
- us = Threads_RemActive();
- us->Next = NULL;
- // - Mark as sleeping
- us->Status = THREAD_STAT_SEMAPHORESLEEP;
- us->WaitPointer = Sem;
-
- // - Add to waiting
- if(Sem->LastWaiting) {
- Sem->LastWaiting->Next = us;
- Sem->LastWaiting = us;
- }
- else {
- Sem->Waiting = us;
- Sem->LastWaiting = us;
- }
-
- SHORTREL( &glThreadListLock );
- SHORTREL( &Sem->Protector );
- while(us->Status == THREAD_STAT_MUTEXSLEEP) Threads_Yield();
- // We're only woken when there's something avaliable
- us->WaitPointer = NULL;
-}
-
-/**
- * \brief Add an "item" to the semaphore
- */
-void Semaphore_Signal(tSemaphore *Sem)
-{
- SHORTLOCK( &Sem->Protector );
- Sem->Value ++;
-
- if( Sem->Waiting )
- {
- tThread *toWake = Sem->Waiting;
-
- Sem->Waiting = Sem->Waiting->Next; // Next!
- // Reset ->LastWaiting to NULL if we have just removed the last waiting thread
- if( Sem->Waiting == NULL )
- Sem->LastWaiting = NULL;
-
- // Wake new owner
- SHORTLOCK( &glThreadListLock );
- if( toWake->Status != THREAD_STAT_ACTIVE )
- Threads_AddActive(toWake);
- SHORTREL( &glThreadListLock );
-
- // Decrement (the value is now "owned" by `toWake`)
- Sem->Value --;
- }
- SHORTREL( &Sem->Protector );
-}
-