mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	thread: moved threading calls to the Kernel namespace
This commit is contained in:
		
							parent
							
								
									0012802456
								
							
						
					
					
						commit
						75c6d2a8fa
					
				
					 4 changed files with 117 additions and 103 deletions
				
			
		|  | @ -132,11 +132,11 @@ Object* ObjectPool::CreateByIDType(int type) { | |||
| } | ||||
| 
 | ||||
| void Init() { | ||||
|     __KernelThreadingInit(); | ||||
|     Kernel::ThreadingInit(); | ||||
| } | ||||
| 
 | ||||
| void Shutdown() { | ||||
|     __KernelThreadingShutdown(); | ||||
|     Kernel::ThreadingShutdown(); | ||||
| } | ||||
| 
 | ||||
| } // namespace
 | ||||
|  | @ -147,7 +147,7 @@ bool __KernelLoadExec(u32 entry_point) { | |||
|     Core::g_app_core->SetPC(entry_point); | ||||
| 
 | ||||
|     // 0x30 is the typical main thread priority I've seen used so far
 | ||||
|     Handle thread_id = __KernelSetupMainThread(0x30); | ||||
|     Handle thread_id = Kernel::SetupMainThread(0x30); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
|  |  | |||
|  | @ -19,7 +19,7 @@ | |||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/thread.h" | ||||
| 
 | ||||
| // Enums
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| enum ThreadStatus { | ||||
|     THREADSTATUS_RUNNING        = 1, | ||||
|  | @ -81,33 +81,32 @@ std::vector<Handle> g_thread_queue; | |||
| Common::ThreadQueueList<Handle> g_thread_ready_queue; | ||||
| 
 | ||||
| Handle g_current_thread_handle; | ||||
| 
 | ||||
| Thread* g_current_thread; | ||||
| 
 | ||||
| 
 | ||||
| /// Gets the current thread
 | ||||
| inline Thread* __GetCurrentThread() { | ||||
|     return g_current_thread; | ||||
| } | ||||
| 
 | ||||
| /// Sets the current thread
 | ||||
| inline void __SetCurrentThread(Thread* t) { | ||||
|     g_current_thread = t; | ||||
|     g_current_thread_handle = t->GetHandle(); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /// Saves the current CPU context
 | ||||
| void __KernelSaveContext(ThreadContext& ctx) { | ||||
| void __SaveContext(ThreadContext& ctx) { | ||||
|     Core::g_app_core->SaveContext(ctx); | ||||
| } | ||||
| 
 | ||||
| /// Loads a CPU context
 | ||||
| void __KernelLoadContext(const ThreadContext& ctx) { | ||||
| void __LoadContext(const ThreadContext& ctx) { | ||||
|     Core::g_app_core->LoadContext(ctx); | ||||
| } | ||||
| 
 | ||||
| /// Resets a thread
 | ||||
| void __KernelResetThread(Thread* t, s32 lowest_priority) { | ||||
| void __ResetThread(Thread* t, s32 lowest_priority) { | ||||
|     memset(&t->context, 0, sizeof(ThreadContext)); | ||||
| 
 | ||||
|     t->context.pc = t->entry_point; | ||||
|  | @ -121,7 +120,7 @@ void __KernelResetThread(Thread* t, s32 lowest_priority) { | |||
| } | ||||
| 
 | ||||
| /// Change a thread to "ready" state
 | ||||
| void __KernelChangeReadyState(Thread* t, bool ready) { | ||||
| void __ChangeReadyState(Thread* t, bool ready) { | ||||
|     Handle handle = t->GetHandle(); | ||||
|     if (t->IsReady()) { | ||||
|         if (!ready) { | ||||
|  | @ -138,11 +137,11 @@ void __KernelChangeReadyState(Thread* t, bool ready) { | |||
| } | ||||
| 
 | ||||
| /// Changes a threads state
 | ||||
| void __KernelChangeThreadState(Thread* t, ThreadStatus new_status) { | ||||
| void __ChangeThreadState(Thread* t, ThreadStatus new_status) { | ||||
|     if (!t || t->status == new_status) { | ||||
|         return; | ||||
|     } | ||||
|     __KernelChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); | ||||
|     __ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); | ||||
|     t->status = new_status; | ||||
|      | ||||
|     if (new_status == THREADSTATUS_WAIT) { | ||||
|  | @ -153,16 +152,75 @@ void __KernelChangeThreadState(Thread* t, ThreadStatus new_status) { | |||
| } | ||||
| 
 | ||||
| /// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields)
 | ||||
| void __KernelCallThread(Thread* t) { | ||||
| void __CallThread(Thread* t) { | ||||
|     // Stop waiting
 | ||||
|     if (t->wait_type != WAITTYPE_NONE) { | ||||
|         t->wait_type = WAITTYPE_NONE; | ||||
|     } | ||||
|     __KernelChangeThreadState(t, THREADSTATUS_READY); | ||||
|     __ChangeThreadState(t, THREADSTATUS_READY); | ||||
| } | ||||
| 
 | ||||
| /// Switches CPU context to that of the specified thread
 | ||||
| void __SwitchContext(Thread* t, const char* reason) { | ||||
|     Thread* cur = __GetCurrentThread(); | ||||
|      | ||||
|     // Save context for current thread
 | ||||
|     if (cur) { | ||||
|         __SaveContext(cur->context); | ||||
|          | ||||
|         if (cur->IsRunning()) { | ||||
|             __ChangeReadyState(cur, true); | ||||
|         } | ||||
|     } | ||||
|     // Load context of new thread
 | ||||
|     if (t) { | ||||
|         __SetCurrentThread(t); | ||||
|         __ChangeReadyState(t, false); | ||||
|         t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY; | ||||
|         t->wait_type = WAITTYPE_NONE; | ||||
|         __LoadContext(t->context); | ||||
|     } else { | ||||
|         __SetCurrentThread(NULL); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Gets the next thread that is ready to be run by priority
 | ||||
| Thread* __NextThread() { | ||||
|     Handle next; | ||||
|     Thread* cur = __GetCurrentThread(); | ||||
|      | ||||
|     if (cur && cur->IsRunning()) { | ||||
|         next = g_thread_ready_queue.pop_first_better(cur->current_priority); | ||||
|     } else  { | ||||
|         next = g_thread_ready_queue.pop_first(); | ||||
|     } | ||||
|     if (next < 0) { | ||||
|         return NULL; | ||||
|     } | ||||
|     return Kernel::g_object_pool.GetFast<Thread>(next); | ||||
| } | ||||
| 
 | ||||
| /// Resumes a thread from waiting by marking it as "ready"
 | ||||
| void __ResumeThreadFromWait(Handle handle) { | ||||
|     u32 error; | ||||
|     Thread* t = Kernel::g_object_pool.Get<Thread>(handle, error); | ||||
|     if (t) { | ||||
|         t->status &= ~THREADSTATUS_WAIT; | ||||
|         if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { | ||||
|             __ChangeReadyState(t, true); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Puts a thread in the wait state for the given type/reason
 | ||||
| void __WaitCurThread(WaitType wait_type, const char* reason) { | ||||
|     Thread* t = __GetCurrentThread(); | ||||
|     t->wait_type = wait_type; | ||||
|     __ChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND))); | ||||
| } | ||||
| 
 | ||||
| /// Creates a new thread
 | ||||
| Thread* __KernelCreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority, | ||||
| Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority, | ||||
|     s32 processor_id, u32 stack_top, int stack_size) { | ||||
| 
 | ||||
|     Thread* t = new Thread; | ||||
|  | @ -187,31 +245,31 @@ Thread* __KernelCreateThread(Handle& handle, const char* name, u32 entry_point, | |||
| } | ||||
| 
 | ||||
| /// Creates a new thread - wrapper for external user
 | ||||
| Handle __KernelCreateThread(const char* name, u32 entry_point, s32 priority, s32 processor_id, | ||||
| Handle CreateThread(const char* name, u32 entry_point, s32 priority, s32 processor_id, | ||||
|     u32 stack_top, int stack_size) { | ||||
|     if (name == NULL) { | ||||
|         ERROR_LOG(KERNEL, "__KernelCreateThread(): NULL name"); | ||||
|         ERROR_LOG(KERNEL, "CreateThread(): NULL name"); | ||||
|         return -1; | ||||
|     } | ||||
|     if ((u32)stack_size < 0x200) { | ||||
|         ERROR_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid stack_size=0x%08X", name,  | ||||
|         ERROR_LOG(KERNEL, "CreateThread(name=%s): invalid stack_size=0x%08X", name,  | ||||
|             stack_size); | ||||
|         return -1; | ||||
|     } | ||||
|     if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { | ||||
|         s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); | ||||
|         WARN_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid priority=0x%08X, clamping to %08X", | ||||
|         WARN_LOG(KERNEL, "CreateThread(name=%s): invalid priority=0x%08X, clamping to %08X", | ||||
|             name, priority, new_priority); | ||||
|         // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
 | ||||
|         // validity of this
 | ||||
|         priority = new_priority; | ||||
|     } | ||||
|     if (!Memory::GetPointer(entry_point)) { | ||||
|         ERROR_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid entry %08x", name, entry_point); | ||||
|         ERROR_LOG(KERNEL, "CreateThread(name=%s): invalid entry %08x", name, entry_point); | ||||
|         return -1; | ||||
|     } | ||||
|     Handle handle; | ||||
|     Thread* t = __KernelCreateThread(handle, name, entry_point, priority, processor_id, stack_top,  | ||||
|     Thread* t = CreateThread(handle, name, entry_point, priority, processor_id, stack_top,  | ||||
|         stack_size); | ||||
| 
 | ||||
|     HLE::EatCycles(32000); | ||||
|  | @ -220,114 +278,62 @@ Handle __KernelCreateThread(const char* name, u32 entry_point, s32 priority, s32 | |||
|     // Technically, this should not eat all at once, and reschedule in the middle, but that's hard.
 | ||||
|     HLE::ReSchedule("thread created"); | ||||
| 
 | ||||
|     __KernelCallThread(t); | ||||
|     __CallThread(t); | ||||
|      | ||||
|     return handle; | ||||
| } | ||||
| 
 | ||||
| /// Switches CPU context to that of the specified thread
 | ||||
| void __KernelSwitchContext(Thread* t, const char* reason) { | ||||
|     Thread* cur = __GetCurrentThread(); | ||||
|      | ||||
|     // Save context for current thread
 | ||||
|     if (cur) { | ||||
|         __KernelSaveContext(cur->context); | ||||
|          | ||||
|         if (cur->IsRunning()) { | ||||
|             __KernelChangeReadyState(cur, true); | ||||
|         } | ||||
|     } | ||||
|     // Load context of new thread
 | ||||
|     if (t) { | ||||
|         __SetCurrentThread(t); | ||||
|         __KernelChangeReadyState(t, false); | ||||
|         t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY; | ||||
|         t->wait_type = WAITTYPE_NONE; | ||||
|         __KernelLoadContext(t->context); | ||||
|     } else { | ||||
|         __SetCurrentThread(NULL); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Gets the next thread that is ready to be run by priority
 | ||||
| Thread* __KernelNextThread() { | ||||
|     Handle next; | ||||
|     Thread* cur = __GetCurrentThread(); | ||||
|      | ||||
|     if (cur && cur->IsRunning()) { | ||||
|         next = g_thread_ready_queue.pop_first_better(cur->current_priority); | ||||
|     } else  { | ||||
|         next = g_thread_ready_queue.pop_first(); | ||||
|     } | ||||
|     if (next < 0) { | ||||
|         return NULL; | ||||
|     } | ||||
|     return Kernel::g_object_pool.GetFast<Thread>(next); | ||||
| /// Gets the current thread
 | ||||
| Handle GetCurrentThread() { | ||||
|     return __GetCurrentThread()->GetHandle(); | ||||
| } | ||||
| 
 | ||||
| /// Sets up the primary application thread
 | ||||
| Handle __KernelSetupMainThread(s32 priority, int stack_size) { | ||||
| Handle SetupMainThread(s32 priority, int stack_size) { | ||||
|     Handle handle; | ||||
|      | ||||
|     // Initialize new "main" thread
 | ||||
|     Thread* t = __KernelCreateThread(handle, "main", Core::g_app_core->GetPC(), priority,  | ||||
|     Thread* t = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority,  | ||||
|         THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); | ||||
|      | ||||
|     __KernelResetThread(t, 0); | ||||
|     __ResetThread(t, 0); | ||||
|      | ||||
|     // If running another thread already, set it to "ready" state
 | ||||
|     Thread* cur = __GetCurrentThread(); | ||||
|     if (cur && cur->IsRunning()) { | ||||
|         __KernelChangeReadyState(cur, true); | ||||
|         __ChangeReadyState(cur, true); | ||||
|     } | ||||
|      | ||||
|     // Run new "main" thread
 | ||||
|     __SetCurrentThread(t); | ||||
|     t->status = THREADSTATUS_RUNNING; | ||||
|     __KernelLoadContext(t->context); | ||||
|     __LoadContext(t->context); | ||||
| 
 | ||||
|     return handle; | ||||
| } | ||||
| 
 | ||||
| /// Resumes a thread from waiting by marking it as "ready"
 | ||||
| void __KernelResumeThreadFromWait(Handle handle) { | ||||
|     u32 error; | ||||
|     Thread* t = Kernel::g_object_pool.Get<Thread>(handle, error); | ||||
|     if (t) { | ||||
|         t->status &= ~THREADSTATUS_WAIT; | ||||
|         if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) { | ||||
|             __KernelChangeReadyState(t, true); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| /// Puts a thread in the wait state for the given type/reason
 | ||||
| void __KernelWaitCurThread(WaitType wait_type, const char* reason) { | ||||
|     Thread* t = __GetCurrentThread(); | ||||
|     t->wait_type = wait_type; | ||||
|     __KernelChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND))); | ||||
| } | ||||
| 
 | ||||
| /// Reschedules to the next available thread (call after current thread is suspended)
 | ||||
| void __KernelReschedule(const char* reason) { | ||||
|     Thread* next = __KernelNextThread(); | ||||
| void Reschedule(const char* reason) { | ||||
|     Thread* next = __NextThread(); | ||||
|     if (next > 0) { | ||||
|         __KernelSwitchContext(next, reason); | ||||
|         __SwitchContext(next, reason); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| /// Put current thread in a wait state - on WaitSynchronization
 | ||||
| void __KernelWaitThread_Synchronization() { | ||||
| void WaitThread_Synchronization() { | ||||
|     // TODO(bunnei): Just a placeholder function for now... FixMe
 | ||||
|     __KernelWaitCurThread(WAITTYPE_SYNCH, "waitSynchronization called"); | ||||
|     __WaitCurThread(WAITTYPE_SYNCH, "waitSynchronization called"); | ||||
| } | ||||
| 
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| void __KernelThreadingInit() { | ||||
| void ThreadingInit() { | ||||
| } | ||||
| 
 | ||||
| void __KernelThreadingShutdown() { | ||||
| void ThreadingShutdown() { | ||||
| } | ||||
| 
 | ||||
| } // namespace
 | ||||
|  |  | |||
|  | @ -7,8 +7,6 @@ | |||
| #include "common/common_types.h" | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| 
 | ||||
| class Thread; | ||||
| 
 | ||||
| enum ThreadPriority { | ||||
|     THREADPRIO_HIGHEST      = 0, | ||||
|     THREADPRIO_DEFAULT      = 16, | ||||
|  | @ -21,18 +19,28 @@ enum ThreadProcessorId { | |||
|     THREADPROCESSORID_ALL   = 0xFFFFFFFC, | ||||
| }; | ||||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| /// Creates a new thread - wrapper for external user
 | ||||
| Handle __KernelCreateThread(const char* name, u32 entry_point, s32 priority,  | ||||
|     s32 processor_id, u32 stack_top, int stack_size=Kernel::DEFAULT_STACK_SIZE); | ||||
| Handle CreateThread(const char* name, u32 entry_point, s32 priority, s32 processor_id, | ||||
|     u32 stack_top, int stack_size=Kernel::DEFAULT_STACK_SIZE); | ||||
| 
 | ||||
| /// Sets up the primary application thread
 | ||||
| Handle __KernelSetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); | ||||
| Handle SetupMainThread(s32 priority, int stack_size=Kernel::DEFAULT_STACK_SIZE); | ||||
| 
 | ||||
| /// Reschedules to the next available thread (call after current thread is suspended)
 | ||||
| void __KernelReschedule(const char* reason); | ||||
| void Reschedule(const char* reason); | ||||
| 
 | ||||
| void __KernelThreadingInit(); | ||||
| void __KernelThreadingShutdown(); | ||||
| /// Gets the current thread
 | ||||
| Handle GetCurrentThread(); | ||||
| 
 | ||||
| /// Put current thread in a wait state - on WaitSynchronization
 | ||||
| void __KernelWaitThread_Synchronization(); | ||||
| void WaitThread_Synchronization(); | ||||
| 
 | ||||
| /// Initialize threading
 | ||||
| void ThreadingInit(); | ||||
| 
 | ||||
| /// Shutdown threading
 | ||||
| void ThreadingShutdown(); | ||||
| 
 | ||||
| } // namespace
 | ||||
|  |  | |||
|  | @ -123,7 +123,7 @@ Result WaitSynchronizationN(void* _out, void* _handles, u32 handle_count, u32 wa | |||
|     for (u32 i = 0; i < handle_count; i++) { | ||||
|         DEBUG_LOG(SVC, "\thandle[%d]=0x%08X", i, handles[i]); | ||||
|     } | ||||
|     __KernelReschedule("WaitSynchronizationN"); | ||||
|     Kernel::Reschedule("WaitSynchronizationN"); | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
|  | @ -175,7 +175,7 @@ Result CreateThread(void* thread, u32 priority, u32 entry_point, u32 arg, u32 st | |||
|         "threadpriority=0x%08X, processorid=0x%08X", entry_point, name.c_str(), arg, stack_top, | ||||
|         priority, processor_id); | ||||
| 
 | ||||
|     Handle handle = __KernelCreateThread(name.c_str(), entry_point, priority, processor_id,  | ||||
|     Handle handle = Kernel::CreateThread(name.c_str(), entry_point, priority, processor_id,  | ||||
|         stack_top); | ||||
|     Core::g_app_core->SetReg(1, 0xFEEDDEAF); | ||||
|      | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue