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/scheduler.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/scheduler.cpp')
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index 5a5f4cef1..df4d6cf0a 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "common/logging/log.h" | 9 | #include "common/logging/log.h" |
| 10 | #include "core/arm/arm_interface.h" | 10 | #include "core/arm/arm_interface.h" |
| 11 | #include "core/core.h" | 11 | #include "core/core.h" |
| 12 | #include "core/core_cpu.h" | ||
| 12 | #include "core/core_timing.h" | 13 | #include "core/core_timing.h" |
| 13 | #include "core/hle/kernel/kernel.h" | 14 | #include "core/hle/kernel/kernel.h" |
| 14 | #include "core/hle/kernel/process.h" | 15 | #include "core/hle/kernel/process.h" |
| @@ -179,4 +180,69 @@ void Scheduler::SetThreadPriority(Thread* thread, u32 priority) { | |||
| 179 | ready_queue.prepare(priority); | 180 | ready_queue.prepare(priority); |
| 180 | } | 181 | } |
| 181 | 182 | ||
| 183 | Thread* Scheduler::GetNextSuggestedThread(u32 core, u32 maximum_priority) const { | ||
| 184 | std::lock_guard<std::mutex> lock(scheduler_mutex); | ||
| 185 | |||
| 186 | const u32 mask = 1U << core; | ||
| 187 | return ready_queue.get_first_filter([mask, maximum_priority](Thread const* thread) { | ||
| 188 | return (thread->GetAffinityMask() & mask) != 0 && thread->GetPriority() < maximum_priority; | ||
| 189 | }); | ||
| 190 | } | ||
| 191 | |||
| 192 | void Scheduler::YieldWithoutLoadBalancing(Thread* thread) { | ||
| 193 | ASSERT(thread != nullptr); | ||
| 194 | // Avoid yielding if the thread isn't even running. | ||
| 195 | ASSERT(thread->GetStatus() == ThreadStatus::Running); | ||
| 196 | |||
| 197 | // Sanity check that the priority is valid | ||
| 198 | ASSERT(thread->GetPriority() < THREADPRIO_COUNT); | ||
| 199 | |||
| 200 | // Yield this thread -- sleep for zero time and force reschedule to different thread | ||
| 201 | WaitCurrentThread_Sleep(); | ||
| 202 | GetCurrentThread()->WakeAfterDelay(0); | ||
| 203 | } | ||
| 204 | |||
| 205 | void Scheduler::YieldWithLoadBalancing(Thread* thread) { | ||
| 206 | ASSERT(thread != nullptr); | ||
| 207 | const auto priority = thread->GetPriority(); | ||
| 208 | const auto core = static_cast<u32>(thread->GetProcessorID()); | ||
| 209 | |||
| 210 | // Avoid yielding if the thread isn't even running. | ||
| 211 | ASSERT(thread->GetStatus() == ThreadStatus::Running); | ||
| 212 | |||
| 213 | // Sanity check that the priority is valid | ||
| 214 | ASSERT(priority < THREADPRIO_COUNT); | ||
| 215 | |||
| 216 | // Sleep for zero time to be able to force reschedule to different thread | ||
| 217 | WaitCurrentThread_Sleep(); | ||
| 218 | GetCurrentThread()->WakeAfterDelay(0); | ||
| 219 | |||
| 220 | Thread* suggested_thread = nullptr; | ||
| 221 | |||
| 222 | // Search through all of the cpu cores (except this one) for a suggested thread. | ||
| 223 | // Take the first non-nullptr one | ||
| 224 | for (unsigned cur_core = 0; cur_core < Core::NUM_CPU_CORES; ++cur_core) { | ||
| 225 | const auto res = | ||
| 226 | Core::System::GetInstance().CpuCore(cur_core).Scheduler().GetNextSuggestedThread( | ||
| 227 | core, priority); | ||
| 228 | |||
| 229 | // If scheduler provides a suggested thread | ||
| 230 | if (res != nullptr) { | ||
| 231 | // And its better than the current suggested thread (or is the first valid one) | ||
| 232 | if (suggested_thread == nullptr || | ||
| 233 | suggested_thread->GetPriority() > res->GetPriority()) { | ||
| 234 | suggested_thread = res; | ||
| 235 | } | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | // If a suggested thread was found, queue that for this core | ||
| 240 | if (suggested_thread != nullptr) | ||
| 241 | suggested_thread->ChangeCore(core, suggested_thread->GetAffinityMask()); | ||
| 242 | } | ||
| 243 | |||
| 244 | void Scheduler::YieldAndWaitForLoadBalancing(Thread* thread) { | ||
| 245 | UNIMPLEMENTED_MSG("Wait for load balancing thread yield type is not implemented!"); | ||
| 246 | } | ||
| 247 | |||
| 182 | } // namespace Kernel | 248 | } // namespace Kernel |