3 * - Acess kernel emulation on another OS using SDL and UDP
6 * - Thread and process handling
12 #include "../../KernelLand/Kernel/include/semaphore.h"
13 typedef signed long long int time_t;
14 #include "../../Usermode/Libraries/ld-acess.so_src/include_exp/acess/syscall_types.h"
17 #include <threads_int.h>
19 #include "include/threads_glue.h"
21 #define THREAD_EVENT_WAKEUP 0x80000000
24 extern void VFS_CloneHandleList(int PID);
25 extern void VFS_CloneHandlesFromList(int PID, int nFD, int FDs[]);
29 int Threads_Wake(tThread *Thread);
32 tProcess gProcessZero = {
38 tThread gThreadZero = {
39 .Status=THREAD_STAT_ACTIVE,
40 .ThreadName="ThreadZero",
41 .Process = &gProcessZero
43 tThread *gpThreads = &gThreadZero;
44 __thread tThread *gpCurrentThread = &gThreadZero;
45 int giThreads_NextThreadID = 1;
48 tThread *Proc_GetCurThread(void)
50 return gpCurrentThread;
53 void Threads_Dump(void)
56 for( thread = gpThreads; thread; thread = thread->GlobalNext )
58 Log_Log("Threads", "TID %i (%s), PID %i",
59 thread->TID, thread->ThreadName, thread->PID);
60 Log_Log("Threads", "User: %i, Group: %i",
61 thread->UID, thread->GID);
62 Log_Log("Threads", "Kernel Thread ID: %i",
67 void Threads_SetThread(int TID)
70 for( thread = gpThreads; thread; thread = thread->GlobalNext )
72 if( thread->TID == TID ) {
73 gpCurrentThread = thread;
77 Log_Error("Threads", "_SetThread - Thread %i is not on global list", TID);
80 tThread *Threads_GetThread(Uint TID)
83 for( thread = gpThreads; thread; thread = thread->GlobalNext )
85 if( thread->TID == TID ) {
93 * \brief Clone a thread control block (with a different TID)
95 tThread *Threads_CloneTCB(tThread *TemplateThread)
97 tThread *ret = malloc(sizeof(tThread));
99 memcpy(ret, TemplateThread, sizeof(tThread));
101 ret->TID = giThreads_NextThreadID ++;
103 ret->ThreadName = strdup(TemplateThread->ThreadName);
104 Threads_Glue_SemInit( &ret->EventSem, 0 );
106 ret->WaitingThreads = NULL;
107 ret->WaitingThreadsEnd = NULL;
109 // Add to the end of the queue
110 // TODO: Handle concurrency issues
111 ret->GlobalNext = gpThreads;
117 tUID Threads_GetUID() { return gpCurrentThread->UID; }
118 tGID Threads_GetGID() { return gpCurrentThread->GID; }
119 tTID Threads_GetTID() { return gpCurrentThread->TID; }
120 tPID Threads_GetPID() { return gpCurrentThread->PID; }
122 int Threads_SetUID(tUID NewUID)
124 if(Threads_GetUID() != 0) {
129 gpCurrentThread->UID = NewUID;
133 int Threads_SetGID(tGID NewGID)
135 if(Threads_GetUID() != 0) {
140 gpCurrentThread->GID = NewGID;
144 int *Threads_GetErrno(void) { return &gpCurrentThread->_errno; }
145 char **Threads_GetCWD(void) { return &gpCurrentThread->Process->CWD; }
146 char **Threads_GetChroot(void) { return &gpCurrentThread->Process->Chroot; }
147 int *Threads_GetMaxFD(void) { return &gpCurrentThread->Process->MaxFD; };
149 tTID Threads_WaitTID(int TID, int *Status)
153 Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
157 // Any peer/child thread
159 Log_Error("Threads", "TODO: Threads_WaitTID(TID=0) - Any Child/Sibling");
165 Log_Error("Threads", "TODO: Threads_WaitTID(TID<0) - TGID");
172 tThread *thread = Threads_GetThread(TID);
173 tThread *us = gpCurrentThread;
174 if(!thread) return -1;
177 us->Status = THREAD_STAT_WAITING;
179 if(thread->WaitingThreadsEnd)
181 thread->WaitingThreadsEnd->Next = us;
182 thread->WaitingThreadsEnd = us;
186 thread->WaitingThreads = us;
187 thread->WaitingThreadsEnd = us;
190 Threads_WaitEvents( THREAD_EVENT_WAKEUP );
192 if(Status) *Status = thread->ExitStatus;
193 thread->WaitingThreads = thread->WaitingThreads->Next;
202 void Threads_Sleep(void)
204 // TODO: Add to a sleeping queue
208 void Threads_Yield(void)
213 void Threads_Exit(int TID, int Status)
217 // VFS_Handles_Cleanup();
219 gpCurrentThread->ExitStatus = Status;
222 if( gpCurrentThread->Parent )
224 // Wait for the thread to be waited upon
225 while( gpCurrentThread->WaitingThreads == NULL )
226 Threads_Glue_Yield();
230 while( (toWake = gpCurrentThread->WaitingThreads) )
232 Log_Debug("Threads", "Threads_Exit - Waking %p %i '%s'", toWake, toWake->TID, toWake->ThreadName);
234 Threads_Wake(toWake);
236 while(gpCurrentThread->WaitingThreads == toWake)
237 Threads_Glue_Yield();
241 int Threads_Wake(tThread *Thread)
243 Thread->Status = THREAD_STAT_ACTIVE;
244 Threads_PostEvent(Thread, THREAD_EVENT_WAKEUP);
248 int Threads_WakeTID(tTID TID)
251 thread = Threads_GetThread(TID);
252 if( !thread ) return -1;
253 return Threads_Wake(thread);
256 int Threads_CreateRootProcess(void)
258 tThread *thread = Threads_CloneTCB(&gThreadZero);
259 thread->PID = thread->TID;
261 // Handle list is created on first open
266 int Threads_Fork(void)
268 tThread *thread = Threads_CloneTCB(gpCurrentThread);
269 thread->PID = thread->TID;
271 // Duplicate the VFS handles (and nodes) from vfs_handle.c
272 VFS_CloneHandleList(thread->PID);
277 int Threads_Spawn(int nFD, int FDs[], struct s_sys_spawninfo *info)
279 tThread *thread = Threads_CloneTCB(gpCurrentThread);
280 thread->PID = thread->TID;
284 //if( info->flags & SPAWNFLAG_NEWPGID )
285 // thread->PGID = thread->PID;
286 if( info->gid && thread->UID == 0 )
287 thread->GID = info->gid;
288 if( info->uid && thread->UID == 0 ) // last because ->UID is used above
289 thread->UID = info->uid;
292 VFS_CloneHandlesFromList(thread->PID, nFD, FDs);
294 Log_Debug("Threads", "_spawn: %i", thread->PID);
298 // --------------------------------------------------------------------
300 // --------------------------------------------------------------------
301 int Mutex_Acquire(tMutex *Mutex)
303 Threads_Glue_AcquireMutex(&Mutex->Protector.Mutex);
307 void Mutex_Release(tMutex *Mutex)
309 Threads_Glue_ReleaseMutex(&Mutex->Protector.Mutex);
312 // --------------------------------------------------------------------
314 // --------------------------------------------------------------------
315 void Semaphore_Init(tSemaphore *Sem, int InitValue, int MaxValue, const char *Module, const char *Name)
317 memset(Sem, 0, sizeof(tSemaphore));
318 // HACK: Use `Sem->Protector` as space for the semaphore pointer
319 Threads_Glue_SemInit( &Sem->Protector.Mutex, InitValue );
322 int Semaphore_Wait(tSemaphore *Sem, int MaxToTake)
324 return Threads_Glue_SemWait( Sem->Protector.Mutex, MaxToTake );
327 int Semaphore_Signal(tSemaphore *Sem, int AmmountToAdd)
329 return Threads_Glue_SemSignal( Sem->Protector.Mutex, AmmountToAdd );
332 // --------------------------------------------------------------------
334 // --------------------------------------------------------------------
335 Uint32 Threads_WaitEvents(Uint32 Mask)
339 //Log_Debug("Threads", "Mask = %x, ->Events = %x", Mask, gpCurrentThread->Events);
341 gpCurrentThread->WaitMask = Mask;
342 if( !(gpCurrentThread->Events & Mask) )
344 if( Threads_Glue_SemWait(gpCurrentThread->EventSem, INT_MAX) == -1 ) {
345 Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
346 gpCurrentThread, gpCurrentThread->EventSem);
348 //Log_Debug("Threads", "Woken from nap (%i here)", SDL_SemValue(gpCurrentThread->EventSem));
350 rv = gpCurrentThread->Events & Mask;
351 gpCurrentThread->Events &= ~Mask;
352 gpCurrentThread->WaitMask = -1;
354 //Log_Debug("Threads", "- rv = %x", rv);
359 void Threads_PostEvent(tThread *Thread, Uint32 Events)
361 Thread->Events |= Events;
362 // Log_Debug("Threads", "Trigger event %x (->Events = %p) on %p", Events, Thread->Events, Thread);
364 if( Events == 0 || Thread->WaitMask & Events ) {
365 Threads_Glue_SemSignal( Thread->EventSem, 1 );
366 // Log_Debug("Threads", "Waking %p(%i %s)", Thread, Thread->TID, Thread->ThreadName);
370 void Threads_ClearEvent(Uint32 EventMask)
372 gpCurrentThread->Events &= ~EventMask;