From 409dcf0e0aecfdb676fd3b64223a25e47c1b1c1a Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 18 Nov 2018 23:44:19 -0500 Subject: svc: Implement yield types 0 and -1 --- src/core/hle/kernel/svc.cpp | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 75dbfc31d..467575c93 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -962,16 +962,39 @@ static void SleepThread(s64 nanoseconds) { // Don't attempt to yield execution if there are no available threads to run, // this way we avoid a useless reschedule to the idle thread. - if (nanoseconds == 0 && !Core::System::GetInstance().CurrentScheduler().HaveReadyThreads()) + if (!Core::System::GetInstance().CurrentScheduler().HaveReadyThreads()) return; + if (nanoseconds <= 0) { + switch (nanoseconds) { + case 0: + GetCurrentThread()->YieldNormal(); + break; + case -1: + GetCurrentThread()->YieldWithLoadBalancing(); + break; + case -2: + GetCurrentThread()->YieldAndWaitForLoadBalancing(); + break; + default: + UNREACHABLE_MSG( + "Unimplemented sleep yield type '{:016X}'! Falling back to forced reschedule...", + nanoseconds); + } + + nanoseconds = 0; + } + // Sleep current thread and check for next thread to schedule WaitCurrentThread_Sleep(); // Create an event to wake the thread up after the specified nanosecond delay has passed GetCurrentThread()->WakeAfterDelay(nanoseconds); - Core::System::GetInstance().PrepareReschedule(); + Core::System::GetInstance().CpuCore(0).PrepareReschedule(); + Core::System::GetInstance().CpuCore(1).PrepareReschedule(); + Core::System::GetInstance().CpuCore(2).PrepareReschedule(); + Core::System::GetInstance().CpuCore(3).PrepareReschedule(); } /// Wait process wide key atomic -- cgit v1.2.3 From 820d81b9a5392951c18daa5a47d6c0ffd28baa9b Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Thu, 22 Nov 2018 00:33:53 -0500 Subject: scheduler: Add explanations for YieldWith and WithoutLoadBalancing --- src/core/hle/kernel/svc.cpp | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 467575c93..205706033 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -965,16 +965,23 @@ static void SleepThread(s64 nanoseconds) { if (!Core::System::GetInstance().CurrentScheduler().HaveReadyThreads()) return; + enum class SleepType : s64 { + YieldWithoutLoadBalancing = 0, + YieldWithLoadBalancing = 1, + YieldAndWaitForLoadBalancing = 2, + }; + if (nanoseconds <= 0) { - switch (nanoseconds) { - case 0: - GetCurrentThread()->YieldNormal(); + auto& scheduler{Core::System::GetInstance().CurrentScheduler()}; + switch (static_cast(nanoseconds)) { + case SleepType::YieldWithoutLoadBalancing: + scheduler.YieldWithoutLoadBalancing(GetCurrentThread()); break; - case -1: - GetCurrentThread()->YieldWithLoadBalancing(); + case SleepType::YieldWithLoadBalancing: + scheduler.YieldWithLoadBalancing(GetCurrentThread()); break; - case -2: - GetCurrentThread()->YieldAndWaitForLoadBalancing(); + case SleepType::YieldAndWaitForLoadBalancing: + scheduler.YieldAndWaitForLoadBalancing(GetCurrentThread()); break; default: UNREACHABLE_MSG( -- cgit v1.2.3 From 3476830b26b61410b633c827e985bffa1dc52528 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Sun, 2 Dec 2018 00:44:40 -0500 Subject: svc: Avoid performance-degrading unnecessary reschedule --- src/core/hle/kernel/svc.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 205706033..c119f7be1 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -962,13 +962,13 @@ static void SleepThread(s64 nanoseconds) { // Don't attempt to yield execution if there are no available threads to run, // this way we avoid a useless reschedule to the idle thread. - if (!Core::System::GetInstance().CurrentScheduler().HaveReadyThreads()) + if (nanoseconds <= 0 && !Core::System::GetInstance().CurrentScheduler().HaveReadyThreads()) return; enum class SleepType : s64 { YieldWithoutLoadBalancing = 0, - YieldWithLoadBalancing = 1, - YieldAndWaitForLoadBalancing = 2, + YieldWithLoadBalancing = -1, + YieldAndWaitForLoadBalancing = -2, }; if (nanoseconds <= 0) { @@ -998,10 +998,7 @@ static void SleepThread(s64 nanoseconds) { // Create an event to wake the thread up after the specified nanosecond delay has passed GetCurrentThread()->WakeAfterDelay(nanoseconds); - Core::System::GetInstance().CpuCore(0).PrepareReschedule(); - Core::System::GetInstance().CpuCore(1).PrepareReschedule(); - Core::System::GetInstance().CpuCore(2).PrepareReschedule(); - Core::System::GetInstance().CpuCore(3).PrepareReschedule(); + Core::System::GetInstance().PrepareReschedule(); } /// Wait process wide key atomic -- cgit v1.2.3 From b5af41a07bebc0a378428e7d7ddc68c9c750d2d1 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 3 Dec 2018 17:29:21 -0500 Subject: scheduler: Only work steal higher priority threads from other cores --- src/core/hle/kernel/svc.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index c119f7be1..fabdedd3d 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -984,20 +984,16 @@ static void SleepThread(s64 nanoseconds) { scheduler.YieldAndWaitForLoadBalancing(GetCurrentThread()); break; default: - UNREACHABLE_MSG( - "Unimplemented sleep yield type '{:016X}'! Falling back to forced reschedule...", - nanoseconds); + UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); } + } else { + // Sleep current thread and check for next thread to schedule + WaitCurrentThread_Sleep(); - nanoseconds = 0; + // Create an event to wake the thread up after the specified nanosecond delay has passed + GetCurrentThread()->WakeAfterDelay(nanoseconds); } - // Sleep current thread and check for next thread to schedule - WaitCurrentThread_Sleep(); - - // Create an event to wake the thread up after the specified nanosecond delay has passed - GetCurrentThread()->WakeAfterDelay(nanoseconds); - Core::System::GetInstance().PrepareReschedule(); } -- cgit v1.2.3 From ddf5903cd9c05f1fecd8a5b8e8ad702b9b20eef8 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Mon, 3 Dec 2018 21:22:09 -0500 Subject: scheduler: Avoid manual Reschedule call This will automatically occur anyway when PrepareReschedule is called --- src/core/hle/kernel/svc.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index fabdedd3d..29c2c2d03 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -994,7 +994,9 @@ static void SleepThread(s64 nanoseconds) { GetCurrentThread()->WakeAfterDelay(nanoseconds); } - Core::System::GetInstance().PrepareReschedule(); + // Reschedule all CPU cores + for (std::size_t i = 0; i < 4; ++i) + Core::System::GetInstance().CpuCore(i).PrepareReschedule(); } /// Wait process wide key atomic -- cgit v1.2.3 From e6f7825a248dd0ff9f2e3fdccabdbe3631622861 Mon Sep 17 00:00:00 2001 From: Zach Hilman Date: Tue, 4 Dec 2018 22:11:32 -0500 Subject: svc: Avoid incorrect fast yield condition --- src/core/hle/kernel/svc.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/core/hle/kernel/svc.cpp') diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 29c2c2d03..e3cf3f909 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -960,11 +960,6 @@ static void ExitThread() { static void SleepThread(s64 nanoseconds) { LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); - // Don't attempt to yield execution if there are no available threads to run, - // this way we avoid a useless reschedule to the idle thread. - if (nanoseconds <= 0 && !Core::System::GetInstance().CurrentScheduler().HaveReadyThreads()) - return; - enum class SleepType : s64 { YieldWithoutLoadBalancing = 0, YieldWithLoadBalancing = -1, @@ -995,7 +990,7 @@ static void SleepThread(s64 nanoseconds) { } // Reschedule all CPU cores - for (std::size_t i = 0; i < 4; ++i) + for (std::size_t i = 0; i < Core::NUM_CPU_CORES; ++i) Core::System::GetInstance().CpuCore(i).PrepareReschedule(); } -- cgit v1.2.3