Usermode/libaxwin4 - Handle demarshal failure
[tpg/acess2.git] / AcessNative / acesskernel_src / threads.c
index e436836..74d85fc 100644 (file)
  * threads.c
  * - Thread and process handling
  */
-#define _SIGNAL_H_
-#undef CLONE_VM        // Such a hack
+#define DEBUG  1
+#include <arch.h>
 #include <acess.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <stdint.h>
-#include "/usr/include/signal.h"
+#include <mutex.h>
+#include "../../KernelLand/Kernel/include/semaphore.h"
+typedef signed long long int   time_t;
+#include "../../Usermode/Libraries/ld-acess.so_src/include_exp/acess/syscall_types.h"
+#include <rwlock.h>
+#include <events.h>
+#include <threads_int.h>
+#include <limits.h>
+#include "include/threads_glue.h"
+#include <stdbool.h>
+
+#define THREAD_EVENT_WAKEUP    0x80000000
+
+// === IMPORTS ===
+extern void    VFS_CloneHandleList(int PID);
+extern void    VFS_CloneHandlesFromList(int PID, int nFD, int FDs[]);
+extern void    VFS_ClearHandles(int PID);
 
 // === STRUCTURES ===
-#if 0
-typedef struct sState
+// === PROTOTYPES ===
+ int   Threads_Wake(tThread *Thread);
+
+// === GLOBALS ===
+tProcess gProcessZero = {
+       .NativePID = 0,
+       .CWD = "/",
+       .Chroot = "/",
+       .MaxFD = 100
+};
+tThread        gThreadZero = {
+       .Status=THREAD_STAT_ACTIVE,
+       .ThreadName="ThreadZero",
+       .Process = &gProcessZero
+};
+tThread        *gpThreads = &gThreadZero;
+__thread tThread       *gpCurrentThread = &gThreadZero;
+ int   giThreads_NextThreadID = 1;
+
+// === CODE ===
+tThread *Proc_GetCurThread(void)
 {
-       void    *CurState;
-       Uint    SP, BP, IP;
-}      tState;
-#endif
+       return gpCurrentThread;
+}
 
-typedef struct sThread
+void Threads_Dump(void)
 {
-       struct sThread  *Next;
+       for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext )
+       {
+               Log_Log("Threads", "TID %i (%s), PID %i",
+                       thread->TID, thread->ThreadName, thread->Process->PID);
+               Log_Log("Threads", "User: %i, Group: %i",
+                       thread->Process->UID, thread->Process->GID);
+               Log_Log("Threads", "Kernel Thread ID: %i",
+                       thread->KernelTID);
+       }
+}
 
-        int    KernelTID;
+void Threads_SetThread(int TID, void *Client)
+{
+       for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext )
+       {
+               if( thread->TID == TID ) {
+                       gpCurrentThread = thread;
+                       thread->ClientPtr = Client;
+                       return ;
+               }
+       }
+       Log_Error("Threads", "_SetThread - Thread %i is not on global list", TID);
+}
 
-       tTID    TID, PID;
-       tUID    UID, GID;
+tThread        *Threads_GetThread(Uint TID)
+{
+       for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext )
+       {
+               if( thread->TID == TID ) {
+                       return thread;
+               }
+       }
+       return NULL;
+}
 
-       struct sThread  *Parent;
+/**
+ * \brief Clone a thread control block (with a different TID)
+ */
+tThread *Threads_CloneTCB(tThread *TemplateThread, bool bNewProcess)
+{
+       tThread *ret = malloc(sizeof(tThread));
+       memcpy(ret, TemplateThread, sizeof(tThread));
+       
+       ret->TID = giThreads_NextThreadID ++;
+       
+       ret->ThreadName = strdup(TemplateThread->ThreadName);
+       Threads_Glue_SemInit( &ret->EventSem, 0 );
+       
+       ret->WaitingThreads = NULL;
+       ret->WaitingThreadsEnd = NULL;
 
-       char    *ThreadName;
+       if( bNewProcess )
+       {
+               tProcess *proc = malloc( sizeof(tProcess) );
+               memcpy(proc, ret->Process, sizeof(tProcess));
+               proc->nThreads = 0;
+               proc->CWD = strdup(proc->CWD);
+               proc->Chroot = strdup(proc->Chroot);
+               
+               proc->PID = ret->TID;
+               
+               ret->Process = proc;
+       }       
 
-        int    State;  // 0: Dead, 1: Active, 2: Paused, 3: Asleep
-       #if 0
-       tState  CurState;
-       #endif
+       ret->Process->nThreads ++;
 
-       // Config?
-       Uint    Config[NUM_CFG_ENTRIES];
-}      tThread;
+       // Add to the end of the queue
+       // TODO: Handle concurrency issues
+       ret->GlobalNext = gpThreads;
+       gpThreads = ret;
+       
+       return ret;
+}
 
