+int Threads_SetUID(tUID NewUID)
+{
+ if(Threads_GetUID() != 0) {
+ errno = EACCES;
+ return -1;
+ }
+
+ gpCurrentThread->UID = NewUID;
+ return 0;
+}
+
+int Threads_SetGID(tGID NewGID)
+{
+ if(Threads_GetUID() != 0) {
+ errno = -EACCES;
+ return -1;
+ }
+
+ gpCurrentThread->GID = NewGID;
+ return 0;
+}
+
+int *Threads_GetErrno(void) { return &gpCurrentThread->_errno; }
+char **Threads_GetCWD(void) { return &gpCurrentThread->Process->CWD; }
+char **Threads_GetChroot(void) { return &gpCurrentThread->Process->Chroot; }
+int *Threads_GetMaxFD(void) { return &gpCurrentThread->Process->MaxFD; };
+
+tTID 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->Status = THREAD_STAT_WAITING;
+ // TODO: Locking
+ if(thread->WaitingThreadsEnd)
+ {
+ thread->WaitingThreadsEnd->Next = us;
+ thread->WaitingThreadsEnd = us;
+ }
+ else
+ {
+ thread->WaitingThreads = us;
+ thread->WaitingThreadsEnd = us;
+ }
+
+ Threads_WaitEvents( THREAD_EVENT_WAKEUP );
+
+ 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();
+
+ gpCurrentThread->ExitStatus = Status;
+
+ #if 1
+ if( gpCurrentThread->Parent )
+ {
+ // Wait for the thread to be waited upon
+ while( gpCurrentThread->WaitingThreads == NULL )
+ Threads_Glue_Yield();
+ }
+ #endif
+
+ while( (toWake = gpCurrentThread->WaitingThreads) )
+ {
+ Log_Debug("Threads", "Threads_Exit - Waking %p %i '%s'", toWake, toWake->TID, toWake->ThreadName);
+
+ Threads_Wake(toWake);
+
+ while(gpCurrentThread->WaitingThreads == toWake)
+ Threads_Glue_Yield();
+ }
+}
+
+int Threads_Wake(tThread *Thread)
+{
+ Thread->Status = THREAD_STAT_ACTIVE;
+ Threads_PostEvent(Thread, THREAD_EVENT_WAKEUP);
+ 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 Threads_Spawn(int nFD, int FDs[], struct s_sys_spawninfo *info)
+{
+ tThread *thread = Threads_CloneTCB(gpCurrentThread);
+ thread->PID = thread->TID;
+ if( info )
+ {
+ // TODO: PGID?
+ //if( info->flags & SPAWNFLAG_NEWPGID )
+ // thread->PGID = thread->PID;
+ if( info->gid && thread->UID == 0 )
+ thread->GID = info->gid;
+ if( info->uid && thread->UID == 0 ) // last because ->UID is used above
+ thread->UID = info->uid;
+ }
+
+ VFS_CloneHandlesFromList(thread->PID, nFD, FDs);
+
+ Log_Debug("Threads", "_spawn: %i", thread->PID);
+ return thread->PID;
+}
+
+// --------------------------------------------------------------------
+// Mutexes
+// --------------------------------------------------------------------
+int Mutex_Acquire(tMutex *Mutex)
+{
+ Threads_Glue_AcquireMutex(&Mutex->Protector.Mutex);
+ return 0;
+}
+
+void Mutex_Release(tMutex *Mutex)
+{
+ Threads_Glue_ReleaseMutex(&Mutex->Protector.Mutex);
+}
+
+// --------------------------------------------------------------------
+// Semaphores
+// --------------------------------------------------------------------
+void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name)