+
+int Threads_WaitTID(int TID, int *Status)
+{
+ // Any Child
+ if(TID == -1) {
+ Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
+ return -1;
+ }
+
+ // Any peer/child thread
+ if(TID == 0) {
+ Log_Error("Threads", "TODO: Threads_WaitTID(TID=0) - Any Child/Sibling");
+ return -1;
+ }
+
+ // TGID = abs(TID)
+ if(TID < -1) {
+ Log_Error("Threads", "TODO: Threads_WaitTID(TID<0) - TGID");
+ return -1;
+ }
+
+ // Specific Thread
+ if(TID > 0) {
+
+ tThread *thread = Threads_GetThread(TID);
+ tThread *us = gpCurrentThread;
+ if(!thread) return -1;
+
+ us->Next = NULL;
+ us->State = 3;
+ if(thread->WaitingThreadsEnd)
+ {
+ thread->WaitingThreadsEnd->Next = us;
+ thread->WaitingThreadsEnd = us;
+ }
+ else
+ {
+ thread->WaitingThreads = us;
+ thread->WaitingThreadsEnd = us;
+ }
+
+ while(thread->State != 0)
+ pause();
+
+ if(Status) *Status = thread->ExitStatus;
+ thread->WaitingThreads = thread->WaitingThreads->Next;
+ us->Next = NULL;
+
+ return TID;
+ }
+
+ return 0;
+}
+
+void Threads_Sleep(void)
+{
+ // TODO: Add to a sleeping queue
+ pause();
+}
+
+void Threads_Yield(void)
+{
+// yield();
+}
+
+void Threads_Exit(int TID, int Status)
+{
+ tThread *toWake;
+
+// VFS_Handles_Cleanup();
+
+ #if 1
+ // Wait for the thread to be waited upon
+ while( gpCurrentThread->WaitingThreads == NULL )
+ SDL_Delay(10);
+ #endif
+
+ while( (toWake = gpCurrentThread->WaitingThreads) )
+ {
+ Threads_Wake(toWake);
+
+ while(gpCurrentThread->WaitingThreads == toWake)
+ SDL_Delay(10);
+ }
+}
+
+int Threads_Wake(tThread *Thread)
+{
+ kill( Thread->KernelTID, SIGUSR1 );
+ return 0;
+}
+
+int Threads_WakeTID(tTID TID)
+{
+ tThread *thread;
+ thread = Threads_GetThread(TID);
+ if( !thread ) return -1;
+ return Threads_Wake(thread);
+}
+
+int Threads_CreateRootProcess(void)
+{
+ tThread *thread = Threads_CloneTCB(&gThreadZero);
+ thread->PID = thread->TID;
+
+ // Handle list is created on first open
+
+ return thread->PID;
+}
+
+int Threads_Fork(void)
+{
+ tThread *thread = Threads_CloneTCB(gpCurrentThread);
+ thread->PID = thread->TID;
+ // Duplicate the VFS handles (and nodes) from vfs_handle.c
+
+ VFS_CloneHandleList(thread->PID);
+
+ return thread->PID;
+}
+
+int Mutex_Acquire(tMutex *Mutex)
+{
+ if(!Mutex->Protector.IsValid) {
+ pthread_mutex_init( &Mutex->Protector.Mutex, NULL );
+ Mutex->Protector.IsValid = 1;
+ }
+ pthread_mutex_lock( &Mutex->Protector.Mutex );
+ return 0;
+}
+
+void Mutex_Release(tMutex *Mutex)
+{
+ pthread_mutex_unlock( &Mutex->Protector.Mutex );
+}
+
+void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name)
+{
+ memset(Sem, 0, sizeof(tSemaphore));
+ // HACK: Use `Sem->Protector` as space for the semaphore pointer
+ *(void**)(&Sem->Protector) = SDL_CreateSemaphore(InitValue);
+}
+
+int Semaphore_Wait(tSemaphore *Sem, int MaxToTake)
+{
+ SDL_SemWait( *(void**)(&Sem->Protector) );
+ return 1;
+}
+
+int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd)
+{
+ int i;
+ for( i = 0; i < AmmountToAdd; i ++ )
+ SDL_SemPost( *(void**)(&Sem->Protector) );
+ return AmmountToAdd;
+}
+
+#if 0
+void Threads_Sleep()
+{
+ gpCurrentThread->State = 3;
+ if( setjmp(&gpCurrentThread->CurState) == 0 ) {
+ // Return to user wait
+ // Hmm... maybe I should have a "kernel" thread for every "user" thread
+ }
+ else {
+ // Just woken up, return
+ return ;
+ }
+}
+
+int SaveState(tState *To)
+{
+ Uint ip;
+ __asm__ __volatile__(
+ "call 1f;\n\t"
+ "1f:\n\t"
+ "pop %%eax"
+ : "=a" (ip)
+ : );
+ // If we just returned
+ if(!ip) return 1;
+
+ To->IP = ip;
+ __asm__ __volatile__ ("mov %%esp, %1" : "=r"(To->SP));
+ __asm__ __volatile__ ("mov %%ebp, %1" : "=r"(To->BP));
+}
+#endif
+