summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/kernel.cpp4
-rw-r--r--src/core/hle/kernel/kernel.h2
-rw-r--r--src/core/hle/kernel/svc.cpp23
-rw-r--r--src/core/hle/kernel/thread.cpp21
-rw-r--r--src/core/hle/kernel/thread.h9
5 files changed, 40 insertions, 19 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 4a091ea38..2a1b91752 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -642,6 +642,10 @@ void KernelCore::Suspend(bool in_suspention) {
}
}
+bool KernelCore::IsMulticore() const {
+ return impl->is_multicore;
+}
+
void KernelCore::ExceptionalExit() {
exception_exited = true;
Suspend(true);
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 162bbd2f8..50eeb50ec 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -212,6 +212,8 @@ public:
/// Exceptional exit the OS.
void ExceptionalExit();
+ bool IsMulticore() const;
+
private:
friend class Object;
friend class Process;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index aad2ac549..eca92b356 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -19,6 +19,7 @@
#include "core/core_manager.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
+#include "core/cpu_manager.h"
#include "core/hle/kernel/address_arbiter.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
@@ -1509,21 +1510,31 @@ static void SleepThread(Core::System& system, s64 nanoseconds) {
if (nanoseconds <= 0) {
switch (static_cast<SleepType>(nanoseconds)) {
- case SleepType::YieldWithoutLoadBalancing:
- current_thread->YieldSimple();
+ case SleepType::YieldWithoutLoadBalancing: {
+ auto pair = current_thread->YieldSimple();
+ is_redundant = pair.second;
break;
- case SleepType::YieldWithLoadBalancing:
- current_thread->YieldAndBalanceLoad();
+ }
+ case SleepType::YieldWithLoadBalancing: {
+ auto pair = current_thread->YieldAndBalanceLoad();
+ is_redundant = pair.second;
break;
- case SleepType::YieldAndWaitForLoadBalancing:
- current_thread->YieldAndWaitForLoadBalancing();
+ }
+ case SleepType::YieldAndWaitForLoadBalancing: {
+ auto pair = current_thread->YieldAndWaitForLoadBalancing();
+ is_redundant = pair.second;
break;
+ }
default:
UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
}
} else {
current_thread->Sleep(nanoseconds);
}
+
+ if (is_redundant && !system.Kernel().IsMulticore()) {
+ system.GetCpuManager().PreemptSingleCore();
+ }
}
/// Wait process wide key atomic
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index fc6c0bc85..1c32552b1 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -435,28 +435,31 @@ ResultCode Thread::Sleep(s64 nanoseconds) {
return RESULT_SUCCESS;
}
-ResultCode Thread::YieldSimple() {
+std::pair<ResultCode, bool> Thread::YieldSimple() {
+ bool is_redundant = false;
{
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);
- 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);
- kernel.GlobalScheduler().YieldThreadAndWaitForLoadBalancing(this);
+ is_redundant = kernel.GlobalScheduler().YieldThreadAndWaitForLoadBalancing(this);
}
- return RESULT_SUCCESS;
+ return {RESULT_SUCCESS, is_redundant};
}
void Thread::AddSchedulingFlag(ThreadSchedFlags flag) {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 953b023b5..9a29875ac 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -6,6 +6,7 @@
#include <functional>
#include <string>
+#include <utility>
#include <vector>
#include "common/common_types.h"
@@ -503,13 +504,13 @@ public:
ResultCode Sleep(s64 nanoseconds);
/// Yields this thread without rebalancing loads.
- ResultCode YieldSimple();
+ std::pair<ResultCode, bool> YieldSimple();
/// 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
- ResultCode YieldAndWaitForLoadBalancing();
+ std::pair<ResultCode, bool> YieldAndWaitForLoadBalancing();
void IncrementYieldCount() {
yield_count++;
@@ -587,7 +588,7 @@ private:
ThreadContext32 context_32{};
ThreadContext64 context_64{};
Common::SpinLock context_guard{};
- std::shared_ptr<Common::Fiber> host_context{};
+ std::shared_ptr<Common::Fiber> host_context{};
u64 thread_id = 0;