yuzu-emu
/
yuzu
Archived
1
0
Fork 0

Kernel: Preempt Single core on redudant yields.

This commit is contained in:
Fernando Sahmkow 2020-03-10 13:13:39 -04:00
parent a439cdf22e
commit d494b074e8
6 changed files with 42 additions and 21 deletions

View File

@ -45,6 +45,8 @@ public:
std::function<void(void*)> GetSuspendThreadStartFunc(); std::function<void(void*)> GetSuspendThreadStartFunc();
void* GetStartFuncParamater(); void* GetStartFuncParamater();
void PreemptSingleCore();
std::size_t CurrentCore() const { std::size_t CurrentCore() const {
return current_core.load(); return current_core.load();
} }
@ -71,8 +73,6 @@ private:
void RunThread(std::size_t core); void RunThread(std::size_t core);
void PreemptSingleCore();
struct CoreData { struct CoreData {
std::shared_ptr<Common::Fiber> host_context; std::shared_ptr<Common::Fiber> host_context;
std::unique_ptr<Common::Event> enter_barrier; std::unique_ptr<Common::Event> enter_barrier;

View File

@ -642,6 +642,10 @@ void KernelCore::Suspend(bool in_suspention) {
} }
} }
bool KernelCore::IsMulticore() const {
return impl->is_multicore;
}
void KernelCore::ExceptionalExit() { void KernelCore::ExceptionalExit() {
exception_exited = true; exception_exited = true;
Suspend(true); Suspend(true);

View File

@ -212,6 +212,8 @@ public:
/// Exceptional exit the OS. /// Exceptional exit the OS.
void ExceptionalExit(); void ExceptionalExit();
bool IsMulticore() const;
private: private:
friend class Object; friend class Object;
friend class Process; friend class Process;

View File

@ -19,6 +19,7 @@
#include "core/core_manager.h" #include "core/core_manager.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/core_timing_util.h" #include "core/core_timing_util.h"
#include "core/cpu_manager.h"
#include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/address_arbiter.h"
#include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h" #include "core/hle/kernel/client_session.h"
@ -1509,21 +1510,31 @@ static void SleepThread(Core::System& system, s64 nanoseconds) {
if (nanoseconds <= 0) { if (nanoseconds <= 0) {
switch (static_cast<SleepType>(nanoseconds)) { switch (static_cast<SleepType>(nanoseconds)) {
case SleepType::YieldWithoutLoadBalancing: case SleepType::YieldWithoutLoadBalancing: {
current_thread->YieldSimple(); auto pair = current_thread->YieldSimple();
is_redundant = pair.second;
break; break;
case SleepType::YieldWithLoadBalancing: }
current_thread->YieldAndBalanceLoad(); case SleepType::YieldWithLoadBalancing: {
auto pair = current_thread->YieldAndBalanceLoad();
is_redundant = pair.second;
break; break;
case SleepType::YieldAndWaitForLoadBalancing: }
current_thread->YieldAndWaitForLoadBalancing(); case SleepType::YieldAndWaitForLoadBalancing: {
auto pair = current_thread->YieldAndWaitForLoadBalancing();
is_redundant = pair.second;
break; break;
}
default: default:
UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
} }
} else { } else {
current_thread->Sleep(nanoseconds); current_thread->Sleep(nanoseconds);
} }
if (is_redundant && !system.Kernel().IsMulticore()) {
system.GetCpuManager().PreemptSingleCore();
}
} }
/// Wait process wide key atomic /// Wait process wide key atomic

View File

@ -435,28 +435,31 @@ ResultCode Thread::Sleep(s64 nanoseconds) {
return RESULT_SUCCESS; return RESULT_SUCCESS;
} }
ResultCode Thread::YieldSimple() { std::pair<ResultCode, bool> Thread::YieldSimple() {
bool is_redundant = false;
{ {
SchedulerLock lock(kernel); SchedulerLock lock(kernel);
kernel.GlobalScheduler().YieldThread(this); is_redundant = kernel.GlobalScheduler().YieldThread(this);
} }
return RESULT_SUCCESS; return {RESULT_SUCCESS, is_redundant};
} }
ResultCode Thread::YieldAndBalanceLoad() { std::pair<ResultCode, bool> Thread::YieldAndBalanceLoad() {
bool is_redundant = false;
{ {
SchedulerLock lock(kernel); SchedulerLock lock(kernel);
kernel.GlobalScheduler().YieldThreadAndBalanceLoad(this); is_redundant = kernel.GlobalScheduler().YieldThreadAndBalanceLoad(this);
} }
return RESULT_SUCCESS; return {RESULT_SUCCESS, is_redundant};
} }
ResultCode Thread::YieldAndWaitForLoadBalancing() { std::pair<ResultCode, bool> Thread::YieldAndWaitForLoadBalancing() {
bool is_redundant = false;
{ {
SchedulerLock lock(kernel); SchedulerLock lock(kernel);
kernel.GlobalScheduler().YieldThreadAndWaitForLoadBalancing(this); is_redundant = kernel.GlobalScheduler().YieldThreadAndWaitForLoadBalancing(this);
} }
return RESULT_SUCCESS; return {RESULT_SUCCESS, is_redundant};
} }
void Thread::AddSchedulingFlag(ThreadSchedFlags flag) { void Thread::AddSchedulingFlag(ThreadSchedFlags flag) {

View File

@ -6,6 +6,7 @@
#include <functional> #include <functional>
#include <string> #include <string>
#include <utility>
#include <vector> #include <vector>
#include "common/common_types.h" #include "common/common_types.h"
@ -503,13 +504,13 @@ public:
ResultCode Sleep(s64 nanoseconds); ResultCode Sleep(s64 nanoseconds);
/// Yields this thread without rebalancing loads. /// Yields this thread without rebalancing loads.
ResultCode YieldSimple(); std::pair<ResultCode, bool> YieldSimple();
/// Yields this thread and does a load rebalancing. /// Yields this thread and does a load rebalancing.
ResultCode YieldAndBalanceLoad(); std::pair<ResultCode, bool> YieldAndBalanceLoad();
/// Yields this thread and if the core is left idle, loads are rebalanced /// Yields this thread and if the core is left idle, loads are rebalanced
ResultCode YieldAndWaitForLoadBalancing(); std::pair<ResultCode, bool> YieldAndWaitForLoadBalancing();
void IncrementYieldCount() { void IncrementYieldCount() {
yield_count++; yield_count++;
@ -587,7 +588,7 @@ private:
ThreadContext32 context_32{}; ThreadContext32 context_32{};
ThreadContext64 context_64{}; ThreadContext64 context_64{};
Common::SpinLock context_guard{}; Common::SpinLock context_guard{};
std::shared_ptr<Common::Fiber> host_context{}; std::shared_ptr<Common::Fiber> host_context{};
u64 thread_id = 0; u64 thread_id = 0;