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 int *Threads_GetMaxFD(void) { return &lpThreads_This->Process->MaxFDs; }
44 char **Threads_GetCWD(void) { return &lpThreads_This->Process->CWD; }
45 char **Threads_GetChroot(void) { return &lpThreads_This->Process->Chroot; }
46 void **Threads_GetHandlesPtr(void) { return &lpThreads_This->Process->Handles; }
48 void Threads_Yield(void)
50 Log_KernelPanic("Threads", "Threads_Yield DEFINITELY shouldn't be used (%p)",
51 __builtin_return_address(0));
54 void Threads_Sleep(void)
56 Log_Warning("Threads", "Threads_Sleep shouldn't be used");
59 int Threads_SetName(const char *Name)
64 if( lpThreads_This->ThreadName )
65 free(lpThreads_This->ThreadName);
66 lpThreads_This->ThreadName = strdup(Name);
71 int *Threads_GetErrno(void) __attribute__ ((weak));
73 int *Threads_GetErrno(void)
79 tThread *Threads_RemActive(void)
81 return lpThreads_This;
84 void Threads_AddActive(tThread *Thread)
86 Thread->Status = THREAD_STAT_ACTIVE;
87 // Increment state-change semaphore
88 LOG("Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName);
89 Threads_int_SemSignal(Thread->WaitSemaphore);
92 struct sProcess *Threads_int_CreateProcess(void)
94 struct sProcess *ret = calloc(sizeof(struct sProcess), 1);
101 tThread *Threads_int_CreateTCB(tThread *Parent)
103 tThread *ret = calloc( sizeof(tThread), 1 );
104 ret->TID = giThreads_NextTID ++;
105 ret->WaitSemaphore = Threads_int_SemCreate();
106 //ret->Protector = Threads_int_MutexCreate();
110 ret->Process = Threads_int_CreateProcess();
113 ret->Process = Parent->Process;
115 ret->ProcNext = ret->Process->Threads;
116 ret->Process->Threads = ret;
118 ret->Next = gThreads_List;
124 struct sThread *Proc_SpawnWorker(void (*Fcn)(void*), void *Data)
126 if( !Threads_int_ThreadingEnabled() )
128 Log_Error("Threads", "Multithreading is disabled in this build");
133 tThread *ret = Threads_int_CreateTCB(lpThreads_This);
135 ret->SpawnData = Data;
136 Threads_int_CreateThread(ret);
141 void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
143 tThread *us = Proc_GetCurThread();
144 assert(Status != THREAD_STAT_ACTIVE);
145 assert(Status != THREAD_STAT_DEAD);
146 LOG("%i(%s) - %i", us->TID, us->ThreadName, Status);
147 while( us->Status == Status )
149 Threads_int_SemWaitAll(us->WaitSemaphore);
150 if( us->Status == Status )
151 Log_Warning("Threads", "Thread %p(%i %s) rescheduled while in %s state",
152 us, us->TID, us->ThreadName, casTHREAD_STAT[Status]);
154 LOG("%p(%i %s) Awake", us, us->TID, us->ThreadName);
157 int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
159 tThread *us = Proc_GetCurThread();
161 // - Mark as sleeping
163 us->WaitPointer = Ptr;
164 us->RetStatus = Num; // Use RetStatus as a temp variable
169 (*ListTail)->Next = us;
177 us->Next = *ListHead;
187 Threads_int_WaitForStatusEnd(Status);
188 us->WaitPointer = NULL;
189 return us->RetStatus;