Kernel: Preempt Single core on redudant yields.
This commit is contained in:
parent
a439cdf22e
commit
d494b074e8
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue