diff options
| author | 2020-02-14 09:30:53 -0400 | |
|---|---|---|
| committer | 2020-02-22 11:18:06 -0400 | |
| commit | 179bafa7cb1efae5405d38ea9b98dc6b3e1ec756 (patch) | |
| tree | e26bc705bf9446b335c29e086b84c61916f44f32 /src | |
| parent | Kernel: Make global scheduler depend on KernelCore (diff) | |
| download | yuzu-179bafa7cb1efae5405d38ea9b98dc6b3e1ec756.tar.gz yuzu-179bafa7cb1efae5405d38ea9b98dc6b3e1ec756.tar.xz yuzu-179bafa7cb1efae5405d38ea9b98dc6b3e1ec756.zip | |
Kernel: Rename ThreadCallbackHandleTable and Setup Thread Ids on Kernel.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hardware_properties.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 88 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 23 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 12 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 6 |
5 files changed, 107 insertions, 24 deletions
diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h index 213461b6a..b04e046ed 100644 --- a/src/core/hardware_properties.h +++ b/src/core/hardware_properties.h | |||
| @@ -20,6 +20,8 @@ constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores | |||
| 20 | 20 | ||
| 21 | } // namespace Hardware | 21 | } // namespace Hardware |
| 22 | 22 | ||
| 23 | constexpr u32 INVALID_HOST_THREAD_ID = 0xFFFFFFFF; | ||
| 24 | |||
| 23 | struct EmuThreadHandle { | 25 | struct EmuThreadHandle { |
| 24 | u32 host_handle; | 26 | u32 host_handle; |
| 25 | u32 guest_handle; | 27 | u32 guest_handle; |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index d312ae31e..b3a5d7505 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -6,6 +6,8 @@ | |||
| 6 | #include <functional> | 6 | #include <functional> |
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <mutex> | 8 | #include <mutex> |
| 9 | #include <thread> | ||
| 10 | #include <unordered_map> | ||
| 9 | #include <utility> | 11 | #include <utility> |
| 10 | 12 | ||
| 11 | #include "common/assert.h" | 13 | #include "common/assert.h" |
| @@ -44,7 +46,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ | |||
| 44 | std::lock_guard lock{HLE::g_hle_lock}; | 46 | std::lock_guard lock{HLE::g_hle_lock}; |
| 45 | 47 | ||
| 46 | std::shared_ptr<Thread> thread = | 48 | std::shared_ptr<Thread> thread = |
| 47 | system.Kernel().RetrieveThreadFromWakeupCallbackHandleTable(proper_handle); | 49 | system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); |
| 48 | if (thread == nullptr) { | 50 | if (thread == nullptr) { |
| 49 | LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); | 51 | LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); |
| 50 | return; | 52 | return; |
| @@ -120,7 +122,7 @@ struct KernelCore::Impl { | |||
| 120 | 122 | ||
| 121 | system_resource_limit = nullptr; | 123 | system_resource_limit = nullptr; |
| 122 | 124 | ||
| 123 | thread_wakeup_callback_handle_table.Clear(); | 125 | global_handle_table.Clear(); |
| 124 | thread_wakeup_event_type = nullptr; | 126 | thread_wakeup_event_type = nullptr; |
| 125 | preemption_event = nullptr; | 127 | preemption_event = nullptr; |
| 126 | 128 | ||
| @@ -138,8 +140,8 @@ struct KernelCore::Impl { | |||
| 138 | 140 | ||
| 139 | void InitializePhysicalCores() { | 141 | void InitializePhysicalCores() { |
| 140 | exclusive_monitor = | 142 | exclusive_monitor = |
| 141 | Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount()); | 143 | Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES); |
| 142 | for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) { | 144 | for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { |
| 143 | cores.emplace_back(system, i, *exclusive_monitor); | 145 | cores.emplace_back(system, i, *exclusive_monitor); |
| 144 | } | 146 | } |
| 145 | } | 147 | } |
| @@ -184,6 +186,48 @@ struct KernelCore::Impl { | |||
| 184 | system.Memory().SetCurrentPageTable(*process); | 186 | system.Memory().SetCurrentPageTable(*process); |
| 185 | } | 187 | } |
| 186 | 188 | ||
| 189 | void RegisterCoreThread(std::size_t core_id) { | ||
| 190 | const std::thread::id this_id = std::this_thread::get_id(); | ||
| 191 | const auto it = host_thread_ids.find(this_id); | ||
| 192 | ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); | ||
| 193 | ASSERT(it == host_thread_ids.end()); | ||
| 194 | ASSERT(!registered_core_threads[core_id]); | ||
| 195 | host_thread_ids[this_id] = static_cast<u32>(core_id); | ||
| 196 | registered_core_threads.set(core_id); | ||
| 197 | } | ||
| 198 | |||
| 199 | void RegisterHostThread() { | ||
| 200 | const std::thread::id this_id = std::this_thread::get_id(); | ||
| 201 | const auto it = host_thread_ids.find(this_id); | ||
| 202 | ASSERT(it == host_thread_ids.end()); | ||
| 203 | host_thread_ids[this_id] = registered_thread_ids++; | ||
| 204 | } | ||
| 205 | |||
| 206 | u32 GetCurrentHostThreadId() const { | ||
| 207 | const std::thread::id this_id = std::this_thread::get_id(); | ||
| 208 | const auto it = host_thread_ids.find(this_id); | ||
| 209 | if (it == host_thread_ids.end()) { | ||
| 210 | return Core::INVALID_HOST_THREAD_ID; | ||
| 211 | } | ||
| 212 | return it->second; | ||
| 213 | } | ||
| 214 | |||
| 215 | Core::EmuThreadHandle GetCurrentEmuThreadId() const { | ||
| 216 | Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle(); | ||
| 217 | result.host_handle = GetCurrentHostThreadId(); | ||
| 218 | if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) { | ||
| 219 | return result; | ||
| 220 | } | ||
| 221 | const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler(); | ||
| 222 | const Kernel::Thread* current = sched.GetCurrentThread(); | ||
| 223 | if (current != nullptr) { | ||
| 224 | result.guest_handle = current->GetGlobalHandle(); | ||
| 225 | } else { | ||
| 226 | result.guest_handle = InvalidHandle; | ||
| 227 | } | ||
| 228 | return result; | ||
| 229 | } | ||
| 230 | |||
| 187 | std::atomic<u32> next_object_id{0}; | 231 | std::atomic<u32> next_object_id{0}; |
| 188 | std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin}; | 232 | std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin}; |
| 189 | std::atomic<u64> next_user_process_id{Process::ProcessIDMin}; | 233 | std::atomic<u64> next_user_process_id{Process::ProcessIDMin}; |
| @@ -202,7 +246,7 @@ struct KernelCore::Impl { | |||
| 202 | 246 | ||
| 203 | // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, | 247 | // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, |
| 204 | // allowing us to simply use a pool index or similar. | 248 | // allowing us to simply use a pool index or similar. |
| 205 | Kernel::HandleTable thread_wakeup_callback_handle_table; | 249 | Kernel::HandleTable global_handle_table; |
| 206 | 250 | ||
| 207 | /// Map of named ports managed by the kernel, which can be retrieved using | 251 | /// Map of named ports managed by the kernel, which can be retrieved using |
| 208 | /// the ConnectToPort SVC. | 252 | /// the ConnectToPort SVC. |
| @@ -211,6 +255,11 @@ struct KernelCore::Impl { | |||
| 211 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | 255 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
| 212 | std::vector<Kernel::PhysicalCore> cores; | 256 | std::vector<Kernel::PhysicalCore> cores; |
| 213 | 257 | ||
| 258 | // 0-3 Ids represent core threads, >3 represent others | ||
| 259 | std::unordered_map<std::thread::id, u32> host_thread_ids; | ||
| 260 | u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; | ||
| 261 | std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads{}; | ||
| 262 | |||
| 214 | // System context | 263 | // System context |
| 215 | Core::System& system; | 264 | Core::System& system; |
| 216 | }; | 265 | }; |
| @@ -232,9 +281,8 @@ std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const { | |||
| 232 | return impl->system_resource_limit; | 281 | return impl->system_resource_limit; |
| 233 | } | 282 | } |
| 234 | 283 | ||
| 235 | std::shared_ptr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable( | 284 | std::shared_ptr<Thread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const { |
| 236 | Handle handle) const { | 285 | return impl->global_handle_table.Get<Thread>(handle); |
| 237 | return impl->thread_wakeup_callback_handle_table.Get<Thread>(handle); | ||
| 238 | } | 286 | } |
| 239 | 287 | ||
| 240 | void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) { | 288 | void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) { |
| @@ -346,12 +394,28 @@ const std::shared_ptr<Core::Timing::EventType>& KernelCore::ThreadWakeupCallback | |||
| 346 | return impl->thread_wakeup_event_type; | 394 | return impl->thread_wakeup_event_type; |
| 347 | } | 395 | } |
| 348 | 396 | ||
| 349 | Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() { | 397 | Kernel::HandleTable& KernelCore::GlobalHandleTable() { |
| 350 | return impl->thread_wakeup_callback_handle_table; | 398 | return impl->global_handle_table; |
| 399 | } | ||
| 400 | |||
| 401 | const Kernel::HandleTable& KernelCore::GlobalHandleTable() const { | ||
| 402 | return impl->global_handle_table; | ||
| 403 | } | ||
| 404 | |||
| 405 | void KernelCore::RegisterCoreThread(std::size_t core_id) { | ||
| 406 | impl->RegisterCoreThread(core_id); | ||
| 407 | } | ||
| 408 | |||
| 409 | void KernelCore::RegisterHostThread() { | ||
| 410 | impl->RegisterHostThread(); | ||
| 411 | } | ||
| 412 | |||
| 413 | u32 KernelCore::GetCurrentHostThreadId() const { | ||
| 414 | return impl->GetCurrentHostThreadId(); | ||
| 351 | } | 415 | } |
| 352 | 416 | ||
| 353 | const Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() const { | 417 | Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadId() const { |
| 354 | return impl->thread_wakeup_callback_handle_table; | 418 | return impl->GetCurrentEmuThreadId(); |
| 355 | } | 419 | } |
| 356 | 420 | ||
| 357 | } // namespace Kernel | 421 | } // namespace Kernel |
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 0dfc559e9..c5e05f7b6 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <unordered_map> | 9 | #include <unordered_map> |
| 10 | #include <vector> | 10 | #include <vector> |
| 11 | #include "core/hardware_properties.h" | ||
| 11 | #include "core/hle/kernel/object.h" | 12 | #include "core/hle/kernel/object.h" |
| 12 | 13 | ||
| 13 | namespace Core { | 14 | namespace Core { |
| @@ -65,7 +66,7 @@ public: | |||
| 65 | std::shared_ptr<ResourceLimit> GetSystemResourceLimit() const; | 66 | std::shared_ptr<ResourceLimit> GetSystemResourceLimit() const; |
| 66 | 67 | ||
| 67 | /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. | 68 | /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. |
| 68 | std::shared_ptr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const; | 69 | std::shared_ptr<Thread> RetrieveThreadFromGlobalHandleTable(Handle handle) const; |
| 69 | 70 | ||
| 70 | /// Adds the given shared pointer to an internal list of active processes. | 71 | /// Adds the given shared pointer to an internal list of active processes. |
| 71 | void AppendNewProcess(std::shared_ptr<Process> process); | 72 | void AppendNewProcess(std::shared_ptr<Process> process); |
| @@ -127,6 +128,18 @@ public: | |||
| 127 | /// Determines whether or not the given port is a valid named port. | 128 | /// Determines whether or not the given port is a valid named port. |
| 128 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; | 129 | bool IsValidNamedPort(NamedPortTable::const_iterator port) const; |
| 129 | 130 | ||
| 131 | /// Gets the current host_thread/guest_thread handle. | ||
| 132 | Core::EmuThreadHandle GetCurrentEmuThreadId() const; | ||
| 133 | |||
| 134 | /// Gets the current host_thread handle. | ||
| 135 | u32 GetCurrentHostThreadId() const; | ||
| 136 | |||
| 137 | /// Register the current thread as a CPU Core Thread. | ||
| 138 | void RegisterCoreThread(std::size_t core_id); | ||
| 139 | |||
| 140 | /// Register the current thread as a non CPU core thread. | ||
| 141 | void RegisterHostThread(); | ||
| 142 | |||
| 130 | private: | 143 | private: |
| 131 | friend class Object; | 144 | friend class Object; |
| 132 | friend class Process; | 145 | friend class Process; |
| @@ -147,11 +160,11 @@ private: | |||
| 147 | /// Retrieves the event type used for thread wakeup callbacks. | 160 | /// Retrieves the event type used for thread wakeup callbacks. |
| 148 | const std::shared_ptr<Core::Timing::EventType>& ThreadWakeupCallbackEventType() const; | 161 | const std::shared_ptr<Core::Timing::EventType>& ThreadWakeupCallbackEventType() const; |
| 149 | 162 | ||
| 150 | /// Provides a reference to the thread wakeup callback handle table. | 163 | /// Provides a reference to the global handle table. |
| 151 | Kernel::HandleTable& ThreadWakeupCallbackHandleTable(); | 164 | Kernel::HandleTable& GlobalHandleTable(); |
| 152 | 165 | ||
| 153 | /// Provides a const reference to the thread wakeup callback handle table. | 166 | /// Provides a const reference to the global handle table. |
| 154 | const Kernel::HandleTable& ThreadWakeupCallbackHandleTable() const; | 167 | const Kernel::HandleTable& GlobalHandleTable() const; |
| 155 | 168 | ||
| 156 | struct Impl; | 169 | struct Impl; |
| 157 | std::unique_ptr<Impl> impl; | 170 | std::unique_ptr<Impl> impl; |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index ae5f2c8bd..bf850e0b2 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -46,9 +46,9 @@ Thread::~Thread() = default; | |||
| 46 | void Thread::Stop() { | 46 | void Thread::Stop() { |
| 47 | // Cancel any outstanding wakeup events for this thread | 47 | // Cancel any outstanding wakeup events for this thread |
| 48 | Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), | 48 | Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), |
| 49 | callback_handle); | 49 | global_handle); |
| 50 | kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle); | 50 | kernel.GlobalHandleTable().Close(global_handle); |
| 51 | callback_handle = 0; | 51 | global_handle = 0; |
| 52 | SetStatus(ThreadStatus::Dead); | 52 | SetStatus(ThreadStatus::Dead); |
| 53 | Signal(); | 53 | Signal(); |
| 54 | 54 | ||
| @@ -73,12 +73,12 @@ void Thread::WakeAfterDelay(s64 nanoseconds) { | |||
| 73 | // thread-safe version of ScheduleEvent. | 73 | // thread-safe version of ScheduleEvent. |
| 74 | const s64 cycles = Core::Timing::nsToCycles(std::chrono::nanoseconds{nanoseconds}); | 74 | const s64 cycles = Core::Timing::nsToCycles(std::chrono::nanoseconds{nanoseconds}); |
| 75 | Core::System::GetInstance().CoreTiming().ScheduleEvent( | 75 | Core::System::GetInstance().CoreTiming().ScheduleEvent( |
| 76 | cycles, kernel.ThreadWakeupCallbackEventType(), callback_handle); | 76 | cycles, kernel.ThreadWakeupCallbackEventType(), global_handle); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | void Thread::CancelWakeupTimer() { | 79 | void Thread::CancelWakeupTimer() { |
| 80 | Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), | 80 | Core::System::GetInstance().CoreTiming().UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), |
| 81 | callback_handle); | 81 | global_handle); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | void Thread::ResumeFromWait() { | 84 | void Thread::ResumeFromWait() { |
| @@ -190,7 +190,7 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(KernelCore& kernel, std::strin | |||
| 190 | thread->condvar_wait_address = 0; | 190 | thread->condvar_wait_address = 0; |
| 191 | thread->wait_handle = 0; | 191 | thread->wait_handle = 0; |
| 192 | thread->name = std::move(name); | 192 | thread->name = std::move(name); |
| 193 | thread->callback_handle = kernel.ThreadWakeupCallbackHandleTable().Create(thread).Unwrap(); | 193 | thread->global_handle = kernel.GlobalHandleTable().Create(thread).Unwrap(); |
| 194 | thread->owner_process = &owner_process; | 194 | thread->owner_process = &owner_process; |
| 195 | auto& scheduler = kernel.GlobalScheduler(); | 195 | auto& scheduler = kernel.GlobalScheduler(); |
| 196 | scheduler.AddThread(thread); | 196 | scheduler.AddThread(thread); |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 7a4916318..129e7858a 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -453,6 +453,10 @@ public: | |||
| 453 | is_sync_cancelled = value; | 453 | is_sync_cancelled = value; |
| 454 | } | 454 | } |
| 455 | 455 | ||
| 456 | Handle GetGlobalHandle() const { | ||
| 457 | return global_handle; | ||
| 458 | } | ||
| 459 | |||
| 456 | private: | 460 | private: |
| 457 | void SetSchedulingStatus(ThreadSchedStatus new_status); | 461 | void SetSchedulingStatus(ThreadSchedStatus new_status); |
| 458 | void SetCurrentPriority(u32 new_priority); | 462 | void SetCurrentPriority(u32 new_priority); |
| @@ -514,7 +518,7 @@ private: | |||
| 514 | VAddr arb_wait_address{0}; | 518 | VAddr arb_wait_address{0}; |
| 515 | 519 | ||
| 516 | /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. | 520 | /// Handle used as userdata to reference this object when inserting into the CoreTiming queue. |
| 517 | Handle callback_handle = 0; | 521 | Handle global_handle = 0; |
| 518 | 522 | ||
| 519 | /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread | 523 | /// Callback that will be invoked when the thread is resumed from a waiting state. If the thread |
| 520 | /// was waiting via WaitSynchronization then the object will be the last object that became | 524 | /// was waiting via WaitSynchronization then the object will be the last object that became |