Usermode/libaxwin4 - Handle demarshal failure
[tpg/acess2.git] / Tools / nativelib / threads.c
index 501954d..f804473 100644 (file)
@@ -5,43 +5,53 @@
  * threads.c
  * - Threads handling
  */
+#define DEBUG  0
 #include <acess.h>
 #include <threads.h>
+#include <threads_int.h>
+#include <mutex.h>
 
-// === CODE ===
-tThread *Proc_GetCurThread(void)
-{
-       return NULL;
-}
+// === PROTOTYPES ===
+void   Threads_int_Init(void)  __attribute__((constructor(101)));
+tThread        *Threads_int_CreateTCB(tThread *Parent);
 
-void Threads_PostEvent(tThread *Thread, Uint32 Events)
-{
-       
-}
+// === GLOBALS ===
+tThread        *gThreads_List;
+tThread __thread       *lpThreads_This;
+ int   giThreads_NextTID = 1;
+tShortSpinlock glThreadListLock;
 
-Uint32 Threads_WaitEvents(Uint32 Events)
+// === CODE ===
+void Threads_int_Init(void)
 {
-       Log_KernelPanic("Threads", "Can't use _WaitEvents in DiskTool");
-       return 0;
+       if( !lpThreads_This ) {
+               lpThreads_This = Threads_int_CreateTCB(NULL);
+               Threads_SetName("ThreadZero");
+       }
 }
 
-void Threads_ClearEvent(Uint32 Mask)
+tThread *Proc_GetCurThread(void)
 {
-       
+       return lpThreads_This;
 }
 
 tUID Threads_GetUID(void) { return 0; }
 tGID Threads_GetGID(void) { return 0; }
 
-tTID Threads_GetTID(void) { return 0; }
+tTID Threads_GetTID(void) { return lpThreads_This ? lpThreads_This->TID : 0; }
 
-int *Threads_GetMaxFD(void) { static int max_fd=32; return &max_fd; }
-char **Threads_GetCWD(void) { static char *cwd; return &cwd; }
-char **Threads_GetChroot(void) { static char *chroot; return &chroot; }
+static inline tProcess* getproc(tProcess *Process) {
+       return (Process ? Process : lpThreads_This->Process);
+}
+int *Threads_GetMaxFD(tProcess *Process)       { return &getproc(Process)->MaxFDs;  }
+char **Threads_GetCWD(tProcess *Process)        { return &getproc(Process)->CWD;     }
+char **Threads_GetChroot(tProcess *Process)     { return &getproc(Process)->Chroot;  }
+void **Threads_GetHandlesPtr(void) { return &lpThreads_This->Process->Handles; }
 
 void Threads_Yield(void)
 {
-       Log_Warning("Threads", "Threads_Yield DEFINITELY shouldn't be used");
+       Log_KernelPanic("Threads", "Threads_Yield DEFINITELY shouldn't be used (%p)",
+               __builtin_return_address(0));
 }
 
 void Threads_Sleep(void)
@@ -51,21 +61,134 @@ void Threads_Sleep(void)
 
 int Threads_SetName(const char *Name)
 {
-       Log_Notice("Threads", "TODO: Threads_SetName('%s')", Name);
+       if( !lpThreads_This )
+               return 0;
+
+       if( lpThreads_This->ThreadName )
+               free(lpThreads_This->ThreadName);
+       lpThreads_This->ThreadName = strdup(Name);
+
        return 0;
 }
 
 int *Threads_GetErrno(void) __attribute__ ((weak));
 
-int *Threads_GetErrno(void)// __attribute__ ((weak))
+int *Threads_GetErrno(void)
 {
        static int a_errno;
        return &a_errno;
 }
 
+tThread *Threads_RemActive(void)
+{
+       return lpThreads_This;
+}
+
+void Threads_AddActive(tThread *Thread)
+{
+       Thread->Status = THREAD_STAT_ACTIVE;
+       // Increment state-change semaphore
+       LOG("Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName);
+       Threads_int_SemSignal(Thread->WaitSemaphore);
+}
+
+struct sProcess *Threads_int_CreateProcess(void)
+{
+       struct sProcess *ret = calloc(sizeof(struct sProcess), 1);
+
+       ret->MaxFDs = 32;
+
+       return ret;
+}
+
+tThread *Threads_int_CreateTCB(tThread *Parent)
+{
+       tThread *ret = calloc( sizeof(tThread), 1 );
+       ret->TID = giThreads_NextTID ++;
+       ret->WaitSemaphore = Threads_int_SemCreate();
+       //ret->Protector = Threads_int_MutexCreate();
+
+       if( !Parent )
+       {
+               ret->Process = Threads_int_CreateProcess();
+       }
+       else
+               ret->Process = Parent->Process;
+
+       ret->ProcNext = ret->Process->Threads;
+       ret->Process->Threads = ret;
+
+       ret->Next = gThreads_List;
+       gThreads_List = ret;
+       
+       return ret;
+}
+
 struct sThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
 {
-       Log_Error("Threads", "TODO - Use pthreads to impliment Proc_SpawnWorker");
-       return NULL;
+       if( !Threads_int_ThreadingEnabled() )
+       {
+               Log_Error("Threads", "Multithreading is disabled in this build");
+               return NULL;
+       }
+       else
+       {
+               tThread *ret = Threads_int_CreateTCB(lpThreads_This);
+               ret->SpawnFcn = Fcn;
+               ret->SpawnData = Data;
+               Threads_int_CreateThread(ret);
+               return ret;
+       }
+}
+
+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 )
+       {
+               Threads_int_SemWaitAll(us->WaitSemaphore);
+               if( us->Status == Status )
+                       Log_Warning("Threads", "Thread %p(%i %s) rescheduled while in %s state",
+                               us, us->TID, us->ThreadName, casTHREAD_STAT[Status]);
+       }
+       LOG("%p(%i %s) Awake", us, us->TID, us->ThreadName);
+}
+
+int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
+{
+       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 if(ListHead) {
+               us->Next = *ListHead;
+               *ListHead = us;
+       }
+       else {
+               // nothing
+       }
+       
+       if( Lock ) {
+               SHORTREL( Lock );
+       }
+       Threads_int_WaitForStatusEnd(Status);
+       us->WaitPointer = NULL;
+       return us->RetStatus;
 }
 

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