+/**
+ * \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
+ Threads_RemActive();
+ // - Mark as sleeping
+ us->Status = THREAD_STAT_OFFSLEEP;
+
+ // - Add to waiting
+ if(Mutex->LastWaiting) {
+ Mutex->LastWaiting->Next = us;
+ Mutex->LastWaiting = us;
+ }
+ else {
+ Mutex->Waiting = us;
+ Mutex->LastWaiting = us;
+ }
+ SHORTREL( &glThreadListLock );
+ SHORTREL( &Mutex->Protector );
+ while(us->Status == THREAD_STAT_OFFSLEEP) HALT();
+ // We're only woken when we get the lock
+ }
+ // Ooh, let's take it!
+ else {
+ Mutex->Owner = us;
+ SHORTREL( &Mutex->Protector );
+ }
+}
+
+/**
+ * \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!
+ // Wake new owner
+ Mutex->Owner->Status = THREAD_STAT_ACTIVE;
+ Threads_AddActive(Mutex->Owner);
+ //Log("Mutex %p Woke %p", Mutex, Mutex->Owner);
+ }
+ else {
+ Mutex->Owner = NULL;
+ }
+ SHORTREL( &Mutex->Protector );
+}
+
+/**
+ * \brief Is this mutex locked?
+ * \param Mutex Mutex pointer
+ */
+int Mutex_IsLocked(tMutex *Mutex)
+{
+ return Mutex->Owner != NULL;
+}
+