diff options
| author | 2018-12-15 00:28:12 -0500 | |
|---|---|---|
| committer | 2018-12-15 00:28:12 -0500 | |
| commit | 2f2fc47af23708f4a79c1e3b554aafd84a32f7db (patch) | |
| tree | 02114974dac4e65b2a1a011c7cad68b32a6a6a47 /src/core/hle/kernel/svc.cpp | |
| parent | Merge pull request #1902 from lioncash/audio (diff) | |
| parent | svc: Avoid incorrect fast yield condition (diff) | |
| download | yuzu-2f2fc47af23708f4a79c1e3b554aafd84a32f7db.tar.gz yuzu-2f2fc47af23708f4a79c1e3b554aafd84a32f7db.tar.xz yuzu-2f2fc47af23708f4a79c1e3b554aafd84a32f7db.zip | |
Merge pull request #1732 from DarkLordZach/yield-types
svc: Implement yield types 0 and -1
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 5d36792ca..348a22904 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -1208,18 +1208,38 @@ static void ExitThread() { | |||
| 1208 | static void SleepThread(s64 nanoseconds) { | 1208 | static void SleepThread(s64 nanoseconds) { |
| 1209 | LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); | 1209 | LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); |
| 1210 | 1210 | ||
| 1211 | // Don't attempt to yield execution if there are no available threads to run, | 1211 | enum class SleepType : s64 { |
| 1212 | // this way we avoid a useless reschedule to the idle thread. | 1212 | YieldWithoutLoadBalancing = 0, |
| 1213 | if (nanoseconds == 0 && !Core::System::GetInstance().CurrentScheduler().HaveReadyThreads()) | 1213 | YieldWithLoadBalancing = -1, |
| 1214 | return; | 1214 | YieldAndWaitForLoadBalancing = -2, |
| 1215 | }; | ||
| 1215 | 1216 | ||
| 1216 | // Sleep current thread and check for next thread to schedule | 1217 | if (nanoseconds <= 0) { |
| 1217 | WaitCurrentThread_Sleep(); | 1218 | auto& scheduler{Core::System::GetInstance().CurrentScheduler()}; |
| 1219 | switch (static_cast<SleepType>(nanoseconds)) { | ||
| 1220 | case SleepType::YieldWithoutLoadBalancing: | ||
| 1221 | scheduler.YieldWithoutLoadBalancing(GetCurrentThread()); | ||
| 1222 | break; | ||
| 1223 | case SleepType::YieldWithLoadBalancing: | ||
| 1224 | scheduler.YieldWithLoadBalancing(GetCurrentThread()); | ||
| 1225 | break; | ||
| 1226 | case SleepType::YieldAndWaitForLoadBalancing: | ||
| 1227 | scheduler.YieldAndWaitForLoadBalancing(GetCurrentThread()); | ||
| 1228 | break; | ||
| 1229 | default: | ||
| 1230 | UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds); | ||
| 1231 | } | ||
| 1232 | } else { | ||
| 1233 | // Sleep current thread and check for next thread to schedule | ||
| 1234 | WaitCurrentThread_Sleep(); | ||
| 1218 | 1235 | ||
| 1219 | // Create an event to wake the thread up after the specified nanosecond delay has passed | 1236 | // Create an event to wake the thread up after the specified nanosecond delay has passed |
| 1220 | GetCurrentThread()->WakeAfterDelay(nanoseconds); | 1237 | GetCurrentThread()->WakeAfterDelay(nanoseconds); |
| 1238 | } | ||
| 1221 | 1239 | ||
| 1222 | Core::System::GetInstance().PrepareReschedule(); | 1240 | // Reschedule all CPU cores |
| 1241 | for (std::size_t i = 0; i < Core::NUM_CPU_CORES; ++i) | ||
| 1242 | Core::System::GetInstance().CpuCore(i).PrepareReschedule(); | ||
| 1223 | } | 1243 | } |
| 1224 | 1244 | ||
| 1225 | /// Wait process wide key atomic | 1245 | /// Wait process wide key atomic |