#define MIN_PRIORITY 10
// === IMPORTS ===
+extern void User_Signal_Kill(int SigNum);
// === TYPE ===
typedef struct
void Threads_Exit(int TID, int Status);
void Threads_Kill(tThread *Thread, int Status);
void Threads_Yield(void);
+#endif
+void Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock);
+#if 0
void Threads_Sleep(void);
int Threads_Wake(tThread *Thread);
void Threads_AddActive(tThread *Thread);
void Threads_ToggleTrace(int TID);
void Threads_Fault(int Num);
void Threads_SegFault(tVAddr Addr);
+void Threads_PostSignalTo(tThread *Thread, int SignalNum);
+#if 0
+void Threads_PostSignal(int SignalNum);
+void Threads_SignalGroup(tPGID PGID, int SignalNum);
+#endif
+ int Threads_GetPendingSignal(void);
+void Threads_SetSignalHandler(int SignalNum, void *Handler);
+void *Threads_GetSignalHandler(int SignalNum);
#if 0
int Threads_GetPID(void);
int Threads_GetTID(void);
// === GLOBALS ===
// -- Core Thread --
-struct sProcess gProcessZero = {
+tProcess gProcessZero = {
};
// Only used for the core kernel
tThread gThreadZero = {
.Priority = DEFAULT_PRIORITY // Number of tickets
};
// -- Processes --
+tProcess *gAllProcesses = &gProcessZero;
// --- Locks ---
tShortSpinlock glThreadListLock; ///\note NEVER use a heap function while locked
// --- Current State ---
if( Thread->Process->nThreads == 0 )
{
tProcess *proc = Thread->Process;
+
+ // Remove from global process list
+ // TODO: RWLock
+ if(proc->Prev)
+ proc->Prev->Next = proc->Next;
+ else
+ gAllProcesses = proc->Next;
+ if(proc->Next)
+ proc->Next->Prev = proc->Prev;
+
// VFS Cleanup
VFS_CloseAllUserHandles();
// Architecture cleanup
if( IsHeap(oldname) ) free( oldname );
cur->ThreadName = strdup(NewName);
-// Log_Debug("Threads", "Thread renamed to '%s'", NewName);
+ Log_Debug("Threads", "Thread renamed to '%s'", NewName);
return 0;
}
newproc->UID = oldproc->UID;
newproc->GID = oldproc->GID;
newproc->MaxFD = oldproc->MaxFD;
- if( oldproc->CurrentWorkingDir )
- newproc->CurrentWorkingDir = strdup( oldproc->CurrentWorkingDir );
- else
- newproc->CurrentWorkingDir = NULL;
- if( oldproc->RootDir )
- newproc->RootDir = strdup( oldproc->RootDir );
- else
- newproc->RootDir = NULL;
+ newproc->CurrentWorkingDir = oldproc->CurrentWorkingDir ? strdup( oldproc->CurrentWorkingDir ) : NULL;
+ newproc->RootDir = oldproc->RootDir ? strdup( oldproc->RootDir ) : NULL;
newproc->nThreads = 1;
// Reference all handles in the VFS
VFS_ReferenceUserHandles();
+
+ // Add to global list
+ newproc->Prev = NULL;
+ // TODO: RWLock
+ newproc->Next = gAllProcesses;
+ gAllProcesses = newproc;
newproc->FirstThread = new;
new->ProcessNext = NULL;
{
Proc_Reschedule();
if( us->Status == Status )
- Debug("Thread %p(%i %s) rescheduled while in %s state", casTHREAD_STAT[Status]);
+ Debug("Thread %p(%i %s) rescheduled while in %s state for %p",
+ us, us->TID, us->ThreadName,
+ casTHREAD_STAT[Status],
+ __builtin_return_address(0));
}
}
+void Threads_int_Sleep(enum eThreadStatus Status, void *Ptr, int Num, tThread **ListHead, tThread **ListTail, tShortSpinlock *Lock)
+{
+ SHORTLOCK( &glThreadListLock );
+ tThread *us = Threads_RemActive();
+ us->Next = NULL;
+ // - Mark as sleeping
+ us->Status = Status;
+ us->WaitPointer = Ptr;
+ us->RetStatus = Num; // Use RetStatus as a temp variable
+
+ // - Add to waiting
+ if( ListTail ) {
+ if(*ListTail) {
+ (*ListTail)->Next = us;
+ *ListTail = us;
+ }
+ else {
+ *ListHead = us;
+ *ListTail = us;
+ }
+ }
+ else {
+ *ListHead = us;
+ }
+
+ //if( Proc_ThreadSync(us) )
+ // return ;
+ SHORTREL( &glThreadListLock );
+ if( Lock )
+ SHORTLOCK( Lock );
+ Threads_int_WaitForStatusEnd(Status);
+}
+
/**
* \fn void Threads_Sleep(void)
* \brief Take the current process off the run queue
//Threads_Exit( 0, -1 );
}
+
+void Threads_PostSignalTo(tThread *Thread, int SignalNum)
+{
+ ASSERT(Thread);
+ Log_Debug("Threads", "Signalling %i(%s) with %i", Thread->TID, Thread->ThreadName, SignalNum);
+ Thread->PendingSignal = SignalNum;
+ Threads_PostEvent(Thread, THREAD_EVENT_SIGNAL);
+}
+void Threads_PostSignal(int SignalNum)
+{
+ Threads_PostSignalTo( Proc_GetCurThread(), SignalNum );
+}
+
+void Threads_SignalGroup(tPGID PGID, int Signal)
+{
+ for( tProcess *proc = gAllProcesses; proc; proc = proc->Next )
+ {
+ if(proc->PGID == PGID)
+ {
+ Threads_PostSignalTo(proc->FirstThread, Signal);
+ }
+ }
+}
+
+/**
+ */
+int Threads_GetPendingSignal(void)
+{
+ tThread *cur = Proc_GetCurThread();
+
+ // Atomic AND with 0 fetches and clears in one operation
+ int ret = __sync_fetch_and_and( &cur->PendingSignal, 0 );
+ if( ret )
+ {
+ Log_Debug("Threads", "Thread %i(%s) has signal %i pending",
+ cur->TID, cur->ThreadName, ret);
+ }
+ return ret;
+}
+
+/*
+ * \brief Update the current thread's signal handler
+ */
+void Threads_SetSignalHandler(int SignalNum, void *Handler)
+{
+ if( SignalNum <= 0 || SignalNum >= NSIGNALS )
+ return ;
+ if( !MM_IsUser(Handler) )
+ return ;
+ Proc_GetCurThread()->Process->SignalHandlers[SignalNum] = Handler;
+}
+
+/**
+ * \brief Gets the registered (or default, if none set) handler for a signal.
+ * \return Handler function pointer, OR NULL if no signal to be ignored
+ */
+void *Threads_GetSignalHandler(int SignalNum)
+{
+ // TODO: Core dump
+ void *User_Signal_Core = User_Signal_Kill;
+
+ if( SignalNum <= 0 || SignalNum >= NSIGNALS )
+ return NULL;
+ void *ret = Proc_GetCurThread()->Process->SignalHandlers[SignalNum];
+ if( !ret || (SignalNum == SIGKILL || SignalNum == SIGSTOP) )
+ {
+ // Defaults
+ switch(SignalNum)
+ {
+ case SIGHUP:
+ case SIGINT:
+ ret = User_Signal_Kill;
+ break;
+ case SIGQUIT:
+ case SIGILL:
+ case SIGABRT:
+ case SIGFPE:
+ ret = User_Signal_Core;
+ break;
+ case SIGKILL:
+ ret = User_Signal_Kill;
+ break;
+ case SIGSEGV:
+ ret = User_Signal_Core;
+ break;
+ case SIGPIPE:
+ case SIGALRM:
+ case SIGTERM:
+ ret = User_Signal_Kill;
+ break;
+ default:
+ ret = NULL;
+ break;
+ }
+ }
+ Log_Debug("Threads", "Handler %p for signal %i", ret, SignalNum);
+ return ret;
+}
+
// --- Process Structure Access Functions ---
tPGID Threads_GetPGID(void)
{
void Threads_int_DumpThread(tThread *thread)
{
+ if( !thread ) {
+ Log(" %p NULL", thread);
+ return ;
+ }
+ if( !CheckMem(thread, sizeof(tThread)) ) {
+ Log(" %p INVAL", thread);
+ return ;
+ }
+ tPID pid = (thread->Process ? thread->Process->PID : -1);
+ const char *statstr = (thread->Status < sizeof(casTHREAD_STAT)/sizeof(casTHREAD_STAT[0])
+ ? casTHREAD_STAT[thread->Status] : "");
Log(" %p %i (%i) - %s (CPU %i) - %i (%s)",
- thread, thread->TID, thread->Process->PID, thread->ThreadName, thread->CurCPU,
- thread->Status, casTHREAD_STAT[thread->Status]
+ thread, thread->TID, pid, thread->ThreadName, thread->CurCPU,
+ thread->Status, statstr
);
switch(thread->Status)
{
((tSemaphore*)thread->WaitPointer)->Name
);
break;
+ case THREAD_STAT_EVENTSLEEP:
+ // TODO: Event mask
+ break;
case THREAD_STAT_ZOMBIE:
Log(" Return Status: %i", thread->RetStatus);
break;
*/
void Threads_Dump(void)
{
- tThread *thread;
-
Log("--- Thread Dump ---");
Threads_DumpActive();
Log("All Threads:");
- for(thread=gAllThreads;thread;thread=thread->GlobalNext)
+ for(tThread *thread = gAllThreads; thread; thread = thread->GlobalNext)
{
Threads_int_DumpThread(thread);
}