From 1fd762fd31afcdd86043bdbd2bbc94344b3b5a79 Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 6 Jun 2026 00:50:10 +0000 Subject: [PATCH] scheduler takes kernel ptr --- src/core/core.h | 1 - src/core/cpu_manager.cpp | 73 ++++------ src/core/cpu_manager.h | 44 +++--- src/core/hle/kernel/k_interrupt_manager.cpp | 2 +- src/core/hle/kernel/k_scheduler.cpp | 140 +++++++++----------- src/core/hle/kernel/k_scheduler.h | 39 +++--- src/core/hle/kernel/k_thread.cpp | 28 ++-- src/core/hle/kernel/k_thread_queue.h | 3 +- src/core/hle/kernel/kernel.cpp | 2 +- 9 files changed, 150 insertions(+), 182 deletions(-) diff --git a/src/core/core.h b/src/core/core.h index 012533c1fa..93f7b057f7 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -438,7 +438,6 @@ public: /// Applies any changes to settings to this core instance. void ApplySettings(); -private: struct Impl; std::unique_ptr impl; }; diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index f8b1df22e2..7194fa5022 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -41,30 +41,28 @@ void CpuManager::Shutdown() { } } -void CpuManager::GuestThreadFunction() { +void CpuManager::GuestThreadFunction(Kernel::KernelCore& kernel) { if (is_multicore) { - MultiCoreRunGuestThread(); + MultiCoreRunGuestThread(kernel); } else { - SingleCoreRunGuestThread(); + SingleCoreRunGuestThread(kernel); } } -void CpuManager::IdleThreadFunction() { +void CpuManager::IdleThreadFunction(Kernel::KernelCore& kernel) { if (is_multicore) { - MultiCoreRunIdleThread(); + MultiCoreRunIdleThread(kernel); } else { - SingleCoreRunIdleThread(); + SingleCoreRunIdleThread(kernel); } } -void CpuManager::ShutdownThreadFunction() { - ShutdownThread(); +void CpuManager::ShutdownThreadFunction(Kernel::KernelCore& kernel) { + ShutdownThread(kernel); } -void CpuManager::HandleInterrupt() { - auto& kernel = system.Kernel(); +void CpuManager::HandleInterrupt(Kernel::KernelCore& kernel) { auto core_index = kernel.CurrentPhysicalCoreIndex(); - Kernel::KInterruptManager::HandleInterrupt(kernel, s32(core_index)); } @@ -72,11 +70,10 @@ void CpuManager::HandleInterrupt() { /// MultiCore /// /////////////////////////////////////////////////////////////////////////////// -void CpuManager::MultiCoreRunGuestThread() { +void CpuManager::MultiCoreRunGuestThread(Kernel::KernelCore& kernel) { // Similar to UserModeThreadStarter in HOS - auto& kernel = system.Kernel(); auto* thread = Kernel::GetCurrentThreadPointer(kernel); - kernel.CurrentScheduler()->OnThreadStart(); + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); @@ -84,26 +81,21 @@ void CpuManager::MultiCoreRunGuestThread() { physical_core->RunThread(kernel, thread); physical_core = &kernel.CurrentPhysicalCore(); } - - HandleInterrupt(); + HandleInterrupt(kernel); } } -void CpuManager::MultiCoreRunIdleThread() { +void CpuManager::MultiCoreRunIdleThread(Kernel::KernelCore& kernel) { // Not accurate to HOS. Remove this entire method when singlecore is removed. // See notes in KScheduler::ScheduleImpl for more information about why this // is inaccurate. - - auto& kernel = system.Kernel(); - kernel.CurrentScheduler()->OnThreadStart(); - + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { auto& physical_core = kernel.CurrentPhysicalCore(); if (!physical_core.IsInterrupted()) { physical_core.Idle(); } - - HandleInterrupt(); + HandleInterrupt(kernel); } } @@ -111,10 +103,9 @@ void CpuManager::MultiCoreRunIdleThread() { /// SingleCore /// /////////////////////////////////////////////////////////////////////////////// -void CpuManager::SingleCoreRunGuestThread() { - auto& kernel = system.Kernel(); +void CpuManager::SingleCoreRunGuestThread(Kernel::KernelCore& kernel) { auto* thread = Kernel::GetCurrentThreadPointer(kernel); - kernel.CurrentScheduler()->OnThreadStart(); + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); @@ -127,26 +118,22 @@ void CpuManager::SingleCoreRunGuestThread() { system.CoreTiming().Advance(); kernel.SetIsPhantomModeForSingleCore(false); - PreemptSingleCore(); - HandleInterrupt(); + PreemptSingleCore(kernel); + HandleInterrupt(kernel); } } -void CpuManager::SingleCoreRunIdleThread() { - auto& kernel = system.Kernel(); - kernel.CurrentScheduler()->OnThreadStart(); - +void CpuManager::SingleCoreRunIdleThread(Kernel::KernelCore& kernel) { + kernel.CurrentScheduler()->OnThreadStart(kernel); while (true) { - PreemptSingleCore(false); + PreemptSingleCore(kernel, false); system.CoreTiming().AddTicks(1000U); idle_count++; - HandleInterrupt(); + HandleInterrupt(kernel); } } -void CpuManager::PreemptSingleCore(bool from_running_environment) { - auto& kernel = system.Kernel(); - +void CpuManager::PreemptSingleCore(Kernel::KernelCore& kernel, bool from_running_environment) { if (idle_count >= 4 || from_running_environment) { if (!from_running_environment) { system.CoreTiming().Idle(); @@ -158,7 +145,7 @@ void CpuManager::PreemptSingleCore(bool from_running_environment) { } current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); system.CoreTiming().ResetTicks(); - kernel.Scheduler(current_core).PreemptSingleCore(); + kernel.Scheduler(current_core).PreemptSingleCore(kernel); // We've now been scheduled again, and we may have exchanged schedulers. // Reload the scheduler in case it's different. @@ -167,20 +154,16 @@ void CpuManager::PreemptSingleCore(bool from_running_environment) { } } -void CpuManager::GuestActivate() { +void CpuManager::GuestActivate(Kernel::KernelCore& kernel) { // Similar to the HorizonKernelMain callback in HOS - auto& kernel = system.Kernel(); auto* scheduler = kernel.CurrentScheduler(); - - scheduler->Activate(); + scheduler->Activate(kernel); UNREACHABLE(); } -void CpuManager::ShutdownThread() { - auto& kernel = system.Kernel(); +void CpuManager::ShutdownThread(Kernel::KernelCore& kernel) { auto* thread = kernel.GetCurrentEmuThread(); auto core = is_multicore ? kernel.CurrentPhysicalCoreIndex() : 0; - Common::Fiber::YieldTo(thread->GetHostContext(), *core_data[core].host_context); UNREACHABLE(); } diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 4ad5b5f0ad..5e97f51bfb 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h @@ -17,6 +17,10 @@ #include "common/thread.h" #include "core/hardware_properties.h" +namespace Kernel { +class KernelCore; +} + namespace Common { class Event; class Fiber; @@ -54,39 +58,39 @@ public: void Initialize(); void Shutdown(); - std::function GetGuestActivateFunc() { - return [this] { GuestActivate(); }; + std::function GetGuestActivateFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { GuestActivate(kernel); }; } - std::function GetGuestThreadFunc() { - return [this] { GuestThreadFunction(); }; + std::function GetGuestThreadFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { GuestThreadFunction(kernel); }; } - std::function GetIdleThreadStartFunc() { - return [this] { IdleThreadFunction(); }; + std::function GetIdleThreadStartFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { IdleThreadFunction(kernel); }; } - std::function GetShutdownThreadStartFunc() { - return [this] { ShutdownThreadFunction(); }; + std::function GetShutdownThreadStartFunc(Kernel::KernelCore& kernel) { + return [this, &kernel] { ShutdownThreadFunction(kernel); }; } - void PreemptSingleCore(bool from_running_environment = true); + void PreemptSingleCore(Kernel::KernelCore& kernel, bool from_running_environment = true); std::size_t CurrentCore() const { return current_core.load(); } private: - void GuestThreadFunction(); - void IdleThreadFunction(); - void ShutdownThreadFunction(); + void GuestThreadFunction(Kernel::KernelCore& kernel); + void IdleThreadFunction(Kernel::KernelCore& kernel); + void ShutdownThreadFunction(Kernel::KernelCore& kernel); - void MultiCoreRunGuestThread(); - void MultiCoreRunIdleThread(); + void MultiCoreRunGuestThread(Kernel::KernelCore& kernel); + void MultiCoreRunIdleThread(Kernel::KernelCore& kernel); - void SingleCoreRunGuestThread(); - void SingleCoreRunIdleThread(); + void SingleCoreRunGuestThread(Kernel::KernelCore& kernel); + void SingleCoreRunIdleThread(Kernel::KernelCore& kernel); - void GuestActivate(); - void HandleInterrupt(); - void ShutdownThread(); + void GuestActivate(Kernel::KernelCore& kernel); + void HandleInterrupt(Kernel::KernelCore& kernel); + void ShutdownThread(Kernel::KernelCore& kernel); void RunThread(std::stop_token stop_token, std::size_t core); static constexpr std::size_t max_cycle_runs = 5; @@ -97,7 +101,7 @@ private: std::jthread host_thread; }; std::array core_data{}; - System& system; + Core::System& system; std::atomic current_core{}; std::size_t idle_count{}; std::size_t num_cores{}; diff --git a/src/core/hle/kernel/k_interrupt_manager.cpp b/src/core/hle/kernel/k_interrupt_manager.cpp index 8960d576b5..9bd182fd9b 100644 --- a/src/core/hle/kernel/k_interrupt_manager.cpp +++ b/src/core/hle/kernel/k_interrupt_manager.cpp @@ -33,7 +33,7 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) { } // Request interrupt scheduling. - kernel.CurrentScheduler()->RequestScheduleOnInterrupt(); + kernel.CurrentScheduler()->RequestScheduleOnInterrupt(kernel); } void SendInterProcessorInterrupt(KernelCore& kernel, u64 core_mask) { diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 2c4d505d77..8e629f6456 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -30,28 +30,26 @@ static void IncrementScheduledCount(Kernel::KThread* thread) { } } -KScheduler::KScheduler(KernelCore& kernel) : m_kernel{kernel} { - m_switch_fiber = std::make_shared([this] { +KScheduler::KScheduler(KernelCore& kernel) { + m_switch_fiber = std::make_shared([this, &kernel] { while (true) { - ScheduleImplFiber(); + ScheduleImplFiber(kernel); } }); - m_state.needs_scheduling = true; } KScheduler::~KScheduler() = default; -void KScheduler::SetInterruptTaskRunnable() { +void KScheduler::SetInterruptTaskRunnable(KernelCore& kernel) { m_state.interrupt_task_runnable = true; m_state.needs_scheduling = true; } -void KScheduler::RequestScheduleOnInterrupt() { +void KScheduler::RequestScheduleOnInterrupt(KernelCore& kernel) { m_state.needs_scheduling = true; - - if (CanSchedule(m_kernel)) { - ScheduleOnInterrupt(); + if (CanSchedule(kernel)) { + ScheduleOnInterrupt(kernel); } } @@ -71,12 +69,12 @@ void KScheduler::EnableScheduling(KernelCore& kernel, u64 cores_needing_scheduli return; } - scheduler->RescheduleOtherCores(cores_needing_scheduling); + scheduler->RescheduleOtherCores(kernel, cores_needing_scheduling); if (GetCurrentThread(kernel).GetDisableDispatchCount() > 1) { GetCurrentThread(kernel).EnableDispatch(kernel); } else { - scheduler->RescheduleCurrentCore(); + scheduler->RescheduleCurrentCore(kernel); } } @@ -99,55 +97,55 @@ u64 KScheduler::UpdateHighestPriorityThreads(KernelCore& kernel) { } } -void KScheduler::Schedule() { - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); - ASSERT(m_core_id == GetCurrentCoreId(m_kernel)); +void KScheduler::Schedule(KernelCore& kernel) { + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); + ASSERT(m_core_id == GetCurrentCoreId(kernel)); - ScheduleImpl(); + ScheduleImpl(kernel); } -void KScheduler::ScheduleOnInterrupt() { - GetCurrentThread(m_kernel).DisableDispatch(m_kernel); - Schedule(); - GetCurrentThread(m_kernel).EnableDispatch(m_kernel); +void KScheduler::ScheduleOnInterrupt(KernelCore& kernel) { + GetCurrentThread(kernel).DisableDispatch(kernel); + Schedule(kernel); + GetCurrentThread(kernel).EnableDispatch(kernel); } -void KScheduler::PreemptSingleCore() { - GetCurrentThread(m_kernel).DisableDispatch(m_kernel); +void KScheduler::PreemptSingleCore(KernelCore& kernel) { + GetCurrentThread(kernel).DisableDispatch(kernel); - auto* thread = GetCurrentThreadPointer(m_kernel); - auto& previous_scheduler = m_kernel.Scheduler(thread->GetCurrentCore()); - previous_scheduler.Unload(thread); + auto* thread = GetCurrentThreadPointer(kernel); + auto& previous_scheduler = kernel.Scheduler(thread->GetCurrentCore()); + previous_scheduler.Unload(kernel, thread); Common::Fiber::YieldTo(thread->GetHostContext(), *m_switch_fiber); - GetCurrentThread(m_kernel).EnableDispatch(m_kernel); + GetCurrentThread(kernel).EnableDispatch(kernel); } -void KScheduler::RescheduleCurrentCore() { - ASSERT(!m_kernel.IsPhantomModeForSingleCore()); - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); +void KScheduler::RescheduleCurrentCore(KernelCore& kernel) { + ASSERT(!kernel.IsPhantomModeForSingleCore()); + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); - GetCurrentThread(m_kernel).EnableDispatch(m_kernel); + GetCurrentThread(kernel).EnableDispatch(kernel); if (m_state.needs_scheduling.load()) { // Disable interrupts, and then check again if rescheduling is needed. // KScopedInterruptDisable intr_disable; - m_kernel.CurrentScheduler()->RescheduleCurrentCoreImpl(); + kernel.CurrentScheduler()->RescheduleCurrentCoreImpl(kernel); } } -void KScheduler::RescheduleCurrentCoreImpl() { +void KScheduler::RescheduleCurrentCoreImpl(KernelCore& kernel) { // Check that scheduling is needed. if (m_state.needs_scheduling.load()) [[likely]] { - GetCurrentThread(m_kernel).DisableDispatch(m_kernel); - Schedule(); - GetCurrentThread(m_kernel).EnableDispatch(m_kernel); + GetCurrentThread(kernel).DisableDispatch(kernel); + Schedule(kernel); + GetCurrentThread(kernel).EnableDispatch(kernel); } } -void KScheduler::Initialize(KThread* main_thread, KThread* idle_thread, s32 core_id) { +void KScheduler::Initialize(KernelCore& kernel, KThread* main_thread, KThread* idle_thread, s32 core_id) { // Set core ID/idle thread/interrupt task manager. m_core_id = core_id; m_idle_thread = idle_thread; @@ -156,39 +154,39 @@ void KScheduler::Initialize(KThread* main_thread, KThread* idle_thread, s32 core // Insert the main thread into the priority queue. // { - // KScopedSchedulerLock lk{m_kernel}; - // GetPriorityQueue(m_kernel).PushBack(GetCurrentThreadPointer(m_kernel)); - // SetSchedulerUpdateNeeded(m_kernel); + // KScopedSchedulerLock lk{kernel}; + // GetPriorityQueue(kernel).PushBack(GetCurrentThreadPointer(kernel)); + // SetSchedulerUpdateNeeded(kernel); // } // Bind interrupt handler. // kernel.GetInterruptManager().BindHandler( - // GetSchedulerInterruptHandler(m_kernel), KInterruptName::Scheduler, m_core_id, + // GetSchedulerInterruptHandler(kernel), KInterruptName::Scheduler, m_core_id, // KInterruptController::PriorityLevel::Scheduler, false, false); // Set the current thread. m_current_thread = main_thread; } -void KScheduler::Activate() { - ASSERT(GetCurrentThread(m_kernel).GetDisableDispatchCount() == 1); +void KScheduler::Activate(KernelCore& kernel) { + ASSERT(GetCurrentThread(kernel).GetDisableDispatchCount() == 1); // m_state.should_count_idle = KTargetSystem::IsDebugMode(); m_is_active = true; - RescheduleCurrentCore(); + RescheduleCurrentCore(kernel); } -void KScheduler::OnThreadStart() { - GetCurrentThread(m_kernel).EnableDispatch(m_kernel); +void KScheduler::OnThreadStart(KernelCore& kernel) { + GetCurrentThread(kernel).EnableDispatch(kernel); } -u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) { +u64 KScheduler::UpdateHighestPriorityThread(KernelCore& kernel, KThread* highest_thread) { if (KThread* prev_highest_thread = m_state.highest_priority_thread; prev_highest_thread != highest_thread) [[likely]] { if (prev_highest_thread != nullptr) [[likely]] { IncrementScheduledCount(prev_highest_thread); prev_highest_thread->SetLastScheduledTick( - m_kernel.System().CoreTiming().GetClockTicks()); + kernel.System().CoreTiming().GetClockTicks()); } if (m_state.should_count_idle) { if (highest_thread != nullptr) [[likely]] { @@ -245,8 +243,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { } top_threads[core_id] = top_thread; - cores_needing_scheduling |= - kernel.Scheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]); + cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); } // Idle cores are bad. We're going to try to migrate threads to each idle core in turn. @@ -274,8 +271,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { suggested->SetActiveCore(core_id); priority_queue.ChangeCore(suggested_core, suggested); top_threads[core_id] = suggested; - cores_needing_scheduling |= - kernel.Scheduler(core_id).UpdateHighestPriorityThread(top_threads[core_id]); + cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); break; } @@ -298,17 +294,13 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { // The candidate core can run some other thread! We'll migrate its current // top thread to us. top_threads[candidate_core] = next_on_candidate_core; - cores_needing_scheduling |= - kernel.Scheduler(candidate_core) - .UpdateHighestPriorityThread(top_threads[candidate_core]); + cores_needing_scheduling |= kernel.Scheduler(candidate_core).UpdateHighestPriorityThread(kernel, top_threads[candidate_core]); // Perform the migration. suggested->SetActiveCore(core_id); priority_queue.ChangeCore(candidate_core, suggested); top_threads[core_id] = suggested; - cores_needing_scheduling |= - kernel.Scheduler(core_id).UpdateHighestPriorityThread( - top_threads[core_id]); + cores_needing_scheduling |= kernel.Scheduler(core_id).UpdateHighestPriorityThread(kernel, top_threads[core_id]); break; } } @@ -331,9 +323,9 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { return cores_needing_scheduling; } -void KScheduler::SwitchThread(KThread* next_thread) { - KProcess* const cur_process = GetCurrentProcessPointer(m_kernel); - KThread* const cur_thread = GetCurrentThreadPointer(m_kernel); +void KScheduler::SwitchThread(KernelCore& kernel, KThread* next_thread) { + KProcess* const cur_process = GetCurrentProcessPointer(kernel); + KThread* const cur_thread = GetCurrentThreadPointer(kernel); // We never want to schedule a null thread, so use the idle thread if we don't have a next. if (next_thread == nullptr) { @@ -355,7 +347,7 @@ void KScheduler::SwitchThread(KThread* next_thread) { // Update the CPU time tracking variables. const s64 prev_tick = m_last_context_switch_time; - const s64 cur_tick = m_kernel.System().CoreTiming().GetClockTicks(); + const s64 cur_tick = kernel.System().CoreTiming().GetClockTicks(); const s64 tick_diff = cur_tick - prev_tick; cur_thread->AddCpuTime(m_core_id, tick_diff); if (cur_process != nullptr) { @@ -379,23 +371,23 @@ void KScheduler::SwitchThread(KThread* next_thread) { // } // Set the new thread. - SetCurrentThread(m_kernel, next_thread); + SetCurrentThread(kernel, next_thread); m_current_thread = next_thread; // Set the new Thread Local region. // cpu::SwitchThreadLocalRegion(GetInteger(next_thread->GetThreadLocalRegionAddress())); // Update the thread's cpu time differential in TLS, if relevant. - next_thread->UpdateTlsThreadCpuTime(m_kernel, cur_tick); + next_thread->UpdateTlsThreadCpuTime(kernel, cur_tick); } -void KScheduler::ScheduleImpl() { +void KScheduler::ScheduleImpl(KernelCore& kernel) { // First, clear the needs scheduling bool. m_state.needs_scheduling.store(false, std::memory_order_relaxed); std::atomic_thread_fence(std::memory_order_seq_cst); // Load the appropriate thread pointers for scheduling. - KThread* const cur_thread{GetCurrentThreadPointer(m_kernel)}; + KThread* const cur_thread{GetCurrentThreadPointer(kernel)}; KThread* highest_priority_thread{m_state.highest_priority_thread}; // Check whether there are runnable interrupt tasks. @@ -423,7 +415,7 @@ void KScheduler::ScheduleImpl() { // Returning from ScheduleImpl occurs after this thread has been scheduled again. } -void KScheduler::ScheduleImplFiber() { +void KScheduler::ScheduleImplFiber(KernelCore& kernel) { KThread* const cur_thread{m_switch_cur_thread}; KThread* highest_priority_thread{m_switch_highest_priority_thread}; @@ -437,7 +429,7 @@ void KScheduler::ScheduleImplFiber() { m_switch_from_schedule = false; // Save the original thread context. - Unload(cur_thread); + Unload(kernel, cur_thread); // The current thread's context has been entirely taken care of. // Now we want to loop until we successfully switch the thread context. @@ -468,7 +460,7 @@ void KScheduler::ScheduleImplFiber() { // It's time to switch the thread. // Switch to the highest priority thread. - SwitchThread(highest_priority_thread); + SwitchThread(kernel, highest_priority_thread); // Check if we need scheduling. If we do, then we can't complete the switch and should // retry. @@ -493,14 +485,14 @@ void KScheduler::ScheduleImplFiber() { } // Reload the guest thread context. - Reload(highest_priority_thread); + Reload(kernel, highest_priority_thread); // Reload the host thread. Common::Fiber::YieldTo(m_switch_fiber, *highest_priority_thread->m_host_context); } -void KScheduler::Unload(KThread* thread) { - m_kernel.PhysicalCore(m_core_id).SaveContext(thread); +void KScheduler::Unload(KernelCore& kernel, KThread* thread) { + kernel.PhysicalCore(m_core_id).SaveContext(thread); // Check if the thread is terminated by checking the DPC flags. if ((thread->GetStackParameters().dpc_flags & static_cast(DpcFlag::Terminated)) == 0) { @@ -509,8 +501,8 @@ void KScheduler::Unload(KThread* thread) { } } -void KScheduler::Reload(KThread* thread) { - m_kernel.PhysicalCore(m_core_id).LoadContext(thread); +void KScheduler::Reload(KernelCore& kernel, KThread* thread) { + kernel.PhysicalCore(m_core_id).LoadContext(thread); } void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) { @@ -877,9 +869,9 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) { } } -void KScheduler::RescheduleOtherCores(u64 cores_needing_scheduling) { +void KScheduler::RescheduleOtherCores(KernelCore& kernel, u64 cores_needing_scheduling) { if (const u64 core_mask = cores_needing_scheduling & ~(1ULL << m_core_id); core_mask != 0) { - RescheduleCores(m_kernel, core_mask); + RescheduleCores(kernel, core_mask); } } diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h index d85a0c0408..5a896fd899 100644 --- a/src/core/hle/kernel/k_scheduler.h +++ b/src/core/hle/kernel/k_scheduler.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -41,15 +44,15 @@ public: explicit KScheduler(KernelCore& kernel); ~KScheduler(); - void Initialize(KThread* main_thread, KThread* idle_thread, s32 core_id); - void Activate(); - void OnThreadStart(); - void Unload(KThread* thread); - void Reload(KThread* thread); + void Initialize(KernelCore& kernel, KThread* main_thread, KThread* idle_thread, s32 core_id); + void Activate(KernelCore& kernel); + void OnThreadStart(KernelCore& kernel); + void Unload(KernelCore& kernel, KThread* thread); + void Reload(KernelCore& kernel, KThread* thread); - void SetInterruptTaskRunnable(); - void RequestScheduleOnInterrupt(); - void PreemptSingleCore(); + void SetInterruptTaskRunnable(KernelCore& kernel); + void RequestScheduleOnInterrupt(KernelCore& kernel); + void PreemptSingleCore(KernelCore& kernel); u64 GetIdleCount() { return m_state.idle_count; @@ -122,18 +125,18 @@ private: static void RescheduleCurrentHLEThread(KernelCore& kernel); // Instanced private API. - void ScheduleImpl(); - void ScheduleImplFiber(); - void SwitchThread(KThread* next_thread); + void ScheduleImpl(KernelCore& kernel); + void ScheduleImplFiber(KernelCore& kernel); + void SwitchThread(KernelCore& kernel, KThread* next_thread); - void Schedule(); - void ScheduleOnInterrupt(); + void Schedule(KernelCore& kernel); + void ScheduleOnInterrupt(KernelCore& kernel); - void RescheduleOtherCores(u64 cores_needing_scheduling); - void RescheduleCurrentCore(); - void RescheduleCurrentCoreImpl(); + void RescheduleOtherCores(KernelCore& kernel, u64 cores_needing_scheduling); + void RescheduleCurrentCore(KernelCore& kernel); + void RescheduleCurrentCoreImpl(KernelCore& kernel); - u64 UpdateHighestPriorityThread(KThread* thread); + u64 UpdateHighestPriorityThread(KernelCore& kernel, KThread* thread); private: friend class KScopedDisableDispatch; @@ -149,14 +152,12 @@ private: KInterruptTaskManager* interrupt_task_manager{nullptr}; }; - KernelCore& m_kernel; SchedulingState m_state; bool m_is_active{false}; s32 m_core_id{0}; s64 m_last_context_switch_time{0}; KThread* m_idle_thread{nullptr}; std::atomic m_current_thread{nullptr}; - std::shared_ptr m_switch_fiber{}; KThread* m_switch_cur_thread{}; KThread* m_switch_highest_priority_thread{}; diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 94ad214af1..b499bd4073 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -287,37 +287,27 @@ namespace Kernel { } Result KThread::InitializeMainThread(Core::System& system, KThread* thread, s32 virt_core) { - R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, - ThreadType::Main, system.GetCpuManager().GetGuestActivateFunc())); + R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, system.GetCpuManager().GetGuestActivateFunc(system.Kernel()))); } Result KThread::InitializeIdleThread(Core::System& system, KThread* thread, s32 virt_core) { - R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, - ThreadType::Main, system.GetCpuManager().GetIdleThreadStartFunc())); + R_RETURN(InitializeThread(system.Kernel(), thread, {}, {}, {}, IdleThreadPriority, virt_core, {}, ThreadType::Main, system.GetCpuManager().GetIdleThreadStartFunc(system.Kernel()))); } - Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, - KThreadFunction func, uintptr_t arg, s32 virt_core) { - R_RETURN(InitializeThread(system.Kernel(), thread, func, arg, {}, {}, virt_core, nullptr, - ThreadType::HighPriority, - system.GetCpuManager().GetShutdownThreadStartFunc())); + Result KThread::InitializeHighPriorityThread(Core::System& system, KThread* thread, KThreadFunction func, uintptr_t arg, s32 virt_core) { + R_RETURN(InitializeThread(system.Kernel(), thread, func, arg, {}, {}, virt_core, nullptr, ThreadType::HighPriority, system.GetCpuManager().GetShutdownThreadStartFunc(system.Kernel()))); } - Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func, - uintptr_t arg, KProcessAddress user_stack_top, s32 prio, - s32 virt_core, KProcess* owner) { + Result KThread::InitializeUserThread(Core::System& system, KThread* thread, KThreadFunction func, uintptr_t arg, KProcessAddress user_stack_top, s32 prio, s32 virt_core, KProcess* owner) { system.Kernel().GlobalSchedulerContext().AddThread(thread); - R_RETURN(InitializeThread(system.Kernel(), thread, func, arg, user_stack_top, prio, virt_core, owner, - ThreadType::User, system.GetCpuManager().GetGuestThreadFunc())); + R_RETURN(InitializeThread(system.Kernel(), thread, func, arg, user_stack_top, prio, virt_core, owner, ThreadType::User, system.GetCpuManager().GetGuestThreadFunc(system.Kernel()))); } - Result KThread::InitializeServiceThread(Core::System& system, KThread* thread, - std::function&& func, s32 prio, s32 virt_core, - KProcess* owner) { + Result KThread::InitializeServiceThread(Core::System& system, KThread* thread, std::function&& func, s32 prio, s32 virt_core, KProcess* owner) { system.Kernel().GlobalSchedulerContext().AddThread(thread); std::function func2{[&system, func_{std::move(func)}] { // Similar to UserModeThreadStarter. - system.Kernel().CurrentScheduler()->OnThreadStart(); + system.Kernel().CurrentScheduler()->OnThreadStart(system.Kernel()); // Run the guest function. func_(); @@ -1449,7 +1439,7 @@ namespace Kernel { auto* scheduler = m_kernel.CurrentScheduler(); if (scheduler && !m_kernel.IsPhantomModeForSingleCore()) { - scheduler->RescheduleCurrentCore(); + scheduler->RescheduleCurrentCore(m_kernel); } else { KScheduler::RescheduleCurrentHLEThread(m_kernel); } diff --git a/src/core/hle/kernel/k_thread_queue.h b/src/core/hle/kernel/k_thread_queue.h index 371efc9d95..953bb78ac6 100644 --- a/src/core/hle/kernel/k_thread_queue.h +++ b/src/core/hle/kernel/k_thread_queue.h @@ -15,7 +15,7 @@ class KHardwareTimer; class KThreadQueue { public: - explicit KThreadQueue(KernelCore& kernel) : m_kernel{kernel}, m_hardware_timer{} {} + explicit KThreadQueue(KernelCore& kernel) : m_hardware_timer{} {} virtual ~KThreadQueue() = default; void SetHardwareTimer(KHardwareTimer* timer) { @@ -27,7 +27,6 @@ public: virtual void CancelWait(KernelCore& kernel, KThread* waiting_thread, Result wait_result, bool cancel_timer_task); private: - KernelCore& m_kernel; KHardwareTimer* m_hardware_timer{}; }; diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b5d6489ea7..6574e902be 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -226,7 +226,7 @@ struct KernelCore::Impl { ASSERT(Kernel::KThread::InitializeIdleThread(system, idle_thread, core).IsSuccess()); KThread::Register(system.Kernel(), idle_thread); - schedulers[i]->Initialize(main_thread, idle_thread, core); + schedulers[i]->Initialize(system.Kernel(), main_thread, idle_thread, core); } }