2 * Acess2 libnative (Kernel Simulation Library)
3 * - By John Hodge (thePowersGang)
11 #include <threads_int.h>
15 void Threads_int_Init(void) __attribute__((constructor(101)));
16 tThread *Threads_int_CreateTCB(tThread *Parent);
19 tThread *gThreads_List;
20 tThread __thread *lpThreads_This;
21 int giThreads_NextTID = 1;
22 tShortSpinlock glThreadListLock;
25 void Threads_int_Init(void)
27 if( !lpThreads_This ) {
28 lpThreads_This = Threads_int_CreateTCB(NULL);
29 Threads_SetName("ThreadZero");
33 tThread *Proc_GetCurThread(void)
35 return lpThreads_This;
38 tUID Threads_GetUID(void) { return 0; }
39 tGID Threads_GetGID(void) { return 0; }
41 tTID Threads_GetTID(void) { return lpThreads_This ? lpThreads_This->TID : 0; }
43 static inline tProcess* getproc(tProcess *Process) {
44 return (Process ? Process : lpThreads_This->Process);
46 int *Threads_GetMaxFD(tProcess *Process) { return &getproc(Process)->MaxFDs; }
47 char **Threads_GetCWD(tProcess *Process) { return &getproc(Process)->CWD; }
48 char **Threads_GetChroot(tProcess *Process) { return &getproc(Process)->Chroot; }
49 void **Threads_GetHandlesPtr(void) { return &lpThreads_This->Process->Handles; }
51 void Threads_Yield(void)
53 Log_KernelPanic("Threads", "Threads_Yield DEFINITELY shouldn't be used (%p)",
54 __builtin_return_address(0));
57 void Threads_Sleep(void)
59 Log_Warning("Threads", "Threads_Sleep shouldn't be used");
62 int Threads_SetName(const char *Name)
67 if( lpThreads_This->ThreadName )
68 free(lpThreads_This->ThreadName);
69 lpThreads_This->ThreadName = strdup(Name);
74 int *Threads_GetErrno(void) __attribute__ ((weak));
76 int *Threads_GetErrno(void)
82 tThread *Threads_RemActive(void)
84 return lpThreads_This;
87 void Threads_AddActive(tThread *Thread)
89 Thread->Status = THREAD_STAT_ACTIVE;
90 // Increment state-change semaphore
91 LOG("Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName);
92 Threads_int_SemSignal(Thread->WaitSemaphore);
95 struct sProcess *Threads_int_CreateProcess(void)
97 struct sProcess *ret = calloc(sizeof(struct sProcess), 1);
104 tThread *Threads_int_CreateTCB(tThread *Parent)
106 tThread *ret = calloc( sizeof(tThread), 1 );
107 ret->TID = giThreads_NextTID ++;
108 ret->WaitSemaphore = Threads_int_SemCreate();
109 //ret->Protector = Threads_int_MutexCreate();
113 ret->Process = Threads_int_CreateProcess();
116 ret->Process = Parent->Process;
118 ret->ProcNext = ret->Process->Threads;
119 ret->Process->Threads = ret;
121 ret->Next = gThreads_List;
127 struct sThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
129 if( !Threads_int_ThreadingEnabled() )
131 Log_Error("Threads", "Multithreading is disabled in this build");
136 tThread *ret = Threads_int_CreateTCB(lpThreads_This);
138 ret->SpawnData = Data;
139 Threads_int_CreateThread(ret);
144 void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
146 tThread *us = Proc_GetCurThread();
147 assert(Status != THREAD_STAT_ACTIVE);
148 assert(Status != THREAD_STAT_DEAD);
149 LOG("%i(%s) - %i", us->TID, us->ThreadName, Status);
150 while( us->Status == Status )
152 Threads_int_SemWaitAll(us->WaitSemaphore);
153 if( us->Status == Status )
154 Log_Warning("Threads", "Thread %p(%i %s) rescheduled while in %s state",
155 us, us->TID, us->ThreadName, casTHREAD_STAT[Status]);
157 LOG("%p(%i %s) Awake", us, us->TID, us->ThreadName);
160 int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
162 tThread *us = Proc_GetCurThread();
164 // - Mark as sleeping
166 us->WaitPointer = Ptr;
167 us->RetStatus = Num; // Use RetStatus as a temp variable
172 (*ListTail)->Next = us;
180 us->Next = *ListHead;
190 Threads_int_WaitForStatusEnd(Status);
191 us->WaitPointer = NULL;
192 return us->RetStatus;