diff options
| author | 2020-03-10 13:13:39 -0400 | |
|---|---|---|
| committer | 2020-06-27 11:35:45 -0400 | |
| commit | d494b074e8afd3aff7b65afc7b977496be06ccc9 (patch) | |
| tree | 002cc29d32a9b1e44e61fb1aae122715556b36c5 /src | |
| parent | CPU_Manager: Unload/Reload threads on preemption on SingleCore (diff) | |
| download | yuzu-d494b074e8afd3aff7b65afc7b977496be06ccc9.tar.gz yuzu-d494b074e8afd3aff7b65afc7b977496be06ccc9.tar.xz yuzu-d494b074e8afd3aff7b65afc7b977496be06ccc9.zip | |
Kernel: Preempt Single core on redudant yields.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/cpu_manager.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 23 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 21 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 9 |
6 files changed, 42 insertions, 21 deletions
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index ff1935d5c..c0e454a7d 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h | |||
| @@ -45,6 +45,8 @@ public: | |||
| 45 | std::function<void(void*)> GetSuspendThreadStartFunc(); | 45 | std::function<void(void*)> GetSuspendThreadStartFunc(); |
| 46 | void* GetStartFuncParamater(); | 46 | void* GetStartFuncParamater(); |
| 47 | 47 | ||
| 48 | void PreemptSingleCore(); | ||
| 49 | |||
| 48 | std::size_t CurrentCore() const { | 50 | std::size_t CurrentCore() const { |
| 49 | return current_core.load(); | 51 | return current_core.load(); |
| 50 | } | 52 | } |
| @@ -71,8 +73,6 @@ private: | |||
| 71 | 73 | ||
| 72 | void RunThread(std::size_t core); | 74 | void RunThread(std::size_t core); |
| 73 | 75 | ||
| 74 | void PreemptSingleCore(); | ||
| 75 | |||
| 76 | struct CoreData { | 76 | struct CoreData { |
| 77 | std::shared_ptr<Common::Fiber> host_context; | 77 | std::shared_ptr<Common::Fiber> host_context; |
| 78 | std::unique_ptr<Common::Event> enter_barrier; | 78 | std::unique_ptr<Common::Event> enter_barrier; |
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) { | |||
| 642 | } | 642 | } |
| 643 | } | 643 | } |
| 644 | 644 | ||
| 645 | bool KernelCore::IsMulticore() const { | ||
| 646 | return impl->is_multicore; | ||
| 647 | } | ||
| 648 | |||
| 645 | void KernelCore::ExceptionalExit() { | 649 | void KernelCore::ExceptionalExit() { |
| 646 | exception_exited = true; | 650 | exception_exited = true; |
| 647 | Suspend(true); | 651 | 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: | |||
| 212 | /// Exceptional exit the OS. | 212 | /// Exceptional exit the OS. |
| 213 | void ExceptionalExit(); | 213 | void ExceptionalExit(); |
| 214 | 214 | ||
| 215 | bool IsMulticore() const; | ||
| 216 | |||
| 215 | private: | 217 | private: |
| 216 | friend class Object; | 218 | friend class Object; |
| 217 | friend class Process; | 219 | 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 @@ | |||
| 19 | #include "core/core_manager.h" | 19 | #include "core/core_manager.h" |
| 20 | #include "core/core_timing.h" | 20 | #include "core/core_timing.h" |
| 21 | #include "core/core_timing_util.h" | 21 | #include "core/core_timing_util.h" |
| 22 | #include "core/cpu_manager.h" | ||
| 22 | #include "core/hle/kernel/address_arbiter.h" | 23 | #include "core/hle/kernel/address_arbiter.h" |
| 23 | #include "core/hle/kernel/client_port.h" | 24 | #include "core/hle/kernel/client_port.h" |
| 24 | #include "core/hle/kernel/client_session.h" | 25 | #include "core/hle/kernel/client_session.h" |
| @@ -1509,21 +1510,31 @@ static void SleepThread(Core::System& system, s64 nanoseconds) { | |||
| 1509 | 1510 | ||
| 1510 | if (nanoseconds <= 0) { | 1511 | if (nanoseconds <= 0) { |
| 1511 | switch (static_cast<SleepType>(nanoseconds)) { | 1512 | switch (static_cast<SleepType>(nanoseconds)) { |
| 1512 | case SleepType::YieldWithoutLoadBalancing: | 1513 | case SleepType::YieldWithoutLoadBalancing: { |
| 1513 | current_thread->YieldSimple(); | 1514 | auto pair = current_thread->YieldSimple(); |
| 1515 | is_redundant = pair.second; | ||
| 1514 | break; | 1516 | break; |
| 1515 | case SleepType::YieldWithLoadBalancing: | 1517 | } |
| 1516 | current_thread->YieldAndBalanceLoad(); | 1518 | case SleepType::YieldWithLoadBalancing: { |
| 1519 | auto pair = current_thread->YieldAndBalanceLoad(); | ||
| 1520 | is_redundant = pair.second; | ||
| 1517 | break; | 1521 | break; |
| 1518 | case SleepType::YieldAndWaitForLoadBalancing: | 1522 | } |
| 1519 | current_thread->YieldAndWaitForLoadBalancing(); | 1523 | case SleepType::YieldAndWaitForLoadBalancing: { |
| 1524 | auto pair = current_thread->YieldAndWaitForLoadBalancing(); | ||
| 1525 | is_redundant = pair.second; | ||
| 1520 | break; | 1526 | break; |
| 1527 | } | ||
| 1521 | default: | 1528 | default: |
| 1522 | UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); | 1529 | UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); |
| 1523 | } | 1530 | } |
| 1524 | } else { | 1531 | } else { |
| 1525 | current_thread->Sleep(nanoseconds); | 1532 | current_thread->Sleep(nanoseconds); |
| 1526 | } | 1533 | } |
| 1534 | |||
| 1535 | if (is_redundant && !system.Kernel().IsMulticore()) { | ||
| 1536 | system.GetCpuManager().PreemptSingleCore(); | ||
| 1537 | } | ||
| 1527 | } | 1538 | } |
| 1528 | 1539 | ||
| 1529 | /// Wait process wide key atomic | 1540 | /// 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) { | |||
| 435 | return RESULT_SUCCESS; | 435 | return RESULT_SUCCESS; |
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | ResultCode Thread::YieldSimple() { | 438 | std::pair<ResultCode, bool> Thread::YieldSimple() { |
| 439 | bool is_redundant = false; | ||
| 439 | { | 440 | { |
| 440 | SchedulerLock lock(kernel); | 441 | SchedulerLock lock(kernel); |
| 441 | kernel.GlobalScheduler().YieldThread(this); | 442 | is_redundant = kernel.GlobalScheduler().YieldThread(this); |
| 442 | } | 443 | } |
| 443 | return RESULT_SUCCESS; | 444 | return {RESULT_SUCCESS, is_redundant}; |
| 444 | } | 445 | } |
| 445 | 446 | ||
| 446 | ResultCode Thread::YieldAndBalanceLoad() { | 447 | std::pair<ResultCode, bool> Thread::YieldAndBalanceLoad() { |
| 448 | bool is_redundant = false; | ||
| 447 | { | 449 | { |
| 448 | SchedulerLock lock(kernel); | 450 | SchedulerLock lock(kernel); |
| 449 | kernel.GlobalScheduler().YieldThreadAndBalanceLoad(this); | 451 | is_redundant = kernel.GlobalScheduler().YieldThreadAndBalanceLoad(this); |
| 450 | } | 452 | } |
| 451 | return RESULT_SUCCESS; | 453 | return {RESULT_SUCCESS, is_redundant}; |
| 452 | } | 454 | } |
| 453 | 455 | ||
| 454 | ResultCode Thread::YieldAndWaitForLoadBalancing() { | 456 | std::pair<ResultCode, bool> Thread::YieldAndWaitForLoadBalancing() { |
| 457 | bool is_redundant = false; | ||
| 455 | { | 458 | { |
| 456 | SchedulerLock lock(kernel); | 459 | SchedulerLock lock(kernel); |
| 457 | kernel.GlobalScheduler().YieldThreadAndWaitForLoadBalancing(this); | 460 | is_redundant = kernel.GlobalScheduler().YieldThreadAndWaitForLoadBalancing(this); |
| 458 | } | 461 | } |
| 459 | return RESULT_SUCCESS; | 462 | return {RESULT_SUCCESS, is_redundant}; |
| 460 | } | 463 | } |
| 461 | 464 | ||
| 462 | void Thread::AddSchedulingFlag(ThreadSchedFlags flag) { | 465 | 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 @@ | |||
| 6 | 6 | ||
| 7 | #include <functional> | 7 | #include <functional> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <utility> | ||
| 9 | #include <vector> | 10 | #include <vector> |
| 10 | 11 | ||
| 11 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| @@ -503,13 +504,13 @@ public: | |||
| 503 | ResultCode Sleep(s64 nanoseconds); | 504 | ResultCode Sleep(s64 nanoseconds); |
| 504 | 505 | ||
| 505 | /// Yields this thread without rebalancing loads. | 506 | /// Yields this thread without rebalancing loads. |
| 506 | ResultCode YieldSimple(); | 507 | std::pair<ResultCode, bool> YieldSimple(); |
| 507 | 508 | ||
| 508 | /// Yields this thread and does a load rebalancing. | 509 | /// Yields this thread and does a load rebalancing. |
| 509 | ResultCode YieldAndBalanceLoad(); | 510 | std::pair<ResultCode, bool> YieldAndBalanceLoad(); |
| 510 | 511 | ||
| 511 | /// Yields this thread and if the core is left idle, loads are rebalanced | 512 | /// Yields this thread and if the core is left idle, loads are rebalanced |
| 512 | ResultCode YieldAndWaitForLoadBalancing(); | 513 | std::pair<ResultCode, bool> YieldAndWaitForLoadBalancing(); |
| 513 | 514 | ||
| 514 | void IncrementYieldCount() { | 515 | void IncrementYieldCount() { |
| 515 | yield_count++; | 516 | yield_count++; |
| @@ -587,7 +588,7 @@ private: | |||
| 587 | ThreadContext32 context_32{}; | 588 | ThreadContext32 context_32{}; |
| 588 | ThreadContext64 context_64{}; | 589 | ThreadContext64 context_64{}; |
| 589 | Common::SpinLock context_guard{}; | 590 | Common::SpinLock context_guard{}; |
| 590 | std::shared_ptr<Common::Fiber> host_context{}; | 591 | std::shared_ptr<Common::Fiber> host_context{}; |
| 591 | 592 | ||
| 592 | u64 thread_id = 0; | 593 | u64 thread_id = 0; |
| 593 | 594 | ||