diff options
| author | 2020-11-28 13:34:07 -0800 | |
|---|---|---|
| committer | 2020-12-06 00:03:24 -0800 | |
| commit | 7e5d0f1fe311663329bc15b9e387f3ce2083dcf0 (patch) | |
| tree | 350e07db8895fae85859b61010dd85a09f46039d /src | |
| parent | hle: kernel: svc: Remove reschedule on svcBreak. (diff) | |
| download | yuzu-7e5d0f1fe311663329bc15b9e387f3ce2083dcf0.tar.gz yuzu-7e5d0f1fe311663329bc15b9e387f3ce2083dcf0.tar.xz yuzu-7e5d0f1fe311663329bc15b9e387f3ce2083dcf0.zip | |
hle: kernel: Port KAbstractSchedulerLock from Mesosphere.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_scheduler_lock.h | 76 |
2 files changed, 77 insertions, 0 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 4de159119..2e60a8331 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -154,6 +154,7 @@ add_library(core STATIC | |||
| 154 | hle/kernel/hle_ipc.h | 154 | hle/kernel/hle_ipc.h |
| 155 | hle/kernel/k_affinity_mask.h | 155 | hle/kernel/k_affinity_mask.h |
| 156 | hle/kernel/k_priority_queue.h | 156 | hle/kernel/k_priority_queue.h |
| 157 | hle/kernel/k_scheduler_lock.h | ||
| 157 | hle/kernel/kernel.cpp | 158 | hle/kernel/kernel.cpp |
| 158 | hle/kernel/kernel.h | 159 | hle/kernel/kernel.h |
| 159 | hle/kernel/memory/address_space_info.cpp | 160 | hle/kernel/memory/address_space_info.cpp |
diff --git a/src/core/hle/kernel/k_scheduler_lock.h b/src/core/hle/kernel/k_scheduler_lock.h new file mode 100644 index 000000000..d46f5fc04 --- /dev/null +++ b/src/core/hle/kernel/k_scheduler_lock.h | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | // Copyright 2020 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | // This file references various implementation details from Atmosphere, an open-source firmware for | ||
| 6 | // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. | ||
| 7 | |||
| 8 | #pragma once | ||
| 9 | |||
| 10 | #include "common/assert.h" | ||
| 11 | #include "common/spin_lock.h" | ||
| 12 | #include "core/hardware_properties.h" | ||
| 13 | |||
| 14 | namespace Kernel { | ||
| 15 | |||
| 16 | class KernelCore; | ||
| 17 | |||
| 18 | template <typename SchedulerType> | ||
| 19 | class KAbstractSchedulerLock { | ||
| 20 | private: | ||
| 21 | KernelCore& kernel; | ||
| 22 | Common::SpinLock spin_lock; | ||
| 23 | s32 lock_count; | ||
| 24 | Core::EmuThreadHandle owner_thread; | ||
| 25 | |||
| 26 | public: | ||
| 27 | KAbstractSchedulerLock(KernelCore& kernel) | ||
| 28 | : kernel{kernel}, spin_lock(), lock_count(0), | ||
| 29 | owner_thread(Core::EmuThreadHandle::InvalidHandle()) {} | ||
| 30 | |||
| 31 | bool IsLockedByCurrentThread() const { | ||
| 32 | return this->owner_thread == kernel.GetCurrentEmuThreadID(); | ||
| 33 | } | ||
| 34 | |||
| 35 | void Lock() { | ||
| 36 | if (this->IsLockedByCurrentThread()) { | ||
| 37 | /* If we already own the lock, we can just increment the count. */ | ||
| 38 | ASSERT(this->lock_count > 0); | ||
| 39 | this->lock_count++; | ||
| 40 | } else { | ||
| 41 | /* Otherwise, we want to disable scheduling and acquire the spinlock. */ | ||
| 42 | SchedulerType::DisableScheduling(kernel); | ||
| 43 | this->spin_lock.lock(); | ||
| 44 | |||
| 45 | /* For debug, ensure that our state is valid. */ | ||
| 46 | ASSERT(this->lock_count == 0); | ||
| 47 | ASSERT(this->owner_thread == Core::EmuThreadHandle::InvalidHandle()); | ||
| 48 | |||
| 49 | /* Increment count, take ownership. */ | ||
| 50 | this->lock_count = 1; | ||
| 51 | this->owner_thread = kernel.GetCurrentEmuThreadID(); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | void Unlock() { | ||
| 56 | ASSERT(this->IsLockedByCurrentThread()); | ||
| 57 | ASSERT(this->lock_count > 0); | ||
| 58 | |||
| 59 | /* Release an instance of the lock. */ | ||
| 60 | if ((--this->lock_count) == 0) { | ||
| 61 | /* We're no longer going to hold the lock. Take note of what cores need scheduling. */ | ||
| 62 | const u64 cores_needing_scheduling = | ||
| 63 | SchedulerType::UpdateHighestPriorityThreads(kernel); | ||
| 64 | Core::EmuThreadHandle leaving_thread = owner_thread; | ||
| 65 | |||
| 66 | /* Note that we no longer hold the lock, and unlock the spinlock. */ | ||
| 67 | this->owner_thread = Core::EmuThreadHandle::InvalidHandle(); | ||
| 68 | this->spin_lock.unlock(); | ||
| 69 | |||
| 70 | /* Enable scheduling, and perform a rescheduling operation. */ | ||
| 71 | SchedulerType::EnableScheduling(kernel, cores_needing_scheduling, leaving_thread); | ||
| 72 | } | ||
| 73 | } | ||
| 74 | }; | ||
| 75 | |||
| 76 | } // namespace Kernel | ||