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/scheduler.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/scheduler.cpp')
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 56 |
1 files changed, 53 insertions, 3 deletions
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 86f1421bf..c65f82fb7 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp | |||
| @@ -18,10 +18,11 @@ | |||
| 18 | #include "core/hle/kernel/kernel.h" | 18 | #include "core/hle/kernel/kernel.h" |
| 19 | #include "core/hle/kernel/process.h" | 19 | #include "core/hle/kernel/process.h" |
| 20 | #include "core/hle/kernel/scheduler.h" | 20 | #include "core/hle/kernel/scheduler.h" |
| 21 | #include "core/hle/kernel/time_manager.h" | ||
| 21 | 22 | ||
| 22 | namespace Kernel { | 23 | namespace Kernel { |
| 23 | 24 | ||
| 24 | GlobalScheduler::GlobalScheduler(Core::System& system) : system{system} {} | 25 | GlobalScheduler::GlobalScheduler(KernelCore& kernel) : kernel{kernel} {} |
| 25 | 26 | ||
| 26 | GlobalScheduler::~GlobalScheduler() = default; | 27 | GlobalScheduler::~GlobalScheduler() = default; |
| 27 | 28 | ||
| @@ -35,7 +36,7 @@ void GlobalScheduler::RemoveThread(std::shared_ptr<Thread> thread) { | |||
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | void GlobalScheduler::UnloadThread(std::size_t core) { | 38 | void GlobalScheduler::UnloadThread(std::size_t core) { |
| 38 | Scheduler& sched = system.Scheduler(core); | 39 | Scheduler& sched = kernel.Scheduler(core); |
| 39 | sched.UnloadThread(); | 40 | sched.UnloadThread(); |
| 40 | } | 41 | } |
| 41 | 42 | ||
| @@ -50,7 +51,7 @@ void GlobalScheduler::SelectThread(std::size_t core) { | |||
| 50 | sched.is_context_switch_pending = sched.selected_thread != sched.current_thread; | 51 | sched.is_context_switch_pending = sched.selected_thread != sched.current_thread; |
| 51 | std::atomic_thread_fence(std::memory_order_seq_cst); | 52 | std::atomic_thread_fence(std::memory_order_seq_cst); |
| 52 | }; | 53 | }; |
| 53 | Scheduler& sched = system.Scheduler(core); | 54 | Scheduler& sched = kernel.Scheduler(core); |
| 54 | Thread* current_thread = nullptr; | 55 | Thread* current_thread = nullptr; |
| 55 | // Step 1: Get top thread in schedule queue. | 56 | // Step 1: Get top thread in schedule queue. |
| 56 | current_thread = scheduled_queue[core].empty() ? nullptr : scheduled_queue[core].front(); | 57 | current_thread = scheduled_queue[core].empty() ? nullptr : scheduled_queue[core].front(); |
| @@ -356,6 +357,32 @@ void GlobalScheduler::Shutdown() { | |||
| 356 | thread_list.clear(); | 357 | thread_list.clear(); |
| 357 | } | 358 | } |
| 358 | 359 | ||
| 360 | void GlobalScheduler::Lock() { | ||
| 361 | Core::EmuThreadHandle current_thread = kernel.GetCurrentEmuThreadID(); | ||
| 362 | if (current_thread == current_owner) { | ||
| 363 | ++scope_lock; | ||
| 364 | } else { | ||
| 365 | inner_lock.lock(); | ||
| 366 | current_owner = current_thread; | ||
| 367 | ASSERT(current_owner != Core::EmuThreadHandle::InvalidHandle()); | ||
| 368 | scope_lock = 1; | ||
| 369 | } | ||
| 370 | } | ||
| 371 | |||
| 372 | void GlobalScheduler::Unlock() { | ||
| 373 | if (--scope_lock != 0) { | ||
| 374 | ASSERT(scope_lock > 0); | ||
| 375 | return; | ||
| 376 | } | ||
| 377 | for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { | ||
| 378 | SelectThread(i); | ||
| 379 | } | ||
| 380 | current_owner = Core::EmuThreadHandle::InvalidHandle(); | ||
| 381 | scope_lock = 1; | ||
| 382 | inner_lock.unlock(); | ||
| 383 | // TODO(Blinkhawk): Setup the interrupts and change context on current core. | ||
| 384 | } | ||
| 385 | |||
| 359 | Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) | 386 | Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) |
| 360 | : system(system), cpu_core(cpu_core), core_id(core_id) {} | 387 | : system(system), cpu_core(cpu_core), core_id(core_id) {} |
| 361 | 388 | ||
| @@ -485,4 +512,27 @@ void Scheduler::Shutdown() { | |||
| 485 | selected_thread = nullptr; | 512 | selected_thread = nullptr; |
| 486 | } | 513 | } |
| 487 | 514 | ||
| 515 | SchedulerLock::SchedulerLock(KernelCore& kernel) : kernel{kernel} { | ||
| 516 | kernel.GlobalScheduler().Lock(); | ||
| 517 | } | ||
| 518 | |||
| 519 | SchedulerLock::~SchedulerLock() { | ||
| 520 | kernel.GlobalScheduler().Unlock(); | ||
| 521 | } | ||
| 522 | |||
| 523 | SchedulerLockAndSleep::SchedulerLockAndSleep(KernelCore& kernel, Handle& event_handle, | ||
| 524 | Thread* time_task, s64 nanoseconds) | ||
| 525 | : SchedulerLock{kernel}, event_handle{event_handle}, time_task{time_task}, nanoseconds{ | ||
| 526 | nanoseconds} { | ||
| 527 | event_handle = InvalidHandle; | ||
| 528 | } | ||
| 529 | |||
| 530 | SchedulerLockAndSleep::~SchedulerLockAndSleep() { | ||
| 531 | if (sleep_cancelled) { | ||
| 532 | return; | ||
| 533 | } | ||
| 534 | auto& time_manager = kernel.TimeManager(); | ||
| 535 | time_manager.ScheduleTimeEvent(event_handle, time_task, nanoseconds); | ||
| 536 | } | ||
| 537 | |||
| 488 | } // namespace Kernel | 538 | } // namespace Kernel |