hle: kernel: Move single core "phantom mode" out of KThread.
- This is a workaround that does not belong in a kernel primitive.
This commit is contained in:
parent
eea346ba8e
commit
4782985013
|
@ -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;
|
||||||
|
|
Reference in New Issue