AcessNative - Bugfixes 'r' us, GUI can start and render (partially)
[tpg/acess2.git] / AcessNative / acesskernel_src / threads.c
index dc4d643..9de6140 100644 (file)
@@ -8,18 +8,29 @@
 #define _SIGNAL_H_     // Stop the acess signal.h being used
 #define _HEAP_H_       // Stop heap.h being imported (collides with stdlib heap)
 #define _VFS_EXT_H     // Stop vfs_ext.h being imported (collides with fd_set)
-#undef CLONE_VM        // Such a hack
+
+#define off_t  _acess_off_t
 #include <arch.h>
 #undef NULL    // Remove acess definition
 #include <acess.h>
 #include <mutex.h>
 #include <semaphore.h>
+#include <rwlock.h>
+#include <events.h>
+#include <threads_int.h>
+
+#undef CLONE_VM        // Such a hack
+#undef off_t   
+
+// - Native headers
 #include <unistd.h>
 #include <sys/types.h>
 #include <stdint.h>
 #include "/usr/include/signal.h"
 #include <SDL/SDL.h>
 
+#define THREAD_EVENT_WAKEUP    0x80000000
+
 // === IMPORTS ===
 void   VFS_CloneHandleList(int PID);
 
@@ -32,52 +43,31 @@ typedef struct sState
 }      tState;
 #endif
 
-typedef struct sThread
-{
-       struct sThread  *GlobalNext;
-       struct sThread  *Next;
-
-        int    KernelTID;
-
-       tTID    TID, PID;
-       tUID    UID, GID;
-
-       struct sThread  *Parent;
-
-       char    *ThreadName;
-
-        int    State;  // 0: Dead, 1: Active, 2: Paused, 3: Asleep
-        int    ExitStatus;
-       #if 0
-       tState  CurState;
-       #endif
-
-       // Threads waiting for this thread to exit.
-       // Quit logic:
-       // - Wait for `WaitingThreads` to be non-null (maybe?)
-       // - Wake first in the queue, wait for it to be removed
-       // - Repeat
-       // - Free thread and quit kernel thread
-       struct sThread  *WaitingThreads;
-       struct sThread  *WaitingThreadsEnd;
-
-       // Config?
-       Uint    Config[NUM_CFG_ENTRIES];
-}      tThread;
-
 // === PROTOTYPES ===
  int   Threads_Wake(tThread *Thread);
 
 // === GLOBALS ===
+tProcess gProcessZero = {
+       .NativePID = 0,
+       .CWD = "/",
+       .Chroot = "/",
+       .MaxFD = 100
+};
 tThread        gThreadZero = {
-       .State=1,
-       .ThreadName="ThreadZero"
+       .Status=THREAD_STAT_ACTIVE,
+       .ThreadName="ThreadZero",
+       .Process = &gProcessZero
 };
 tThread        *gpThreads = &gThreadZero;
 __thread tThread       *gpCurrentThread = &gThreadZero;
  int   giThreads_NextThreadID = 1;
 
 // === CODE ===
+tThread *Proc_GetCurThread(void)
+{
+       return gpCurrentThread;
+}
+
 void Threads_Dump(void)
 {
        tThread *thread;
@@ -105,13 +95,14 @@ void Threads_SetThread(int TID)
        Log_Error("Threads", "_SetThread - Thread %i is not on global list", TID);
 }
 
-tThread        *Threads_GetThread(int TID)
+tThread        *Threads_GetThread(Uint TID)
 {
        tThread *thread;
        for( thread = gpThreads; thread; thread = thread->GlobalNext )
        {
-               if( thread->TID == TID )
+               if( thread->TID == TID ) {
                        return thread;
+               }
        }
        return NULL;
 }
@@ -128,6 +119,10 @@ tThread *Threads_CloneTCB(tThread *TemplateThread)
        ret->TID = giThreads_NextThreadID ++;
        
        ret->ThreadName = strdup(TemplateThread->ThreadName);
+       ret->EventSem = SDL_CreateSemaphore(0);
+       if( !ret->EventSem ) {
+               Log_Warning("Threads", "Semaphore creation failed - %s", SDL_GetError());
+       }
        
        ret->WaitingThreads = NULL;
        ret->WaitingThreadsEnd = NULL;
@@ -145,10 +140,10 @@ tGID Threads_GetGID() { return gpCurrentThread->GID; }
 tTID Threads_GetTID() { return gpCurrentThread->TID; }
 tPID Threads_GetPID() { return gpCurrentThread->PID; }
 
-int Threads_SetUID(int *Errno, tUID NewUID)
+int Threads_SetUID(tUID NewUID)
 {
        if(Threads_GetUID() != 0) {
-               if(Errno)       *Errno = -EACCES;
+               errno = EACCES;
                return -1;
        }
        
@@ -156,10 +151,10 @@ int Threads_SetUID(int *Errno, tUID NewUID)
        return 0;
 }
 
-int Threads_SetGID(int *Errno, tGID NewGID)
+int Threads_SetGID(tGID NewGID)
 {
        if(Threads_GetUID() != 0) {
-               if(Errno)       *Errno = -EACCES;
+               errno = -EACCES;
                return -1;
        }
        
@@ -167,18 +162,12 @@ int Threads_SetGID(int *Errno, tGID NewGID)
        return 0;
 }
 
