X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=AcessNative%2Facesskernel_src%2Fthreads.c;h=74d85fc60c078c54bfdc59fae473d26be74fd0f5;hb=13078002b01ee4f63eb2001d2ef479a2a006ea32;hp=9de6140bc6cdae8670f6f2ffb2b68bdc6ecd3553;hpb=57e4db716b3e7db0be336abd9f256962e3b19aa3;p=tpg%2Facess2.git diff --git a/AcessNative/acesskernel_src/threads.c b/AcessNative/acesskernel_src/threads.c index 9de6140b..74d85fc6 100644 --- a/AcessNative/acesskernel_src/threads.c +++ b/AcessNative/acesskernel_src/threads.c @@ -5,44 +5,28 @@ * threads.c * - Thread and process handling */ -#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) - -#define off_t _acess_off_t +#define DEBUG 1 #include -#undef NULL // Remove acess definition #include #include -#include +#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 #include #include - -#undef CLONE_VM // Such a hack -#undef off_t - -// - Native headers -#include -#include -#include -#include "/usr/include/signal.h" -#include +#include +#include "include/threads_glue.h" +#include #define THREAD_EVENT_WAKEUP 0x80000000 // === IMPORTS === -void VFS_CloneHandleList(int PID); +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 -{ - void *CurState; - Uint SP, BP, IP; -} tState; -#endif - // === PROTOTYPES === int Threads_Wake(tThread *Thread); @@ -70,25 +54,24 @@ tThread *Proc_GetCurThread(void) void Threads_Dump(void) { - tThread *thread; - for( thread = gpThreads; thread; thread = thread->GlobalNext ) + for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext ) { Log_Log("Threads", "TID %i (%s), PID %i", - thread->TID, thread->ThreadName, thread->PID); + thread->TID, thread->ThreadName, thread->Process->PID); Log_Log("Threads", "User: %i, Group: %i", - thread->UID, thread->GID); + thread->Process->UID, thread->Process->GID); Log_Log("Threads", "Kernel Thread ID: %i", thread->KernelTID); } } -void Threads_SetThread(int TID) +void Threads_SetThread(int TID, void *Client) { - tThread *thread; - for( thread = gpThreads; thread; thread = thread->GlobalNext ) + for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext ) { if( thread->TID == TID ) { gpCurrentThread = thread; + thread->ClientPtr = Client; return ; } } @@ -97,8 +80,7 @@ void Threads_SetThread(int TID) tThread *Threads_GetThread(Uint TID) { - tThread *thread; - for( thread = gpThreads; thread; thread = thread->GlobalNext ) + for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext ) { if( thread->TID == TID ) { return thread; @@ -110,23 +92,34 @@ tThread *Threads_GetThread(Uint TID) /** * \brief Clone a thread control block (with a different TID) */ -tThread *Threads_CloneTCB(tThread *TemplateThread) +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); - ret->EventSem = SDL_CreateSemaphore(0); - if( !ret->EventSem ) { - Log_Warning("Threads", "Semaphore creation failed - %s", SDL_GetError()); - } + Threads_Glue_SemInit( &ret->EventSem, 0 ); ret->WaitingThreads = NULL; ret->WaitingThreadsEnd = NULL; - + + 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; + } + + ret->Process->nThreads ++; + // Add to the end of the queue // TODO: Handle concurrency issues ret->GlobalNext = gpThreads; @@ -135,10 +128,53 @@ tThread *Threads_CloneTCB(tThread *TemplateThread) return ret; } -tUID Threads_GetUID() { return gpCurrentThread->UID; } -tGID Threads_GetGID() { return gpCurrentThread->GID; } +void Threads_int_Destroy(tThread *Thread) +{ + // Clear WaitingThreads + + Threads_Glue_SemDestroy(Thread->EventSem); + free(Thread->ThreadName); + Thread->Process->nThreads --; +} + +void Threads_Terminate(void) +{ + tThread *us = gpCurrentThread; + tProcess *proc = us->Process; + + if( us->TID == proc->PID ) + { + // 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); + } +} + +tUID Threads_GetUID() { return gpCurrentThread->Process->UID; } +tGID Threads_GetGID() { return gpCurrentThread->Process->GID; } tTID Threads_GetTID() { return gpCurrentThread->TID; } -tPID Threads_GetPID() { return gpCurrentThread->PID; } +tPID Threads_GetPID() { return gpCurrentThread->Process->PID; } int Threads_SetUID(tUID NewUID) { @@ -147,7 +183,7 @@ int Threads_SetUID(tUID NewUID) return -1; } - gpCurrentThread->UID = NewUID; + gpCurrentThread->Process->UID = NewUID; return 0; } @@ -158,14 +194,15 @@ int Threads_SetGID(tGID NewGID) return -1; } - gpCurrentThread->GID = NewGID; + gpCurrentThread->Process->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; }; +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) { @@ -188,8 +225,8 @@ tTID Threads_WaitTID(int TID, int *Status) } // Specific Thread - if(TID > 0) { - + if(TID > 0) + { tThread *thread = Threads_GetThread(TID); tThread *us = gpCurrentThread; if(!thread) return -1; @@ -210,7 +247,7 @@ tTID Threads_WaitTID(int TID, int *Status) Threads_WaitEvents( THREAD_EVENT_WAKEUP ); - if(Status) *Status = thread->ExitStatus; + if(Status) *Status = thread->RetStatus; thread->WaitingThreads = thread->WaitingThreads->Next; us->Next = NULL; @@ -220,31 +257,20 @@ tTID Threads_WaitTID(int TID, int *Status) 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; + gpCurrentThread->RetStatus = Status; #if 1 if( gpCurrentThread->Parent ) { // Wait for the thread to be waited upon while( gpCurrentThread->WaitingThreads == NULL ) - SDL_Delay(10); + Threads_Glue_Yield(); } #endif @@ -255,10 +281,16 @@ void Threads_Exit(int TID, int Status) Threads_Wake(toWake); while(gpCurrentThread->WaitingThreads == toWake) - SDL_Delay(10); + Threads_Glue_Yield(); } } +void Threads_Sleep() +{ + gpCurrentThread->Status = THREAD_STAT_SLEEPING; + Threads_int_WaitForStatusEnd(THREAD_STAT_SLEEPING); +} + int Threads_Wake(tThread *Thread) { Thread->Status = THREAD_STAT_ACTIVE; @@ -276,138 +308,119 @@ int Threads_WakeTID(tTID TID) int Threads_CreateRootProcess(void) { - tThread *thread = Threads_CloneTCB(&gThreadZero); - thread->PID = thread->TID; + tThread *thread = Threads_CloneTCB(&gThreadZero, true); // Handle list is created on first open - return thread->PID; + return thread->Process->PID; } int Threads_Fork(void) { - tThread *thread = Threads_CloneTCB(gpCurrentThread); - thread->PID = thread->TID; + tThread *thread = Threads_CloneTCB(gpCurrentThread, true); + // Duplicate the VFS handles (and nodes) from vfs_handle.c + VFS_CloneHandleList(thread->Process->PID); - VFS_CloneHandleList(thread->PID); - - return thread->PID; + return thread->Process->PID; } -// -------------------------------------------------------------------- -// Mutexes -// -------------------------------------------------------------------- -int Mutex_Acquire(tMutex *Mutex) +int Threads_Spawn(int nFD, int FDs[], struct s_sys_spawninfo *info) { - if(!Mutex->Protector.IsValid) { - pthread_mutex_init( &Mutex->Protector.Mutex, NULL ); - Mutex->Protector.IsValid = 1; + 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 ); - return 0; -} - -void Mutex_Release(tMutex *Mutex) -{ - pthread_mutex_unlock( &Mutex->Protector.Mutex ); -} + + VFS_CloneHandlesFromList(thread->Process->PID, nFD, FDs); -// -------------------------------------------------------------------- -// Semaphores -// -------------------------------------------------------------------- -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); + return thread->Process->PID; } -int Semaphore_Wait(tSemaphore *Sem, int MaxToTake) +// ---- +// ---- +void Threads_int_Terminate(tThread *Thread) { - SDL_SemWait( *(void**)(&Sem->Protector) ); - return 1; + Thread->RetStatus = -1; + Threads_AddActive(Thread); } -int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd) +void Threads_int_WaitForStatusEnd(enum eThreadStatus Status) { - int i; - for( i = 0; i < AmmountToAdd; i ++ ) - SDL_SemPost( *(void**)(&Sem->Protector) ); - return AmmountToAdd; + 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]); + } } -// -------------------------------------------------------------------- -// Event handling -// -------------------------------------------------------------------- -int RWLock_AcquireRead(tRWLock *Lock) +int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock) { - if( !Lock->ReaderWaiting ) { - Lock->ReaderWaiting = malloc(sizeof(pthread_rwlock_t)); - pthread_rwlock_init( (void*)Lock->ReaderWaiting, 0 ); + 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; } - 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 ); + else { + *ListHead = us; } - pthread_rwlock_wrlock( (void*)Lock->ReaderWaiting ); - return 0; + + if( Lock ) { + SHORTREL( Lock ); + } + Threads_int_WaitForStatusEnd(Status); + us->WaitPointer = NULL; + return us->RetStatus; } -void RWLock_Release(tRWLock *Lock) + +void Threads_AddActive(tThread *Thread) { - pthread_rwlock_unlock( (void*)Lock->ReaderWaiting ); + LOG("%i(%s)", Thread->TID, Thread->ThreadName); + Thread->Status = THREAD_STAT_ACTIVE; + Threads_Glue_SemSignal(Thread->EventSem, 1); } - // -------------------------------------------------------------------- -// Event handling +// Signals // -------------------------------------------------------------------- -Uint32 Threads_WaitEvents(Uint32 Mask) +void Threads_PostSignal(int SigNum) { - 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; + Log_Error("Threads", "TODO: %s", __func__); } - -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) +void Threads_SignalGroup(tPGID PGID, int SignalNum) { - gpCurrentThread->Events &= ~EventMask; + Log_Error("Threads", "TODO: %s", __func__); }