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 char **Threads_GetCWD(void) { return &gpCurrentThread->Process->CWD; }
203 char **Threads_GetChroot(void) { return &gpCurrentThread->Process->Chroot; }
204 int *Threads_GetMaxFD(void) { return &gpCurrentThread->Process->MaxFD; };
206 tTID Threads_WaitTID(int TID, int *Status)
210 Log_Error("Threads", "TODO: Threads_WaitTID(TID=-1) - Any Child");
214 // Any peer/child thread
216 Log_Error("Threads", "TODO: Threads_WaitTID(TID=0) - Any Child/Sibling");
222 Log_Error("Threads", "TODO: Threads_WaitTID(TID<0) - TGID");
229 tThread *thread = Threads_GetThread(TID);
230 tThread *us = gpCurrentThread;
231 if(!thread) return -1;
234 us->Status = THREAD_STAT_WAITING;
236 if(thread->WaitingThreadsEnd)
238 thread->WaitingThreadsEnd->Next = us;
239 thread->WaitingThreadsEnd = us;
243 thread->WaitingThreads = us;
244 thread->WaitingThreadsEnd = us;
247 Threads_WaitEvents( THREAD_EVENT_WAKEUP );
249 if(Status) *Status = thread->RetStatus;
250 thread->WaitingThreads = thread->WaitingThreads->Next;
259 void Threads_Exit(int TID, int Status)
263 // VFS_Handles_Cleanup();
265 gpCurrentThread->RetStatus = Status;
268 if( gpCurrentThread->Parent )
270 // Wait for the thread to be waited upon
271 while( gpCurrentThread->WaitingThreads == NULL )
272 Threads_Glue_Yield();
276 while( (toWake = gpCurrentThread->WaitingThreads) )
278 Log_Debug("Threads", "Threads_Exit - Waking %p %i '%s'", toWake, toWake->TID, toWake->ThreadName);
280 Threads_Wake(toWake);
282 while(gpCurrentThread->WaitingThreads == toWake)
283 Threads_Glue_Yield();
289 gpCurrentThread->Status = THREAD_STAT_SLEEPING;
290 Threads_int_WaitForStatusEnd(THREAD_STAT_SLEEPING);
293 int Threads_Wake(tThread *Thread)
295 Thread->Status = THREAD_STAT_ACTIVE;
296 Threads_PostEvent(Thread, THREAD_EVENT_WAKEUP);
300 int Threads_WakeTID(tTID TID)
303 thread = Threads_GetThread(TID);
304 if( !thread ) return -1;
305 return Threads_Wake(thread);
308 int Threads_CreateRootProcess(void)
310 tThread *thread = Threads_CloneTCB(&gThreadZero, true);
312 // Handle list is created on first open
314 return thread->Process->PID;
317 int Threads_Fork(void)
319 tThread *thread = Threads_CloneTCB(gpCurrentThread, true);
321 // Duplicate the VFS handles (and nodes) from vfs_handle.c
322 VFS_CloneHandleList(thread->Process->PID);
324 return thread->Process->PID;
327 int Threads_Spawn(int nFD, int FDs[], struct s_sys_spawninfo *info)
329 tThread *thread = Threads_CloneTCB(gpCurrentThread, true);
333 //if( info->flags & SPAWNFLAG_NEWPGID )
334 // thread->PGID = thread->PID;
335 if( thread->Process->UID == 0 )
338 thread->Process->GID = info->gid;
340 thread->Process->UID = info->uid;
344 VFS_CloneHandlesFromList(thread->Process->PID, nFD, FDs);
346 return thread->Process->PID;
351 void Threads_int_Terminate(tThread *Thread)
353 Thread->RetStatus = -1;
354 Threads_AddActive(Thread);
357 void Threads_int_WaitForStatusEnd(enum eThreadStatus Status)
359 tThread *us = Proc_GetCurThread();
360 ASSERT(Status != THREAD_STAT_ACTIVE);
361 ASSERT(Status != THREAD_STAT_DEAD);
362 LOG("%i(%s) - %i", us->TID, us->ThreadName, Status);
363 while( us->Status == Status )
365 if( Threads_Glue_SemWait(gpCurrentThread->EventSem, INT_MAX) == -1 ) {
366 Log_Warning("Threads", "Wait on eventsem of %p, %p failed",
367 gpCurrentThread, gpCurrentThread->EventSem);
370 if( us->Status == Status )
371 Log_Warning("Threads", "Thread %p(%i %s) rescheduled while in %s state",
372 us, us->TID, us->ThreadName, casTHREAD_STAT[Status]);
376 int Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
378 tThread *us = Proc_GetCurThread();
380 // - Mark as sleeping
382 us->WaitPointer = Ptr;
383 us->RetStatus = Num; // Use RetStatus as a temp variable
388 (*ListTail)->Next = us;
402 Threads_int_WaitForStatusEnd(Status);
403 us->WaitPointer = NULL;
404 return us->RetStatus;
407 void Threads_AddActive(tThread *Thread)
409 LOG("%i(%s)", Thread->TID, Thread->ThreadName);
410 Thread->Status = THREAD_STAT_ACTIVE;
411 Threads_Glue_SemSignal(Thread->EventSem, 1);
414 // --------------------------------------------------------------------
416 // --------------------------------------------------------------------
417 void Threads_PostSignal(int SigNum)
419 Log_Error("Threads", "TODO: %s", __func__);
421 void Threads_SignalGroup(tPGID PGID, int SignalNum)
423 Log_Error("Threads", "TODO: %s", __func__);