-Uint *Threads_GetCfgPtr(int Index)
-{
-//     Log_Debug("Threads", "Index=%i, gpCurrentThread=%p",
-//             Index, gpCurrentThread);
-       if( Index < 0 || Index >= NUM_CFG_ENTRIES )
-               return NULL;
-       if( !gpCurrentThread )
-               return NULL;
-       return &gpCurrentThread->Config[Index];
-}
+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; };
 
-int Threads_WaitTID(int TID, int *Status)
+tTID Threads_WaitTID(int TID, int *Status)
 {
        // Any Child
        if(TID == -1) {
@@ -206,7 +195,7 @@ int Threads_WaitTID(int TID, int *Status)
                if(!thread)     return -1;
                
                us->Next = NULL;
-               us->State = 3;
+               us->Status = THREAD_STAT_WAITING;
                // TODO: Locking
                if(thread->WaitingThreadsEnd)
                {
@@ -219,11 +208,7 @@ int Threads_WaitTID(int TID, int *Status)
                        thread->WaitingThreadsEnd = us;
                }
                
-               while(thread->State != 0)
-               {
-                       pause();
-                       Log_Debug("Threads", "Huh?... state = %i", thread->State);
-               }
+               Threads_WaitEvents( THREAD_EVENT_WAKEUP );
                
                if(Status)      *Status = thread->ExitStatus;
                thread->WaitingThreads = thread->WaitingThreads->Next;
@@ -276,8 +261,8 @@ void Threads_Exit(int TID, int Status)
 
 int Threads_Wake(tThread *Thread)
 {
-       Thread->State = 0;
-       kill( Thread->KernelTID, SIGUSR1 );
+       Thread->Status = THREAD_STAT_ACTIVE;
+       Threads_PostEvent(Thread, THREAD_EVENT_WAKEUP);
        return 0;
 }
 
@@ -310,6 +295,9 @@ int Threads_Fork(void)
        return thread->PID;
 }
 
+// --------------------------------------------------------------------
+// Mutexes 
+// --------------------------------------------------------------------
 int Mutex_Acquire(tMutex *Mutex)
 {
        if(!Mutex->Protector.IsValid) {
@@ -325,6 +313,9 @@ void Mutex_Release(tMutex *Mutex)
        pthread_mutex_unlock( &Mutex->Protector.Mutex );
 }
 
+// --------------------------------------------------------------------
+// Semaphores
+// --------------------------------------------------------------------
 void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name)
 {
        memset(Sem, 0, sizeof(tSemaphore));
@@ -346,35 +337,77 @@ int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd)
        return AmmountToAdd;
 }
 
-#if 0
-void Threads_Sleep()
+// --------------------------------------------------------------------
+// Event handling
+// --------------------------------------------------------------------
+int RWLock_AcquireRead(tRWLock *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
+       if( !Lock->ReaderWaiting ) {
+               Lock->ReaderWaiting = malloc(sizeof(pthread_rwlock_t));
+               pthread_rwlock_init( (void*)Lock->ReaderWaiting, 0 );
        }
-       else {
-               // Just woken up, return
-               return ;
+       pthread_rwlock_rdlock( (void*)Lock->ReaderWaiting );
+       return 0;
+}
+int RWLock_AcquireWrite(tRWLock *Lock)
+{
+       if( !Lock->ReaderWaiting ) {
+               Lock->ReaderWaiting = malloc(sizeof(pthread_rwlock_t));
+               pthread_rwlock_init( (void*)Lock->ReaderWaiting, 0 );
        }
+       pthread_rwlock_wrlock( (void*)Lock->ReaderWaiting );
+       return 0;
 }
+void RWLock_Release(tRWLock *Lock)
+{
+       pthread_rwlock_unlock( (void*)Lock->ReaderWaiting );
+}
+
 
-int SaveState(tState *To)
+// --------------------------------------------------------------------
+// Event handling
+// --------------------------------------------------------------------
+Uint32 Threads_WaitEvents(Uint32 Mask)
 {
-       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));
+       Uint32  rv;
+
+       Log_Debug("Threads", "Mask = %x, ->Events = %x", Mask, gpCurrentThread->Events);        
+
+       gpCurrentThread->WaitMask = Mask;
+       if( !(gpCurrentThread->Events & Mask) )
+       {
+               do {
+                       if( SDL_SemWait( gpCurrentThread->EventSem ) == -1 ) {
+                               Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
+                                       gpCurrentThread, gpCurrentThread->EventSem);
+                               break;
+                       }
+               } while(SDL_SemValue(gpCurrentThread->EventSem));
+               // NOTE: While loop catches multiple event occurances
+               Log_Debug("Threads", "Woken from nap (%i here)", SDL_SemValue(gpCurrentThread->EventSem));
+       }
+       rv = gpCurrentThread->Events & Mask;
+       gpCurrentThread->Events &= ~Mask;
+       gpCurrentThread->WaitMask = -1;
+
+       Log_Debug("Threads", "- rv = %x", rv);
+
+       return rv;
+}
+
+void Threads_PostEvent(tThread *Thread, Uint32 Events)
+{
+       Thread->Events |= Events;
+       Log_Debug("Threads", "Trigger event %x (->Events = %p)", Events, Thread->Events);
+       
+       if( Events == 0 || Thread->WaitMask & Events ) {
+               SDL_SemPost( Thread->EventSem );
+//             Log_Debug("Threads", "Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName);
+       }
+}
+
+void Threads_ClearEvent(Uint32 EventMask)
+{
+       gpCurrentThread->Events &= ~EventMask;
 }
-#endif
 

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