mirror of
				https://git.suyu.dev/suyu/suyu
				synced 2025-10-31 07:59:02 -05:00 
			
		
		
		
	core: Implement multicore support.
This commit is contained in:
		| @@ -485,22 +485,28 @@ static void ExitProcess() { | ||||
|  | ||||
|     Core::CurrentProcess()->status = ProcessStatus::Exited; | ||||
|  | ||||
|     // Stop all the process threads that are currently waiting for objects. | ||||
|     auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList(); | ||||
|     for (auto& thread : thread_list) { | ||||
|         if (thread->owner_process != Core::CurrentProcess()) | ||||
|             continue; | ||||
|     auto stop_threads = [](const std::vector<SharedPtr<Thread>>& thread_list) { | ||||
|         for (auto& thread : thread_list) { | ||||
|             if (thread->owner_process != Core::CurrentProcess()) | ||||
|                 continue; | ||||
|  | ||||
|         if (thread == GetCurrentThread()) | ||||
|             continue; | ||||
|             if (thread == GetCurrentThread()) | ||||
|                 continue; | ||||
|  | ||||
|         // TODO(Subv): When are the other running/ready threads terminated? | ||||
|         ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY || | ||||
|                        thread->status == THREADSTATUS_WAIT_SYNCH_ALL, | ||||
|                    "Exiting processes with non-waiting threads is currently unimplemented"); | ||||
|             // TODO(Subv): When are the other running/ready threads terminated? | ||||
|             ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY || | ||||
|                            thread->status == THREADSTATUS_WAIT_SYNCH_ALL, | ||||
|                        "Exiting processes with non-waiting threads is currently unimplemented"); | ||||
|  | ||||
|         thread->Stop(); | ||||
|     } | ||||
|             thread->Stop(); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     auto& system = Core::System::GetInstance(); | ||||
|     stop_threads(system.Scheduler(0)->GetThreadList()); | ||||
|     stop_threads(system.Scheduler(1)->GetThreadList()); | ||||
|     stop_threads(system.Scheduler(2)->GetThreadList()); | ||||
|     stop_threads(system.Scheduler(3)->GetThreadList()); | ||||
|  | ||||
|     // Kill the current thread | ||||
|     GetCurrentThread()->Stop(); | ||||
| @@ -530,14 +536,9 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V | ||||
|  | ||||
|     switch (processor_id) { | ||||
|     case THREADPROCESSORID_0: | ||||
|         break; | ||||
|     case THREADPROCESSORID_1: | ||||
|     case THREADPROCESSORID_2: | ||||
|     case THREADPROCESSORID_3: | ||||
|         // TODO(bunnei): Implement support for other processor IDs | ||||
|         NGLOG_ERROR(Kernel_SVC, | ||||
|                     "Newly created thread must run in another thread ({}), unimplemented.", | ||||
|                     processor_id); | ||||
|         break; | ||||
|     default: | ||||
|         ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id); | ||||
| @@ -576,7 +577,7 @@ static ResultCode StartThread(Handle thread_handle) { | ||||
|  | ||||
| /// Called when a thread exits | ||||
| static void ExitThread() { | ||||
|     NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CPU().GetPC()); | ||||
|     NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CurrentArmInterface().GetPC()); | ||||
|  | ||||
|     ExitCurrentThread(); | ||||
|     Core::System::GetInstance().PrepareReschedule(); | ||||
| @@ -588,7 +589,7 @@ static void SleepThread(s64 nanoseconds) { | ||||
|  | ||||
|     // Don't attempt to yield execution if there are no available threads to run, | ||||
|     // this way we avoid a useless reschedule to the idle thread. | ||||
|     if (nanoseconds == 0 && !Core::System::GetInstance().Scheduler().HaveReadyThreads()) | ||||
|     if (nanoseconds == 0 && !Core::System::GetInstance().CurrentScheduler().HaveReadyThreads()) | ||||
|         return; | ||||
|  | ||||
|     // Sleep current thread and check for next thread to schedule | ||||
| @@ -634,7 +635,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target | ||||
|                 condition_variable_addr, target); | ||||
|  | ||||
|     u32 processed = 0; | ||||
|     auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList(); | ||||
|     auto& thread_list = Core::System::GetInstance().CurrentScheduler().GetThreadList(); | ||||
|  | ||||
|     for (auto& thread : thread_list) { | ||||
|         if (thread->condvar_wait_address != condition_variable_addr) | ||||
|   | ||||
| @@ -13,14 +13,14 @@ | ||||
|  | ||||
| namespace Kernel { | ||||
|  | ||||
| #define PARAM(n) Core::CPU().GetReg(n) | ||||
| #define PARAM(n) Core::CurrentArmInterface().GetReg(n) | ||||
|  | ||||
| /** | ||||
|  * HLE a function return from the current ARM userland process | ||||
|  * @param res Result to return | ||||
|  */ | ||||
| static inline void FuncReturn(u64 res) { | ||||
|     Core::CPU().SetReg(0, res); | ||||
|     Core::CurrentArmInterface().SetReg(0, res); | ||||
| } | ||||
|  | ||||
| //////////////////////////////////////////////////////////////////////////////////////////////////// | ||||
| @@ -45,7 +45,7 @@ template <ResultCode func(u32*, u32)> | ||||
| void SvcWrap() { | ||||
|     u32 param_1 = 0; | ||||
|     u32 retval = func(¶m_1, (u32)PARAM(1)).raw; | ||||
|     Core::CPU().SetReg(1, param_1); | ||||
|     Core::CurrentArmInterface().SetReg(1, param_1); | ||||
|     FuncReturn(retval); | ||||
| } | ||||
|  | ||||
| @@ -53,7 +53,7 @@ template <ResultCode func(u32*, u64)> | ||||
| void SvcWrap() { | ||||
|     u32 param_1 = 0; | ||||
|     u32 retval = func(¶m_1, PARAM(1)).raw; | ||||
|     Core::CPU().SetReg(1, param_1); | ||||
|     Core::CurrentArmInterface().SetReg(1, param_1); | ||||
|     FuncReturn(retval); | ||||
| } | ||||
|  | ||||
| @@ -66,7 +66,7 @@ template <ResultCode func(u64*, u64)> | ||||
| void SvcWrap() { | ||||
|     u64 param_1 = 0; | ||||
|     u32 retval = func(¶m_1, PARAM(1)).raw; | ||||
|     Core::CPU().SetReg(1, param_1); | ||||
|     Core::CurrentArmInterface().SetReg(1, param_1); | ||||
|     FuncReturn(retval); | ||||
| } | ||||
|  | ||||
| @@ -85,8 +85,8 @@ void SvcWrap() { | ||||
|     u32 param_1 = 0; | ||||
|     u64 param_2 = 0; | ||||
|     ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), ¶m_1, ¶m_2); | ||||
|     Core::CPU().SetReg(1, param_1); | ||||
|     Core::CPU().SetReg(2, param_2); | ||||
|     Core::CurrentArmInterface().SetReg(1, param_1); | ||||
|     Core::CurrentArmInterface().SetReg(2, param_2); | ||||
|     FuncReturn(retval.raw); | ||||
| } | ||||
|  | ||||
| @@ -120,7 +120,7 @@ template <ResultCode func(u32*, u64, u64, s64)> | ||||
| void SvcWrap() { | ||||
|     u32 param_1 = 0; | ||||
|     ResultCode retval = func(¶m_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3)); | ||||
|     Core::CPU().SetReg(1, param_1); | ||||
|     Core::CurrentArmInterface().SetReg(1, param_1); | ||||
|     FuncReturn(retval.raw); | ||||
| } | ||||
|  | ||||
| @@ -133,7 +133,7 @@ template <ResultCode func(u64*, u64, u64, u64)> | ||||
| void SvcWrap() { | ||||
|     u64 param_1 = 0; | ||||
|     u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3)).raw; | ||||
|     Core::CPU().SetReg(1, param_1); | ||||
|     Core::CurrentArmInterface().SetReg(1, param_1); | ||||
|     FuncReturn(retval); | ||||
| } | ||||
|  | ||||
| @@ -143,7 +143,7 @@ void SvcWrap() { | ||||
|     u32 retval = | ||||
|         func(¶m_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF)) | ||||
|             .raw; | ||||
|     Core::CPU().SetReg(1, param_1); | ||||
|     Core::CurrentArmInterface().SetReg(1, param_1); | ||||
|     FuncReturn(retval); | ||||
| } | ||||
|  | ||||
| @@ -166,7 +166,7 @@ template <ResultCode func(u32*, u64, u64, u32)> | ||||
| void SvcWrap() { | ||||
|     u32 param_1 = 0; | ||||
|     u32 retval = func(¶m_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; | ||||
|     Core::CPU().SetReg(1, param_1); | ||||
|     Core::CurrentArmInterface().SetReg(1, param_1); | ||||
|     FuncReturn(retval); | ||||
| } | ||||
|  | ||||
| @@ -175,7 +175,7 @@ void SvcWrap() { | ||||
|     u32 param_1 = 0; | ||||
|     u32 retval = | ||||
|         func(¶m_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; | ||||
|     Core::CPU().SetReg(1, param_1); | ||||
|     Core::CurrentArmInterface().SetReg(1, param_1); | ||||
|     FuncReturn(retval); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -64,7 +64,7 @@ void Thread::Stop() { | ||||
|     // Clean up thread from ready queue | ||||
|     // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) | ||||
|     if (status == THREADSTATUS_READY) { | ||||
|         Core::System::GetInstance().Scheduler().UnscheduleThread(this, current_priority); | ||||
|         scheduler->UnscheduleThread(this, current_priority); | ||||
|     } | ||||
|  | ||||
|     status = THREADSTATUS_DEAD; | ||||
| @@ -92,7 +92,7 @@ void WaitCurrentThread_Sleep() { | ||||
| void ExitCurrentThread() { | ||||
|     Thread* thread = GetCurrentThread(); | ||||
|     thread->Stop(); | ||||
|     Core::System::GetInstance().Scheduler().RemoveThread(thread); | ||||
|     Core::System::GetInstance().CurrentScheduler().RemoveThread(thread); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -188,7 +188,7 @@ void Thread::ResumeFromWait() { | ||||
|     wakeup_callback = nullptr; | ||||
|  | ||||
|     status = THREADSTATUS_READY; | ||||
|     Core::System::GetInstance().Scheduler().ScheduleThread(this, current_priority); | ||||
|     scheduler->ScheduleThread(this, current_priority); | ||||
|     Core::System::GetInstance().PrepareReschedule(); | ||||
| } | ||||
|  | ||||
| @@ -259,8 +259,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | ||||
|  | ||||
|     SharedPtr<Thread> thread(new Thread); | ||||
|  | ||||
|     Core::System::GetInstance().Scheduler().AddThread(thread, priority); | ||||
|  | ||||
|     thread->thread_id = NewThreadId(); | ||||
|     thread->status = THREADSTATUS_DORMANT; | ||||
|     thread->entry_point = entry_point; | ||||
| @@ -275,6 +273,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | ||||
|     thread->name = std::move(name); | ||||
|     thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); | ||||
|     thread->owner_process = owner_process; | ||||
|     thread->scheduler = Core::System().GetInstance().Scheduler(static_cast<size_t>(processor_id)); | ||||
|     thread->scheduler->AddThread(thread, priority); | ||||
|  | ||||
|     // Find the next available TLS index, and mark it as used | ||||
|     auto& tls_slots = owner_process->tls_slots; | ||||
| @@ -337,7 +337,7 @@ void Thread::SetPriority(u32 priority) { | ||||
| } | ||||
|  | ||||
| void Thread::BoostPriority(u32 priority) { | ||||
|     Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority); | ||||
|     scheduler->SetThreadPriority(this, priority); | ||||
|     current_priority = priority; | ||||
| } | ||||
|  | ||||
| @@ -406,7 +406,7 @@ void Thread::UpdatePriority() { | ||||
|     if (new_priority == current_priority) | ||||
|         return; | ||||
|  | ||||
|     Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority); | ||||
|     scheduler->SetThreadPriority(this, new_priority); | ||||
|  | ||||
|     current_priority = new_priority; | ||||
|  | ||||
| @@ -421,7 +421,7 @@ void Thread::UpdatePriority() { | ||||
|  * Gets the current thread | ||||
|  */ | ||||
| Thread* GetCurrentThread() { | ||||
|     return Core::System::GetInstance().Scheduler().GetCurrentThread(); | ||||
|     return Core::System::GetInstance().CurrentScheduler().GetCurrentThread(); | ||||
| } | ||||
|  | ||||
| void ThreadingInit() { | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <unordered_map> | ||||
| #include <vector> | ||||
| @@ -56,6 +57,7 @@ enum class ThreadWakeupReason { | ||||
| namespace Kernel { | ||||
|  | ||||
| class Process; | ||||
| class Scheduler; | ||||
|  | ||||
| class Thread final : public WaitObject { | ||||
| public: | ||||
| @@ -240,6 +242,8 @@ public: | ||||
|     // available. In case of a timeout, the object will be nullptr. | ||||
|     std::function<WakeupCallback> wakeup_callback; | ||||
|  | ||||
|     std::shared_ptr<Scheduler> scheduler; | ||||
|  | ||||
| private: | ||||
|     Thread(); | ||||
|     ~Thread() override; | ||||
|   | ||||
| @@ -104,8 +104,15 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, | ||||
|     VirtualMemoryArea& final_vma = vma_handle->second; | ||||
|     ASSERT(final_vma.size == size); | ||||
|  | ||||
|     Core::CPU().MapBackingMemory(target, size, block->data() + offset, | ||||
|                                  VMAPermission::ReadWriteExecute); | ||||
|     auto& system = Core::System::GetInstance(); | ||||
|     system.ArmInterface(0).MapBackingMemory(target, size, block->data() + offset, | ||||
|                                             VMAPermission::ReadWriteExecute); | ||||
|     system.ArmInterface(1).MapBackingMemory(target, size, block->data() + offset, | ||||
|                                             VMAPermission::ReadWriteExecute); | ||||
|     system.ArmInterface(2).MapBackingMemory(target, size, block->data() + offset, | ||||
|                                             VMAPermission::ReadWriteExecute); | ||||
|     system.ArmInterface(3).MapBackingMemory(target, size, block->data() + offset, | ||||
|                                             VMAPermission::ReadWriteExecute); | ||||
|  | ||||
|     final_vma.type = VMAType::AllocatedMemoryBlock; | ||||
|     final_vma.permissions = VMAPermission::ReadWrite; | ||||
| @@ -126,7 +133,11 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me | ||||
|     VirtualMemoryArea& final_vma = vma_handle->second; | ||||
|     ASSERT(final_vma.size == size); | ||||
|  | ||||
|     Core::CPU().MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); | ||||
|     auto& system = Core::System::GetInstance(); | ||||
|     system.ArmInterface(0).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); | ||||
|     system.ArmInterface(1).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); | ||||
|     system.ArmInterface(2).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); | ||||
|     system.ArmInterface(3).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); | ||||
|  | ||||
|     final_vma.type = VMAType::BackingMemory; | ||||
|     final_vma.permissions = VMAPermission::ReadWrite; | ||||
| @@ -184,7 +195,11 @@ ResultCode VMManager::UnmapRange(VAddr target, u64 size) { | ||||
|  | ||||
|     ASSERT(FindVMA(target)->second.size >= size); | ||||
|  | ||||
|     Core::CPU().UnmapMemory(target, size); | ||||
|     auto& system = Core::System::GetInstance(); | ||||
|     system.ArmInterface(0).UnmapMemory(target, size); | ||||
|     system.ArmInterface(1).UnmapMemory(target, size); | ||||
|     system.ArmInterface(2).UnmapMemory(target, size); | ||||
|     system.ArmInterface(3).UnmapMemory(target, size); | ||||
|  | ||||
|     return RESULT_SUCCESS; | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 bunnei
					bunnei