+/**
+ * \brief Wake a thread given the TID
+ * \param TID Thread ID to wake
+ * \return Boolean Faulure (errno)
+ */
+int Threads_WakeTID(tTID TID)
+{
+ tThread *thread = Threads_GetThread(TID);
+ int ret;
+ if(!thread)
+ return -ENOENT;
+ ret = Threads_Wake( thread );
+ //Log_Debug("Threads", "TID %i woke %i (%p)", Threads_GetTID(), TID, thread);
+ return ret;
+}
+
+void Threads_ToggleTrace(int TID)
+{
+ tThread *thread = Threads_GetThread(TID);
+ if(!thread) return ;
+ thread->bInstrTrace = !thread->bInstrTrace;
+}
+
+/**
+ * \brief Adds a thread to the active queue
+ */
+void Threads_AddActive(tThread *Thread)
+{
+ SHORTLOCK( &glThreadListLock );
+
+ if( Thread->Status == THREAD_STAT_ACTIVE ) {
+ tThread *cur = Proc_GetCurThread();
+ Log_Warning("Threads", "WTF, %p CPU%i %p (%i %s) is adding %p (%i %s) when it is active",
+ __builtin_return_address(0),
+ GetCPUNum(), cur, cur->TID, cur->ThreadName, Thread, Thread->TID, Thread->ThreadName);
+ SHORTREL( &glThreadListLock );
+ return ;
+ }
+
+ // Set state
+ Thread->Status = THREAD_STAT_ACTIVE;
+// Thread->CurCPU = -1;
+ // Add to active list
+ {
+ #if SCHEDULER_TYPE == SCHED_RR_PRI
+ tThreadList *list = &gaActiveThreads[Thread->Priority];
+ #else
+ tThreadList *list = &gActiveThreads;
+ #endif
+ Threads_int_AddToList( list, Thread );
+ }
+
+ // Update bookkeeping
+ giNumActiveThreads ++;
+
+ #if SCHEDULER_TYPE == SCHED_LOTTERY
+ {
+ int delta;
+ // Only change the ticket count if the thread is un-scheduled
+ if(Thread->CurCPU != -1)
+ delta = 0;
+ else
+ delta = caiTICKET_COUNTS[ Thread->Priority ];
+
+ giFreeTickets += delta;
+ # if DEBUG_TRACE_TICKETS
+ Log("CPU%i %p (%i %s) added, new giFreeTickets = %i [+%i]",
+ GetCPUNum(), Thread, Thread->TID, Thread->ThreadName,
+ giFreeTickets, delta
+ );
+ # endif
+ }
+ #endif
+
+ SHORTREL( &glThreadListLock );
+}
+
+/**
+ * \brief Removes the current thread from the active queue
+ * \warning This should ONLY be called with the lock held
+ * \return Current thread pointer
+ */
+tThread *Threads_RemActive(void)
+{
+ #if 0
+ tThread *ret = Proc_GetCurThread();
+
+ if( !IS_LOCKED(&glThreadListLock) ) {
+ Log_KernelPanic("Threads", "Threads_RemActive called without lock held");
+ return NULL;
+ }
+
+ // Delete from active queue
+ #if SCHEDULER_TYPE == SCHED_RR_PRI
+ if( !Threads_int_DelFromQueue(&gaActiveThreads[ret->Priority], ret) )
+ #else
+ if( !Threads_int_DelFromQueue(&gActiveThreads, ret) )
+ #endif
+ {
+ Log_Warning("Threads", "Current thread %p(%i %s) is not on active queue",
+ ret, ret->TID, ret->ThreadName
+ );
+ return NULL;
+ }
+
+ ret->Next = NULL;
+ ret->Remaining = 0;
+
+ giNumActiveThreads --;
+ // no need to decrement tickets, scheduler did it for us
+
+ #if SCHEDULER_TYPE == SCHED_LOTTERY && DEBUG_TRACE_TICKETS
+ Log("CPU%i %p (%i %s) removed, giFreeTickets = %i [nc]",
+ GetCPUNum(), ret, ret->TID, ret->ThreadName, giFreeTickets);
+ #endif
+
+ return ret;
+ #else
+ return Proc_GetCurThread();
+ #endif
+}
+
+/**
+ * \fn void Threads_SetFaultHandler(Uint Handler)
+ * \brief Sets the signal handler for a signal
+ */
+void Threads_SetFaultHandler(Uint Handler)
+{
+ //Log_Debug("Threads", "Threads_SetFaultHandler: Handler = %p", Handler);
+ Proc_GetCurThread()->FaultHandler = Handler;
+}
+
+/**
+ * \fn void Threads_Fault(int Num)
+ * \brief Calls a fault handler
+ */
+void Threads_Fault(int Num)
+{
+ tThread *thread = Proc_GetCurThread();
+
+ if(!thread) return ;
+
+ Log_Log("Threads", "Threads_Fault: thread->FaultHandler = %p", thread->FaultHandler);
+
+ switch(thread->FaultHandler)
+ {
+ case 0: // Panic?
+ Threads_Kill(thread, -1);
+ HALT();
+ return ;
+ case 1: // Dump Core?
+ Threads_Kill(thread, -1);
+ HALT();
+ return ;
+ }
+
+ // Double Fault? Oh, F**k
+ if(thread->CurFaultNum != 0) {
+ Log_Warning("Threads", "Threads_Fault: Double fault on %i", thread->TID);
+ Threads_Kill(thread, -1); // For now, just kill
+ HALT();
+ }
+
+ thread->CurFaultNum = Num;
+
+ Proc_CallFaultHandler(thread);
+}
+
+/**
+ * \fn void Threads_SegFault(tVAddr Addr)
+ * \brief Called when a Segment Fault occurs
+ */
+void Threads_SegFault(tVAddr Addr)
+{
+ tThread *cur = Proc_GetCurThread();
+ cur->bInstrTrace = 0;
+ Log_Warning("Threads", "Thread #%i committed a segfault at address %p", cur->TID, Addr);
+ MM_DumpTables(0, USER_MAX);
+ Threads_Fault( 1 );
+ //Threads_Exit( 0, -1 );
+}
+