Kernel: Rename ThreadCallbackHandleTable and Setup Thread Ids on Kernel.
This commit is contained in:
		
				
					committed by
					
						 FernandoS27
						FernandoS27
					
				
			
			
				
	
			
			
			
						parent
						
							0728dfef84
						
					
				
				
					commit
					179bafa7cb
				
			| @@ -20,6 +20,8 @@ constexpr u32 NUM_CPU_CORES = 4;            // Number of CPU Cores | ||||
|  | ||||
| } // namespace Hardware | ||||
|  | ||||
| constexpr u32 INVALID_HOST_THREAD_ID = 0xFFFFFFFF; | ||||
|  | ||||
| struct EmuThreadHandle { | ||||
|     u32 host_handle; | ||||
|     u32 guest_handle; | ||||
|   | ||||
| @@ -6,6 +6,8 @@ | ||||
| #include <functional> | ||||
| #include <memory> | ||||
| #include <mutex> | ||||
| #include <thread> | ||||
| #include <unordered_map> | ||||
| #include <utility> | ||||
|  | ||||
| #include "common/assert.h" | ||||
| @@ -44,7 +46,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ | ||||
|     std::lock_guard lock{HLE::g_hle_lock}; | ||||
|  | ||||
|     std::shared_ptr<Thread> thread = | ||||
|         system.Kernel().RetrieveThreadFromWakeupCallbackHandleTable(proper_handle); | ||||
|         system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); | ||||
|     if (thread == nullptr) { | ||||
|         LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); | ||||
|         return; | ||||
| @@ -120,7 +122,7 @@ struct KernelCore::Impl { | ||||
|  | ||||
|         system_resource_limit = nullptr; | ||||
|  | ||||
|         thread_wakeup_callback_handle_table.Clear(); | ||||
|         global_handle_table.Clear(); | ||||
|         thread_wakeup_event_type = nullptr; | ||||
|         preemption_event = nullptr; | ||||
|  | ||||
| @@ -138,8 +140,8 @@ struct KernelCore::Impl { | ||||
|  | ||||
|     void InitializePhysicalCores() { | ||||
|         exclusive_monitor = | ||||
|             Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount()); | ||||
|         for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) { | ||||
|             Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES); | ||||
|         for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { | ||||
|             cores.emplace_back(system, i, *exclusive_monitor); | ||||
|         } | ||||
|     } | ||||
| @@ -184,6 +186,48 @@ struct KernelCore::Impl { | ||||
|         system.Memory().SetCurrentPageTable(*process); | ||||
|     } | ||||
|  | ||||
|     void RegisterCoreThread(std::size_t core_id) { | ||||
|         const std::thread::id this_id = std::this_thread::get_id(); | ||||
|         const auto it = host_thread_ids.find(this_id); | ||||
|         ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); | ||||
|         ASSERT(it == host_thread_ids.end()); | ||||
|         ASSERT(!registered_core_threads[core_id]); | ||||
|         host_thread_ids[this_id] = static_cast<u32>(core_id); | ||||
|         registered_core_threads.set(core_id); | ||||
|     } | ||||
|  | ||||
|     void RegisterHostThread() { | ||||
|         const std::thread::id this_id = std::this_thread::get_id(); | ||||
|         const auto it = host_thread_ids.find(this_id); | ||||
|         ASSERT(it == host_thread_ids.end()); | ||||
|         host_thread_ids[this_id] = registered_thread_ids++; | ||||
|     } | ||||
|  | ||||
|     u32 GetCurrentHostThreadId() const { | ||||
|         const std::thread::id this_id = std::this_thread::get_id(); | ||||
|         const auto it = host_thread_ids.find(this_id); | ||||
|         if (it == host_thread_ids.end()) { | ||||
|             return Core::INVALID_HOST_THREAD_ID; | ||||
|         } | ||||
|         return it->second; | ||||
|     } | ||||
|  | ||||
|     Core::EmuThreadHandle GetCurrentEmuThreadId() const { | ||||
|         Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle(); | ||||
|         result.host_handle = GetCurrentHostThreadId(); | ||||
|         if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) { | ||||
|             return result; | ||||
|         } | ||||
|         const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler(); | ||||
|         const Kernel::Thread* current = sched.GetCurrentThread(); | ||||
|         if (current != nullptr) { | ||||
|             result.guest_handle = current->GetGlobalHandle(); | ||||
|         } else { | ||||
|             result.guest_handle = InvalidHandle; | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     std::atomic<u32> next_object_id{0}; | ||||
|     std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin}; | ||||
|     std::atomic<u64> next_user_process_id{Process::ProcessIDMin}; | ||||
| @@ -202,7 +246,7 @@ struct KernelCore::Impl { | ||||
|  | ||||
|     // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, | ||||
|     // allowing us to simply use a pool index or similar. | ||||
|     Kernel::HandleTable thread_wakeup_callback_handle_table; | ||||
|     Kernel::HandleTable global_handle_table; | ||||
|  | ||||
|     /// Map of named ports managed by the kernel, which can be retrieved using | ||||
|     /// the ConnectToPort SVC. | ||||
| @@ -211,6 +255,11 @@ struct KernelCore::Impl { | ||||
|     std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | ||||
|     std::vector<Kernel::PhysicalCore> cores; | ||||
|  | ||||
|     // 0-3 Ids represent core threads, >3 represent others | ||||
|     std::unordered_map<std::thread::id, u32> host_thread_ids; | ||||
|     u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; | ||||
|     std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads{}; | ||||
|  | ||||
|     // System context | ||||
|     Core::System& system; | ||||
| }; | ||||
| @@ -232,9 +281,8 @@ std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const { | ||||
|     return impl->system_resource_limit; | ||||
| } | ||||
|  | ||||
| std::shared_ptr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable( | ||||
|     Handle handle) const { | ||||
|     return impl->thread_wakeup_callback_handle_table.Get<Thread>(handle); | ||||
| std::shared_ptr<Thread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const { | ||||
|     return impl->global_handle_table.Get<Thread>(handle); | ||||
| } | ||||
|  | ||||
| void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) { | ||||
| @@ -346,12 +394,28 @@ const std::shared_ptr<Core::Timing::EventType>& KernelCore::ThreadWakeupCallback | ||||
|     return impl->thread_wakeup_event_type; | ||||
| } | ||||
|  | ||||
| Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() { | ||||
|     return impl->thread_wakeup_callback_handle_table; | ||||
| Kernel::HandleTable& KernelCore::GlobalHandleTable() { | ||||
|     return impl->global_handle_table; | ||||
| } | ||||
|  | ||||
| const Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() const { | ||||
|     return impl->thread_wakeup_callback_handle_table; | ||||
| const Kernel::HandleTable& KernelCore::GlobalHandleTable() const { | ||||
|     return impl->global_handle_table; | ||||
| } | ||||
|  | ||||
| void KernelCore::RegisterCoreThread(std::size_t core_id) { | ||||
|     impl->RegisterCoreThread(core_id); | ||||
| } | ||||
|  | ||||
| void KernelCore::RegisterHostThread() { | ||||
|     impl->RegisterHostThread(); | ||||
| } | ||||
|  | ||||
| u32 KernelCore::GetCurrentHostThreadId() const { | ||||
|     return impl->GetCurrentHostThreadId(); | ||||
| } | ||||
|  | ||||
| Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadId() const { | ||||
|     return impl->GetCurrentEmuThreadId(); | ||||
| } | ||||
|  | ||||
| } // namespace Kernel | ||||
|   | ||||
| @@ -8,6 +8,7 @@ | ||||
| #include <string> | ||||
| #include <unordered_map> | ||||
| #include <vector> | ||||
| #include "core/hardware_properties.h" | ||||
| #include "core/hle/kernel/object.h" | ||||
|  | ||||
| namespace Core { | ||||
| @@ -65,7 +66,7 @@ public: | ||||
|     std::shared_ptr<ResourceLimit> GetSystemResourceLimit() const; | ||||
|  | ||||
|     /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. | ||||
|     std::shared_ptr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const; | ||||
|     std::shared_ptr<Thread> RetrieveThreadFromGlobalHandleTable(Handle handle) const; | ||||
|  | ||||
|     /// Adds the given shared pointer to an internal list of active processes. | ||||
|     void AppendNewProcess(std::shared_ptr<Process> process); | ||||
| @@ -127,6 +128,18 @@ public: | ||||
|     /// Determines whether or not the given port is a valid named port. | ||||
|     bool IsValidNamedPort(NamedPortTable::const_iterator port) const; | ||||
|  | ||||
|     /// Gets the current host_thread/guest_thread handle. | ||||
|     Core::EmuThreadHandle GetCurrentEmuThreadId() const; | ||||
|  | ||||
|     /// Gets the current host_thread handle. | ||||
|     u32 GetCurrentHostThreadId() const; | ||||
|  | ||||
|     /// Register the current thread as a CPU Core Thread. | ||||
|     void RegisterCoreThread(std::size_t core_id); | ||||
|  | ||||
|     /// Register the current thread as a non CPU core thread. | ||||
|     void RegisterHostThread(); | ||||
|  | ||||
| private: | ||||
|     friend class Object; | ||||
|     friend class Process; | ||||
| @@ -147,11 +160,11 @@ private: | ||||
|     /// Retrieves the event type used for thread wakeup callbacks. | ||||
|     const std::shared_ptr<Core::Timing::EventType>& ThreadWakeupCallbackEventType() const; | ||||
|  | ||||
|     /// Provides a reference to the thread wakeup callback handle table. | ||||
|     Kernel::HandleTable& ThreadWakeupCallbackHandleTable(); | ||||
|     /// Provides a reference to the global handle table. | ||||
|     Kernel::HandleTable& GlobalHandleTable(); | ||||
|  | ||||
|     /// Provides a const reference to the thread wakeup callback handle table. | ||||
|     const Kernel::HandleTable& ThreadWakeupCallbackHandleTable() const; | ||||
|     /// Provides a const reference to the global handle table. | ||||
|     const Kernel::HandleTable& GlobalHandleTable() const; | ||||
|  | ||||
|     struct Impl; | ||||
|     std::unique_ptr<Impl> impl; | ||||
|   | ||||
| @@ -46,9 +46,9 @@ Thread::~Thread() = default; | ||||
| void Thread::Stop() { | ||||
|     // Cancel any outstanding wakeup events for this thread | ||||
|     Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), | ||||
|                                                              callback_handle); | ||||
|     kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle); | ||||
|     callback_handle = 0; | ||||
|                                                              global_handle); | ||||
|     kernel.GlobalHandleTable().Close(global_handle); | ||||
|     global_handle = 0; | ||||
|     SetStatus(ThreadStatus::Dead); | ||||
|     Signal(); | ||||
|  | ||||
| @@ -73,12 +73,12 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { | ||||
|     // thread-safe version of ScheduleEvent. | ||||
|     const s64 cycles = Core::Timing::nsToCycles(std::chrono::nanoseconds{nanoseconds}); | ||||
|     Core::System::GetInstance().CoreTiming().ScheduleEvent( | ||||
|         cycles, kernel.ThreadWakeupCallbackEventType(), callback_handle); | ||||
|         cycles, kernel.ThreadWakeupCallbackEventType(), global_handle); | ||||
| } | ||||
|  | ||||
| void Thread::CancelWakeupTimer() { | ||||
|     Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), | ||||
|                                                              callback_handle); | ||||
|                                                              global_handle); | ||||
| } | ||||
|  | ||||
| void Thread::ResumeFromWait() { | ||||
| @@ -190,7 +190,7 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(KernelCore& kernel, std::strin | ||||
|     thread->condvar_wait_address = 0; | ||||
|     thread->wait_handle = 0; | ||||
|     thread->name = std::move(name); | ||||
|     thread->callback_handle = kernel.ThreadWakeupCallbackHandleTable().Create(thread).Unwrap(); | ||||
|     thread->global_handle = kernel.GlobalHandleTable().Create(thread).Unwrap(); | ||||
|     thread->owner_process = &owner_process; | ||||
|     auto& scheduler = kernel.GlobalScheduler(); | ||||
|     scheduler.AddThread(thread); | ||||
|   | ||||
| @@ -453,6 +453,10 @@ public: | ||||
|         is_sync_cancelled = value; | ||||
|     } | ||||
|  | ||||
|     Handle GetGlobalHandle() const { | ||||
|         return global_handle; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     void SetSchedulingStatus(ThreadSchedStatus new_status); | ||||
|     void SetCurrentPriority(u32 new_priority); | ||||
| @@ -514,7 +518,7 @@ private: | ||||
|     VAddr arb_wait_address{0}; | ||||
|  | ||||
|     /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. | ||||
|     Handle callback_handle = 0; | ||||
|     Handle global_handle = 0; | ||||
|  | ||||
|     /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread | ||||
|     /// was waiting via WaitSynchronization then the object will be the last object that became | ||||
|   | ||||
		Reference in New Issue
	
	Block a user