-// === GLOBALS ===
-tThread        gThread_Zero = {
-       State: 1,
-       ThreadName: "ThreadZero"
-};
-tThread        *gpThreads = &gThread_Zero;
-__thread tThread       *gpCurrentThread = &gThread_Zero;
+void Threads_int_Destroy(tThread *Thread)
+{
+       // Clear WaitingThreads
+       
+       Threads_Glue_SemDestroy(Thread->EventSem);
+       free(Thread->ThreadName);
+       Thread->Process->nThreads --;
+}
 
-// === CODE ===
-tThread        *Threads_GetThread(int TID)
+void Threads_Terminate(void)
 {
-       tThread *thread;
-       for( thread = gpThreads; thread; thread = thread->Next )
+       tThread *us = gpCurrentThread;
+       tProcess *proc = us->Process;
+
+       if( us->TID == proc->PID )
        {
-               if( thread->TID == TID )
-                       return thread;
+               // If we're the process leader, then tear down the entire process
+               VFS_ClearHandles(proc->PID);
+               tThread **next_ptr = &gpThreads;
+               for( tThread *thread = gpThreads; thread; thread = *next_ptr )
+               {
+                       if( thread->Process == proc ) {
+                               Threads_int_Destroy(thread);
+                       }
+                       else {
+                               next_ptr = &thread->Next;
+                       }
+               }
+       }
+       else
+       {
+               // Just a lowly thread, remove from process
+               Threads_int_Destroy(us);
+       }
+       
+       if( proc->nThreads == 0 )
+       {
+               free(proc->Chroot);
+               free(proc->CWD);
+               free(proc);
        }
-       return NULL;
 }
 
-tUID Threads_GetUID() { return gpCurrentThread->UID; }
-tGID Threads_GetGID() { return gpCurrentThread->GID; }
+tUID Threads_GetUID() { return gpCurrentThread->Process->UID; }
+tGID Threads_GetGID() { return gpCurrentThread->Process->GID; }
 tTID Threads_GetTID() { return gpCurrentThread->TID; }
-tPID Threads_GetPID() {
-       return SDL_ThreadID();
-       //return gpCurrentThread->PID;
+tPID Threads_GetPID() { return gpCurrentThread->Process->PID; }
+
+int Threads_SetUID(tUID NewUID)
+{
+       if(Threads_GetUID() != 0) {
+               errno = EACCES;
+               return -1;
+       }
+       
+       gpCurrentThread->Process->UID = NewUID;
+       return 0;
 }
 
-Uint *Threads_GetCfgPtr(int Index)
+int Threads_SetGID(tGID NewGID)
 {
-       if( Index < 0 || Index >= NUM_CFG_ENTRIES )
-               return NULL;
-       if( !gpCurrentThread )
-               return NULL;
-       return &gpCurrentThread->Config[Index];
+       if(Threads_GetUID() != 0) {
+               errno = -EACCES;
+               return -1;
+       }
+       
+       gpCurrentThread->Process->GID = NewGID;
+       return 0;
+}
+
+int *Threads_GetErrno(void) { return &gpCurrentThread->_errno; }
+static tProcess *proc(tProcess *Proc) { return Proc ? Proc : gpCurrentThread->Process; }
+char **Threads_GetCWD   (tProcess *Proc) { return &proc(Proc)->CWD; }
+char **Threads_GetChroot(tProcess *Proc) { return &proc(Proc)->Chroot; }
+int *Threads_GetMaxFD   (tProcess *Proc) { return &proc(Proc)->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->RetStatus;
+               thread->WaitingThreads = thread->WaitingThreads->Next;
+               us->Next = NULL;
+               
+               return TID;
+       }
+       
+       return 0;
 }
 
-void Threads_Sleep(void)
+void Threads_Exit(int TID, int Status)
+{
+       tThread *toWake;
+       
+//     VFS_Handles_Cleanup();
+
+       gpCurrentThread->RetStatus = 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();
+       }
+}
+
+void Threads_Sleep()
 {
-       pause();
+       gpCurrentThread->Status = THREAD_STAT_SLEEPING;
+       Threads_int_WaitForStatusEnd(THREAD_STAT_SLEEPING);
 }
 
-void Threads_Yield(void)
+int Threads_Wake(tThread *Thread)
 {
-//     yield();
+       Thread->Status = THREAD_STAT_ACTIVE;
+       Threads_PostEvent(Thread, THREAD_EVENT_WAKEUP);
+       return 0;
 }
 
 int Threads_WakeTID(tTID TID)
@@ -96,53 +303,124 @@ int Threads_WakeTID(tTID TID)
        tThread *thread;
        thread = Threads_GetThread(TID);
        if( !thread )   return -1;
-       kill( thread->KernelTID, SIGUSR1 );
-       return 0;
+       return Threads_Wake(thread);
+}
+
+int Threads_CreateRootProcess(void)
+{
+       tThread *thread = Threads_CloneTCB(&gThreadZero, true);
+       
+       // Handle list is created on first open
+       
+       return thread->Process->PID;
 }
 
