X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=AcessNative%2Facesskernel_src%2Fthreads.c;h=c31c5d0548493e3a24d09d4f821630e0b272f550;hb=9d2ff6cf13e1a0ec5cbdc2773e1a3204e600b2e5;hp=dc4d643aae75b169b491a42b57b72225cf35f4fe;hpb=c84c6acf1e8be4fb6e76ef0f8fd275400be8d5ae;p=tpg%2Facess2.git diff --git a/AcessNative/acesskernel_src/threads.c b/AcessNative/acesskernel_src/threads.c index dc4d643a..c31c5d05 100644 --- a/AcessNative/acesskernel_src/threads.c +++ b/AcessNative/acesskernel_src/threads.c @@ -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 #undef NULL // Remove acess definition #include #include #include +#include +#include +#include + +#undef CLONE_VM // Such a hack +#undef off_t + +// - Native headers #include #include #include #include "/usr/include/signal.h" #include +#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( 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