summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2020-11-28 13:34:07 -0800
committerGravatar bunnei2020-12-06 00:03:24 -0800
commit7e5d0f1fe311663329bc15b9e387f3ce2083dcf0 (patch)
tree350e07db8895fae85859b61010dd85a09f46039d /src
parenthle: kernel: svc: Remove reschedule on svcBreak. (diff)
downloadyuzu-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.txt1
-rw-r--r--src/core/hle/kernel/k_scheduler_lock.h76
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
14namespace Kernel {
15
16class KernelCore;
17
18template <typename SchedulerType>
19class KAbstractSchedulerLock {
20private:
21 KernelCore& kernel;
22 Common::SpinLock spin_lock;
23 s32 lock_count;
24 Core::EmuThreadHandle owner_thread;
25
26public:
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