hle: kernel: Move single core "phantom mode" out of KThread.

- This is a workaround that does not belong in a kernel primitive.
master
bunnei 2020-12-31 02:13:02 +07:00
parent eea346ba8e
commit 4782985013
4 changed files with 31 additions and 16 deletions

@ -217,9 +217,9 @@ void CpuManager::SingleCoreRunGuestLoop() {
physical_core = &kernel.CurrentPhysicalCore(); physical_core = &kernel.CurrentPhysicalCore();
} }
system.ExitDynarmicProfile(); system.ExitDynarmicProfile();
thread->SetPhantomMode(true); kernel.SetIsPhantomModeForSingleCore(true);
system.CoreTiming().Advance(); system.CoreTiming().Advance();
thread->SetPhantomMode(false); kernel.SetIsPhantomModeForSingleCore(false);
physical_core->ArmInterface().ClearExclusiveState(); physical_core->ArmInterface().ClearExclusiveState();
PreemptSingleCore(); PreemptSingleCore();
auto& scheduler = kernel.Scheduler(current_core); auto& scheduler = kernel.Scheduler(current_core);
@ -255,22 +255,23 @@ void CpuManager::SingleCoreRunSuspendThread() {
void CpuManager::PreemptSingleCore(bool from_running_enviroment) { void CpuManager::PreemptSingleCore(bool from_running_enviroment) {
{ {
auto& scheduler = system.Kernel().Scheduler(current_core); auto& kernel = system.Kernel();
auto& scheduler = kernel.Scheduler(current_core);
Kernel::KThread* current_thread = scheduler.GetCurrentThread(); Kernel::KThread* current_thread = scheduler.GetCurrentThread();
if (idle_count >= 4 || from_running_enviroment) { if (idle_count >= 4 || from_running_enviroment) {
if (!from_running_enviroment) { if (!from_running_enviroment) {
system.CoreTiming().Idle(); system.CoreTiming().Idle();
idle_count = 0; idle_count = 0;
} }
current_thread->SetPhantomMode(true); kernel.SetIsPhantomModeForSingleCore(true);
system.CoreTiming().Advance(); system.CoreTiming().Advance();
current_thread->SetPhantomMode(false); kernel.SetIsPhantomModeForSingleCore(false);
} }
current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES); current_core.store((current_core + 1) % Core::Hardware::NUM_CPU_CORES);
system.CoreTiming().ResetTicks(); system.CoreTiming().ResetTicks();
scheduler.Unload(scheduler.GetCurrentThread()); scheduler.Unload(scheduler.GetCurrentThread());
auto& next_scheduler = system.Kernel().Scheduler(current_core); auto& next_scheduler = kernel.Scheduler(current_core);
Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext()); Common::Fiber::YieldTo(current_thread->GetHostContext(), next_scheduler.ControlContext());
} }

@ -451,14 +451,6 @@ public:
is_continuous_on_svc = is_continuous; is_continuous_on_svc = is_continuous;
} }
bool IsPhantomMode() const {
return is_phantom_mode;
}
void SetPhantomMode(bool phantom) {
is_phantom_mode = phantom;
}
bool HasExited() const { bool HasExited() const {
return has_exited; return has_exited;
} }
@ -747,7 +739,6 @@ private:
bool is_continuous_on_svc = false; bool is_continuous_on_svc = false;
bool will_be_terminated = false; bool will_be_terminated = false;
bool is_phantom_mode = false;
bool has_exited = false; bool has_exited = false;
bool was_running = false; bool was_running = false;

@ -62,6 +62,7 @@ struct KernelCore::Impl {
global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
service_thread_manager = service_thread_manager =
std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager"); std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager");
is_phantom_mode_for_singlecore = false;
InitializePhysicalCores(); InitializePhysicalCores();
InitializeSystemResourceLimit(kernel); InitializeSystemResourceLimit(kernel);
@ -227,6 +228,15 @@ struct KernelCore::Impl {
return this_id; return this_id;
} }
bool IsPhantomModeForSingleCore() const {
return is_phantom_mode_for_singlecore;
}
void SetIsPhantomModeForSingleCore(bool value) {
ASSERT(!is_multicore);
is_phantom_mode_for_singlecore = value;
}
[[nodiscard]] Core::EmuThreadHandle GetCurrentEmuThreadID() { [[nodiscard]] Core::EmuThreadHandle GetCurrentEmuThreadID() {
Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle(); Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
result.host_handle = GetCurrentHostThreadID(); result.host_handle = GetCurrentHostThreadID();
@ -235,7 +245,7 @@ struct KernelCore::Impl {
} }
const Kernel::KScheduler& sched = cores[result.host_handle].Scheduler(); const Kernel::KScheduler& sched = cores[result.host_handle].Scheduler();
const Kernel::KThread* current = sched.GetCurrentThread(); const Kernel::KThread* current = sched.GetCurrentThread();
if (current != nullptr && !current->IsPhantomMode()) { if (current != nullptr && !IsPhantomModeForSingleCore()) {
result.guest_handle = current->GetGlobalHandle(); result.guest_handle = current->GetGlobalHandle();
} else { } else {
result.guest_handle = InvalidHandle; result.guest_handle = InvalidHandle;
@ -345,6 +355,7 @@ struct KernelCore::Impl {
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
bool is_multicore{}; bool is_multicore{};
bool is_phantom_mode_for_singlecore{};
u32 single_core_thread_id{}; u32 single_core_thread_id{};
std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{}; std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{};
@ -643,4 +654,12 @@ void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> servi
}); });
} }
bool KernelCore::IsPhantomModeForSingleCore() const {
return impl->IsPhantomModeForSingleCore();
}
void KernelCore::SetIsPhantomModeForSingleCore(bool value) {
impl->SetIsPhantomModeForSingleCore(value);
}
} // namespace Kernel } // namespace Kernel

@ -237,6 +237,10 @@ public:
*/ */
void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread); void ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> service_thread);
/// Workaround for single-core mode when preempting threads while idle.
bool IsPhantomModeForSingleCore() const;
void SetIsPhantomModeForSingleCore(bool value);
private: private:
friend class Object; friend class Object;
friend class Process; friend class Process;