-void Mutex_Acquire(tMutex *Mutex)
+int Threads_Fork(void)
 {
-       if(!Mutex->Protector.IsValid) {
-               pthread_mutex_init( &Mutex->Protector.Mutex, NULL );
-               Mutex->Protector.IsValid = 1;
+       tThread *thread = Threads_CloneTCB(gpCurrentThread, true);
+
+       // Duplicate the VFS handles (and nodes) from vfs_handle.c
+       VFS_CloneHandleList(thread->Process->PID);
+       
+       return thread->Process->PID;
+}
+
+int Threads_Spawn(int nFD, int FDs[], struct s_sys_spawninfo *info)
+{
+       tThread *thread = Threads_CloneTCB(gpCurrentThread, true);
+       if( info )
+       {
+               // TODO: PGID?
+               //if( info->flags & SPAWNFLAG_NEWPGID )
+               //      thread->PGID = thread->PID;
+               if( thread->Process->UID == 0 )
+               {
+                       if( info->gid )
+                               thread->Process->GID = info->gid;
+                       if( info->uid )
+                               thread->Process->UID = info->uid;
+               }
        }
-       pthread_mutex_lock( &Mutex->Protector.Mutex );
+       
+       VFS_CloneHandlesFromList(thread->Process->PID, nFD, FDs);
+
+       return thread->Process->PID;
 }
 
-void Mutex_Release(tMutex *Mutex)
+// ----
+// ----
+void Threads_int_Terminate(tThread *Thread)
 {
-       pthread_mutex_unlock( &Mutex->Protector.Mutex );
+       Thread->RetStatus = -1;
+       Threads_AddActive(Thread);
 }
 
-#if 0
-void Threads_Sleep()
+void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
+{
+       tThread *us = Proc_GetCurThread();
+       ASSERT(Status != THREAD_STAT_ACTIVE);
+       ASSERT(Status != THREAD_STAT_DEAD);
+       LOG("%i(%s) - %i", us->TID, us->ThreadName, Status);
+       while( us->Status == Status )
+       {
+               if( Threads_Glue_SemWait(gpCurrentThread->EventSem, INT_MAX) == -1 ) {
+                       Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
+                               gpCurrentThread, gpCurrentThread->EventSem);
+                       return ;
+               }
+               if( us->Status == Status )
+                       Log_Warning("Threads", "Thread %p(%i %s) rescheduled while in %s state",
+                               us, us->TID, us->ThreadName, casTHREAD_STAT[Status]);
+       }
+}
+
+int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
 {
-       gpCurrentThread->State = 3;
-       if( setjmp(&gpCurrentThread->CurState) == 0 ) {
-               // Return to user wait
-               // Hmm... maybe I should have a "kernel" thread for every "user" thread
+       tThread *us = Proc_GetCurThread();
+       us->Next = NULL;
+       // - Mark as sleeping
+       us->Status = Status;
+       us->WaitPointer = Ptr;
+       us->RetStatus = Num;    // Use RetStatus as a temp variable
+               
+       // - Add to waiting
+       if( ListTail ) {
+               if(*ListTail) {
+                       (*ListTail)->Next = us;
+               }
+               else {
+                       *ListHead = us;
+               }
+               *ListTail = us;
        }
        else {
-               // Just woken up, return
-               return ;
+               *ListHead = us;
        }
+       
+       if( Lock ) {
+               SHORTREL( Lock );
+       }
+       Threads_int_WaitForStatusEnd(Status);
+       us->WaitPointer = NULL;
+       return us->RetStatus;
 }
 
-int SaveState(tState *To)
+void Threads_AddActive(tThread *Thread)
 {
-       Uint    ip;
-       __asm__ __volatile__(
-               "call 1f;\n\t"
-               "1f:\n\t"
-               "pop %%eax"
-               : "=a" (ip)
-               : );
-       // If we just returned
-       if(!ip) return 1;
+       LOG("%i(%s)", Thread->TID, Thread->ThreadName);
+       Thread->Status = THREAD_STAT_ACTIVE;
+       Threads_Glue_SemSignal(Thread->EventSem, 1);
+}
 
-       To->IP = ip;
-       __asm__ __volatile__ ("mov %%esp, %1" : "=r"(To->SP));
-       __asm__ __volatile__ ("mov %%ebp, %1" : "=r"(To->BP));
+// --------------------------------------------------------------------
+// Signals
+// --------------------------------------------------------------------
+void Threads_PostSignal(int SigNum)
+{
+       Log_Error("Threads", "TODO: %s", __func__);
+}
+void Threads_SignalGroup(tPGID PGID, int SignalNum)
+{
+       Log_Error("Threads", "TODO: %s", __func__);
 }
-#endif
 

UCC git Repository :: git.ucc.asn.au