diff options
| author | 2020-02-22 22:32:21 -0500 | |
|---|---|---|
| committer | 2020-02-22 22:32:21 -0500 | |
| commit | 3ef5f2017dba35742b32500e95744512dd5ef630 (patch) | |
| tree | ca5359a2ae4e34608e5564e43bdefe4946e413c8 /src/core/hle/kernel/kernel.cpp | |
| parent | Merge pull request #3444 from bunnei/linux-audio-fix (diff) | |
| parent | Scheduler: Inline global scheduler in Scheduler Lock. (diff) | |
| download | yuzu-3ef5f2017dba35742b32500e95744512dd5ef630.tar.gz yuzu-3ef5f2017dba35742b32500e95744512dd5ef630.tar.xz yuzu-3ef5f2017dba35742b32500e95744512dd5ef630.zip | |
Merge pull request #3416 from FernandoS27/schedule
Kernel: Refactors and Implement a TimeManager and SchedulerLocks
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 121 |
1 files changed, 104 insertions, 17 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 4eb1d8703..9232f4d7e 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -3,9 +3,12 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <atomic> | 5 | #include <atomic> |
| 6 | #include <bitset> | ||
| 6 | #include <functional> | 7 | #include <functional> |
| 7 | #include <memory> | 8 | #include <memory> |
| 8 | #include <mutex> | 9 | #include <mutex> |
| 10 | #include <thread> | ||
| 11 | #include <unordered_map> | ||
| 9 | #include <utility> | 12 | #include <utility> |
| 10 | 13 | ||
| 11 | #include "common/assert.h" | 14 | #include "common/assert.h" |
| @@ -15,6 +18,7 @@ | |||
| 15 | #include "core/core.h" | 18 | #include "core/core.h" |
| 16 | #include "core/core_timing.h" | 19 | #include "core/core_timing.h" |
| 17 | #include "core/core_timing_util.h" | 20 | #include "core/core_timing_util.h" |
| 21 | #include "core/hardware_properties.h" | ||
| 18 | #include "core/hle/kernel/client_port.h" | 22 | #include "core/hle/kernel/client_port.h" |
| 19 | #include "core/hle/kernel/errors.h" | 23 | #include "core/hle/kernel/errors.h" |
| 20 | #include "core/hle/kernel/handle_table.h" | 24 | #include "core/hle/kernel/handle_table.h" |
| @@ -25,6 +29,7 @@ | |||
| 25 | #include "core/hle/kernel/scheduler.h" | 29 | #include "core/hle/kernel/scheduler.h" |
| 26 | #include "core/hle/kernel/synchronization.h" | 30 | #include "core/hle/kernel/synchronization.h" |
| 27 | #include "core/hle/kernel/thread.h" | 31 | #include "core/hle/kernel/thread.h" |
| 32 | #include "core/hle/kernel/time_manager.h" | ||
| 28 | #include "core/hle/lock.h" | 33 | #include "core/hle/lock.h" |
| 29 | #include "core/hle/result.h" | 34 | #include "core/hle/result.h" |
| 30 | #include "core/memory.h" | 35 | #include "core/memory.h" |
| @@ -44,7 +49,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ | |||
| 44 | std::lock_guard lock{HLE::g_hle_lock}; | 49 | std::lock_guard lock{HLE::g_hle_lock}; |
| 45 | 50 | ||
| 46 | std::shared_ptr<Thread> thread = | 51 | std::shared_ptr<Thread> thread = |
| 47 | system.Kernel().RetrieveThreadFromWakeupCallbackHandleTable(proper_handle); | 52 | system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle); |
| 48 | if (thread == nullptr) { | 53 | if (thread == nullptr) { |
| 49 | LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); | 54 | LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); |
| 50 | return; | 55 | return; |
| @@ -97,8 +102,8 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_ | |||
| 97 | } | 102 | } |
| 98 | 103 | ||
| 99 | struct KernelCore::Impl { | 104 | struct KernelCore::Impl { |
| 100 | explicit Impl(Core::System& system) | 105 | explicit Impl(Core::System& system, KernelCore& kernel) |
| 101 | : system{system}, global_scheduler{system}, synchronization{system} {} | 106 | : system{system}, global_scheduler{kernel}, synchronization{system}, time_manager{system} {} |
| 102 | 107 | ||
| 103 | void Initialize(KernelCore& kernel) { | 108 | void Initialize(KernelCore& kernel) { |
| 104 | Shutdown(); | 109 | Shutdown(); |
| @@ -120,7 +125,7 @@ struct KernelCore::Impl { | |||
| 120 | 125 | ||
| 121 | system_resource_limit = nullptr; | 126 | system_resource_limit = nullptr; |
| 122 | 127 | ||
| 123 | thread_wakeup_callback_handle_table.Clear(); | 128 | global_handle_table.Clear(); |
| 124 | thread_wakeup_event_type = nullptr; | 129 | thread_wakeup_event_type = nullptr; |
| 125 | preemption_event = nullptr; | 130 | preemption_event = nullptr; |
| 126 | 131 | ||
| @@ -138,8 +143,8 @@ struct KernelCore::Impl { | |||
| 138 | 143 | ||
| 139 | void InitializePhysicalCores() { | 144 | void InitializePhysicalCores() { |
| 140 | exclusive_monitor = | 145 | exclusive_monitor = |
| 141 | Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount()); | 146 | Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES); |
| 142 | for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) { | 147 | for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { |
| 143 | cores.emplace_back(system, i, *exclusive_monitor); | 148 | cores.emplace_back(system, i, *exclusive_monitor); |
| 144 | } | 149 | } |
| 145 | } | 150 | } |
| @@ -184,6 +189,50 @@ struct KernelCore::Impl { | |||
| 184 | system.Memory().SetCurrentPageTable(*process); | 189 | system.Memory().SetCurrentPageTable(*process); |
| 185 | } | 190 | } |
| 186 | 191 | ||
| 192 | void RegisterCoreThread(std::size_t core_id) { | ||
| 193 | std::unique_lock lock{register_thread_mutex}; | ||
| 194 | const std::thread::id this_id = std::this_thread::get_id(); | ||
| 195 | const auto it = host_thread_ids.find(this_id); | ||
| 196 | ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); | ||
| 197 | ASSERT(it == host_thread_ids.end()); | ||
| 198 | ASSERT(!registered_core_threads[core_id]); | ||
| 199 | host_thread_ids[this_id] = static_cast<u32>(core_id); | ||
| 200 | registered_core_threads.set(core_id); | ||
| 201 | } | ||
| 202 | |||
| 203 | void RegisterHostThread() { | ||
| 204 | std::unique_lock lock{register_thread_mutex}; | ||
| 205 | const std::thread::id this_id = std::this_thread::get_id(); | ||
| 206 | const auto it = host_thread_ids.find(this_id); | ||
| 207 | ASSERT(it == host_thread_ids.end()); | ||
| 208 | host_thread_ids[this_id] = registered_thread_ids++; | ||
| 209 | } | ||
| 210 | |||
| 211 | u32 GetCurrentHostThreadID() const { | ||
| 212 | const std::thread::id this_id = std::this_thread::get_id(); | ||
| 213 | const auto it = host_thread_ids.find(this_id); | ||
| 214 | if (it == host_thread_ids.end()) { | ||
| 215 | return Core::INVALID_HOST_THREAD_ID; | ||
| 216 | } | ||
| 217 | return it->second; | ||
| 218 | } | ||
| 219 | |||
| 220 | Core::EmuThreadHandle GetCurrentEmuThreadID() const { | ||
| 221 | Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle(); | ||
| 222 | result.host_handle = GetCurrentHostThreadID(); | ||
| 223 | if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) { | ||
| 224 | return result; | ||
| 225 | } | ||
| 226 | const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler(); | ||
| 227 | const Kernel::Thread* current = sched.GetCurrentThread(); | ||
| 228 | if (current != nullptr) { | ||
| 229 | result.guest_handle = current->GetGlobalHandle(); | ||
| 230 | } else { | ||
| 231 | result.guest_handle = InvalidHandle; | ||
| 232 | } | ||
| 233 | return result; | ||
| 234 | } | ||
| 235 | |||
| 187 | std::atomic<u32> next_object_id{0}; | 236 | std::atomic<u32> next_object_id{0}; |
| 188 | std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin}; | 237 | std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin}; |
| 189 | std::atomic<u64> next_user_process_id{Process::ProcessIDMin}; | 238 | std::atomic<u64> next_user_process_id{Process::ProcessIDMin}; |
| @@ -194,15 +243,16 @@ struct KernelCore::Impl { | |||
| 194 | Process* current_process = nullptr; | 243 | Process* current_process = nullptr; |
| 195 | Kernel::GlobalScheduler global_scheduler; | 244 | Kernel::GlobalScheduler global_scheduler; |
| 196 | Kernel::Synchronization synchronization; | 245 | Kernel::Synchronization synchronization; |
| 246 | Kernel::TimeManager time_manager; | ||
| 197 | 247 | ||
| 198 | std::shared_ptr<ResourceLimit> system_resource_limit; | 248 | std::shared_ptr<ResourceLimit> system_resource_limit; |
| 199 | 249 | ||
| 200 | std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type; | 250 | std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type; |
| 201 | std::shared_ptr<Core::Timing::EventType> preemption_event; | 251 | std::shared_ptr<Core::Timing::EventType> preemption_event; |
| 202 | 252 | ||
| 203 | // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, | 253 | // This is the kernel's handle table or supervisor handle table which |
| 204 | // allowing us to simply use a pool index or similar. | 254 | // stores all the objects in place. |
| 205 | Kernel::HandleTable thread_wakeup_callback_handle_table; | 255 | Kernel::HandleTable global_handle_table; |
| 206 | 256 | ||
| 207 | /// Map of named ports managed by the kernel, which can be retrieved using | 257 | /// Map of named ports managed by the kernel, which can be retrieved using |
| 208 | /// the ConnectToPort SVC. | 258 | /// the ConnectToPort SVC. |
| @@ -211,11 +261,17 @@ struct KernelCore::Impl { | |||
| 211 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | 261 | std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; |
| 212 | std::vector<Kernel::PhysicalCore> cores; | 262 | std::vector<Kernel::PhysicalCore> cores; |
| 213 | 263 | ||
| 264 | // 0-3 IDs represent core threads, >3 represent others | ||
| 265 | std::unordered_map<std::thread::id, u32> host_thread_ids; | ||
| 266 | u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; | ||
| 267 | std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads; | ||
| 268 | std::mutex register_thread_mutex; | ||
| 269 | |||
| 214 | // System context | 270 | // System context |
| 215 | Core::System& system; | 271 | Core::System& system; |
| 216 | }; | 272 | }; |
| 217 | 273 | ||
| 218 | KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system)} {} | 274 | KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system, *this)} {} |
| 219 | KernelCore::~KernelCore() { | 275 | KernelCore::~KernelCore() { |
| 220 | Shutdown(); | 276 | Shutdown(); |
| 221 | } | 277 | } |
| @@ -232,9 +288,8 @@ std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const { | |||
| 232 | return impl->system_resource_limit; | 288 | return impl->system_resource_limit; |
| 233 | } | 289 | } |
| 234 | 290 | ||
| 235 | std::shared_ptr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable( | 291 | std::shared_ptr<Thread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const { |
| 236 | Handle handle) const { | 292 | return impl->global_handle_table.Get<Thread>(handle); |
| 237 | return impl->thread_wakeup_callback_handle_table.Get<Thread>(handle); | ||
| 238 | } | 293 | } |
| 239 | 294 | ||
| 240 | void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) { | 295 | void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) { |
| @@ -265,6 +320,14 @@ const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const { | |||
| 265 | return impl->global_scheduler; | 320 | return impl->global_scheduler; |
| 266 | } | 321 | } |
| 267 | 322 | ||
| 323 | Kernel::Scheduler& KernelCore::Scheduler(std::size_t id) { | ||
| 324 | return impl->cores[id].Scheduler(); | ||
| 325 | } | ||
| 326 | |||
| 327 | const Kernel::Scheduler& KernelCore::Scheduler(std::size_t id) const { | ||
| 328 | return impl->cores[id].Scheduler(); | ||
| 329 | } | ||
| 330 | |||
| 268 | Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) { | 331 | Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) { |
| 269 | return impl->cores[id]; | 332 | return impl->cores[id]; |
| 270 | } | 333 | } |
| @@ -281,6 +344,14 @@ const Kernel::Synchronization& KernelCore::Synchronization() const { | |||
| 281 | return impl->synchronization; | 344 | return impl->synchronization; |
| 282 | } | 345 | } |
| 283 | 346 | ||
| 347 | Kernel::TimeManager& KernelCore::TimeManager() { | ||
| 348 | return impl->time_manager; | ||
| 349 | } | ||
| 350 | |||
| 351 | const Kernel::TimeManager& KernelCore::TimeManager() const { | ||
| 352 | return impl->time_manager; | ||
| 353 | } | ||
| 354 | |||
| 284 | Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { | 355 | Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { |
| 285 | return *impl->exclusive_monitor; | 356 | return *impl->exclusive_monitor; |
| 286 | } | 357 | } |
| @@ -338,12 +409,28 @@ const std::shared_ptr<Core::Timing::EventType>& KernelCore::ThreadWakeupCallback | |||
| 338 | return impl->thread_wakeup_event_type; | 409 | return impl->thread_wakeup_event_type; |
| 339 | } | 410 | } |
| 340 | 411 | ||
| 341 | Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() { | 412 | Kernel::HandleTable& KernelCore::GlobalHandleTable() { |
| 342 | return impl->thread_wakeup_callback_handle_table; | 413 | return impl->global_handle_table; |
| 414 | } | ||
| 415 | |||
| 416 | const Kernel::HandleTable& KernelCore::GlobalHandleTable() const { | ||
| 417 | return impl->global_handle_table; | ||
| 418 | } | ||
| 419 | |||
| 420 | void KernelCore::RegisterCoreThread(std::size_t core_id) { | ||
| 421 | impl->RegisterCoreThread(core_id); | ||
| 422 | } | ||
| 423 | |||
| 424 | void KernelCore::RegisterHostThread() { | ||
| 425 | impl->RegisterHostThread(); | ||
| 426 | } | ||
| 427 | |||
| 428 | u32 KernelCore::GetCurrentHostThreadID() const { | ||
| 429 | return impl->GetCurrentHostThreadID(); | ||
| 343 | } | 430 | } |
| 344 | 431 | ||
| 345 | const Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() const { | 432 | Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadID() const { |
| 346 | return impl->thread_wakeup_callback_handle_table; | 433 | return impl->GetCurrentEmuThreadID(); |
| 347 | } | 434 | } |
| 348 | 435 | ||
| 349 | } // namespace Kernel | 436 | } // namespace Kernel |