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"
22 #define THREAD_EVENT_WAKEUP 0x80000000
25 extern void VFS_CloneHandleList(int PID);
26 extern void VFS_CloneHandlesFromList(int PID, int nFD, int FDs[]);
27 extern void VFS_ClearHandles(int PID);
31 int Threads_Wake(tThread *Thread);
34 tProcess gProcessZero = {
40 tThread gThreadZero = {
41 .Status=THREAD_STAT_ACTIVE,
42 .ThreadName="ThreadZero",
43 .Process = &gProcessZero
45 tThread *gpThreads = &gThreadZero;
46 __thread tThread *gpCurrentThread = &gThreadZero;
47 int giThreads_NextThreadID = 1;
50 tThread *Proc_GetCurThread(void)
52 return gpCurrentThread;
55 void Threads_Dump(void)
57 for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext )
59 Log_Log("Threads", "TID %i (%s), PID %i",
60 thread->TID, thread->ThreadName, thread->Process->PID);
61 Log_Log("Threads", "User: %i, Group: %i",
62 thread->Process->UID, thread->Process->GID);
63 Log_Log("Threads", "Kernel Thread ID: %i",
68 void Threads_SetThread(int TID, void *Client)
70 for( tThread *thread = gpThreads; thread; thread = thread->GlobalNext )
72 if( thread->TID == TID ) {
73 gpCurrentThread = thread;
74 thread->ClientPtr = Client;
78 Log_Error("Threads", "_SetThread - Thread %i is not on global list", TID);
81 tThread *Threads_GetThread(Uint TID)
83 for( tThread *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, bool bNewProcess)
97 tThread *ret = malloc(sizeof(tThread));
98 memcpy(ret, TemplateThread, sizeof(tThread));
100 ret->TID = giThreads_NextThreadID ++;
102 ret->ThreadName = strdup(TemplateThread->ThreadName);
103 Threads_Glue_SemInit( &ret->EventSem, 0 );
105 ret->WaitingThreads = NULL;
106 ret->WaitingThreadsEnd = NULL;
110 tProcess *proc = malloc( sizeof(tProcess) );
111 memcpy(proc, ret->Process, sizeof(tProcess));
113 proc->CWD = strdup(proc->CWD);
114 proc->Chroot = strdup(proc->Chroot);
116 proc->PID = ret->TID;
121 ret->Process->nThreads ++;
123 // Add to the end of the queue
124 // TODO: Handle concurrency issues
125 ret->GlobalNext = gpThreads;
131 void Threads_int_Destroy(tThread *Thread)
133 // Clear WaitingThreads
135 Threads_Glue_SemDestroy(Thread->EventSem);
136 free(Thread->ThreadName);
137 Thread->Process->nThreads --;
140 void Threads_Terminate(void)
142 tThread *us = gpCurrentThread;
143 tProcess *proc = us->Process;
145 if( us->TID == proc->PID )
147 // If we're the process leader, then tear down the entire process
148 VFS_ClearHandles(proc->PID);
149 tThread **next_ptr = &gpThreads;
150 for( tThread *thread = gpThreads; thread; thread = *next_ptr )
152 if( thread->Process == proc ) {
153 Threads_int_Destroy(thread);
156 next_ptr = &thread->Next;
162 // Just a lowly thread, remove from process
163 Threads_int_Destroy(us);
166 if( proc->nThreads == 0 )
174 tUID Threads_GetUID() { return gpCurrentThread->Process->UID; }
175 tGID Threads_GetGID() { return gpCurrentThread->Process->GID; }
176 tTID Threads_GetTID() { return gpCurrentThread->TID; }
177 tPID Threads_GetPID() { return gpCurrentThread->Process->PID; }
179 int Threads_SetUID(tUID NewUID)
181 if(Threads_GetUID() != 0) {
186 gpCurrentThread->Process->UID = NewUID;
190 int Threads_SetGID(tGID NewGID)
192 if(Threads_GetUID() != 0) {
197 gpCurrentThread->Process->GID = NewGID;
201 int *Threads_GetErrno(void) { return &gpCurrentThread->_errno; }
202 static tProcess *proc(tProcess *Proc) { return Proc ? Proc : gpCurrentThread->Process; }
203 char **Threads_GetCWD (tProcess *Proc) { return &proc(Proc)->CWD; }
204 char **Threads_GetChroot(tProcess *Proc) { return &proc(Proc)->Chroot; }
205 int *Threads_GetMaxFD (tProcess *Proc) { return &proc(Proc)->MaxFD; };
207 tTID Threads_WaitTID(int TID, int *Status)
211 Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
215 // Any peer/child thread
217 Log_Error("Threads", "TODO: Threads_WaitTID(TID=0) - Any Child/Sibling");
223 Log_Error("Threads", "TODO: Threads_WaitTID(TID<0) - TGID");
230 tThread *thread = Threads_GetThread(TID);
231 tThread *us = gpCurrentThread;
232 if(!thread) return -1;
235 us->Status = THREAD_STAT_WAITING;
237 if(thread->WaitingThreadsEnd)
239 thread->WaitingThreadsEnd->Next = us;
240 thread->WaitingThreadsEnd = us;
244 thread->WaitingThreads = us;
245 thread->WaitingThreadsEnd = us;
248 Threads_WaitEvents( THREAD_EVENT_WAKEUP );
250 if(Status) *Status = thread->RetStatus;
251 thread->WaitingThreads = thread->WaitingThreads->Next;
260 void Threads_Exit(int TID, int Status)
264 // VFS_Handles_Cleanup();
266 gpCurrentThread->RetStatus = Status;
269 if( gpCurrentThread->Parent )
271 // Wait for the thread to be waited upon
272 while( gpCurrentThread->WaitingThreads == NULL )
273 Threads_Glue_Yield();
277 while( (toWake = gpCurrentThread->WaitingThreads) )
279 Log_Debug("Threads", "Threads_Exit - Waking %p %i '%s'", toWake, toWake->TID, toWake->ThreadName);
281 Threads_Wake(toWake);
283 while(gpCurrentThread->WaitingThreads == toWake)
284 Threads_Glue_Yield();
290 gpCurrentThread->Status = THREAD_STAT_SLEEPING;
291 Threads_int_WaitForStatusEnd(THREAD_STAT_SLEEPING);
294 int Threads_Wake(tThread *Thread)
296 Thread->Status = THREAD_STAT_ACTIVE;
297 Threads_PostEvent(Thread, THREAD_EVENT_WAKEUP);
301 int Threads_WakeTID(tTID TID)
304 thread = Threads_GetThread(TID);
305 if( !thread ) return -1;
306 return Threads_Wake(thread);
309 int Threads_CreateRootProcess(void)
311 tThread *thread = Threads_CloneTCB(&gThreadZero, true);
313 // Handle list is created on first open
315 return thread->Process->PID;
318 int Threads_Fork(void)
320 tThread *thread = Threads_CloneTCB(gpCurrentThread, true);
322 // Duplicate the VFS handles (and nodes) from vfs_handle.c
323 VFS_CloneHandleList(thread->Process->PID);
325 return thread->Process->PID;
328 int Threads_Spawn(int nFD, int FDs[], struct s_sys_spawninfo *info)
330 tThread *thread = Threads_CloneTCB(gpCurrentThread, true);
334 //if( info->flags & SPAWNFLAG_NEWPGID )
335 // thread->PGID = thread->PID;
336 if( thread->Process->UID == 0 )
339 thread->Process->GID = info->gid;
341 thread->Process->UID = info->uid;
345 VFS_CloneHandlesFromList(thread->Process->PID, nFD, FDs);
347 return thread->Process->PID;
352 void Threads_int_Terminate(tThread *Thread)
354 Thread->RetStatus = -1;
355 Threads_AddActive(Thread);
358 void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
360 tThread *us = Proc_GetCurThread();
361 ASSERT(Status != THREAD_STAT_ACTIVE);
362 ASSERT(Status != THREAD_STAT_DEAD);
363 LOG("%i(%s) - %i", us->TID, us->ThreadName, Status);
364 while( us->Status == Status )
366 if( Threads_Glue_SemWait(gpCurrentThread->EventSem, INT_MAX) == -1 ) {
367 Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
368 gpCurrentThread, gpCurrentThread->EventSem);
371 if( us->Status == Status )
372 Log_Warning("Threads", "Thread %p(%i %s) rescheduled while in %s state",
373 us, us->TID, us->ThreadName, casTHREAD_STAT[Status]);
377 int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
379 tThread *us = Proc_GetCurThread();
381 // - Mark as sleeping
383 us->WaitPointer = Ptr;
384 us->RetStatus = Num; // Use RetStatus as a temp variable
389 (*ListTail)->Next = us;
403 Threads_int_WaitForStatusEnd(Status);
404 us->WaitPointer = NULL;
405 return us->RetStatus;
408 void Threads_AddActive(tThread *Thread)
410 LOG("%i(%s)", Thread->TID, Thread->ThreadName);
411 Thread->Status = THREAD_STAT_ACTIVE;
412 Threads_Glue_SemSignal(Thread->EventSem, 1);
415 // --------------------------------------------------------------------
417 // --------------------------------------------------------------------
418 void Threads_PostSignal(int SigNum)
420 Log_Error("Threads", "TODO: %s", __func__);
422 void Threads_SignalGroup(tPGID PGID, int SignalNum)
424 Log_Error("Threads", "TODO: %s", __func__);