summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/core.cpp5
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp147
-rw-r--r--src/core/hle/kernel/address_arbiter.h74
-rw-r--r--src/core/hle/kernel/kernel.cpp30
-rw-r--r--src/core/hle/kernel/kernel.h26
-rw-r--r--src/core/hle/kernel/svc.cpp14
-rw-r--r--src/tests/core/arm/arm_test_common.cpp6
7 files changed, 187 insertions, 115 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index ab7181a05..6dda20faa 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -78,6 +78,7 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
78 return vfs->OpenFile(path, FileSys::Mode::Read); 78 return vfs->OpenFile(path, FileSys::Mode::Read);
79} 79}
80struct System::Impl { 80struct System::Impl {
81 explicit Impl(System& system) : kernel{system} {}
81 82
82 Cpu& CurrentCpuCore() { 83 Cpu& CurrentCpuCore() {
83 return cpu_core_manager.GetCurrentCore(); 84 return cpu_core_manager.GetCurrentCore();
@@ -95,7 +96,7 @@ struct System::Impl {
95 LOG_DEBUG(HW_Memory, "initialized OK"); 96 LOG_DEBUG(HW_Memory, "initialized OK");
96 97
97 core_timing.Initialize(); 98 core_timing.Initialize();
98 kernel.Initialize(core_timing); 99 kernel.Initialize();
99 100
100 const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( 101 const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
101 std::chrono::system_clock::now().time_since_epoch()); 102 std::chrono::system_clock::now().time_since_epoch());
@@ -265,7 +266,7 @@ struct System::Impl {
265 Core::FrameLimiter frame_limiter; 266 Core::FrameLimiter frame_limiter;
266}; 267};
267 268
268System::System() : impl{std::make_unique<Impl>()} {} 269System::System() : impl{std::make_unique<Impl>(*this)} {}
269System::~System() = default; 270System::~System() = default;
270 271
271Cpu& System::CurrentCpuCore() { 272Cpu& System::CurrentCpuCore() {
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index a250d088d..9780a7849 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -9,6 +9,7 @@
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/core_cpu.h" 11#include "core/core_cpu.h"
12#include "core/hle/kernel/address_arbiter.h"
12#include "core/hle/kernel/errors.h" 13#include "core/hle/kernel/errors.h"
13#include "core/hle/kernel/object.h" 14#include "core/hle/kernel/object.h"
14#include "core/hle/kernel/process.h" 15#include "core/hle/kernel/process.h"
@@ -17,58 +18,16 @@
17#include "core/hle/result.h" 18#include "core/hle/result.h"
18#include "core/memory.h" 19#include "core/memory.h"
19 20
20namespace Kernel::AddressArbiter { 21namespace Kernel {
21 22namespace {
22// Performs actual address waiting logic.
23static ResultCode WaitForAddress(VAddr address, s64 timeout) {
24 SharedPtr<Thread> current_thread = GetCurrentThread();
25 current_thread->SetArbiterWaitAddress(address);
26 current_thread->SetStatus(ThreadStatus::WaitArb);
27 current_thread->InvalidateWakeupCallback();
28
29 current_thread->WakeAfterDelay(timeout);
30
31 Core::System::GetInstance().CpuCore(current_thread->GetProcessorID()).PrepareReschedule();
32 return RESULT_TIMEOUT;
33}
34
35// Gets the threads waiting on an address.
36static std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) {
37 const auto RetrieveWaitingThreads = [](std::size_t core_index,
38 std::vector<SharedPtr<Thread>>& waiting_threads,
39 VAddr arb_addr) {
40 const auto& scheduler = Core::System::GetInstance().Scheduler(core_index);
41 const auto& thread_list = scheduler.GetThreadList();
42
43 for (const auto& thread : thread_list) {
44 if (thread->GetArbiterWaitAddress() == arb_addr)
45 waiting_threads.push_back(thread);
46 }
47 };
48
49 // Retrieve all threads that are waiting for this address.
50 std::vector<SharedPtr<Thread>> threads;
51 RetrieveWaitingThreads(0, threads, address);
52 RetrieveWaitingThreads(1, threads, address);
53 RetrieveWaitingThreads(2, threads, address);
54 RetrieveWaitingThreads(3, threads, address);
55
56 // Sort them by priority, such that the highest priority ones come first.
57 std::sort(threads.begin(), threads.end(),
58 [](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
59 return lhs->GetPriority() < rhs->GetPriority();
60 });
61
62 return threads;
63}
64
65// Wake up num_to_wake (or all) threads in a vector. 23// Wake up num_to_wake (or all) threads in a vector.
66static void WakeThreads(std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_to_wake) { 24void WakeThreads(const std::vector<SharedPtr<Thread>>& waiting_threads, s32 num_to_wake) {
67 // Only process up to 'target' threads, unless 'target' is <= 0, in which case process 25 // Only process up to 'target' threads, unless 'target' is <= 0, in which case process
68 // them all. 26 // them all.
69 std::size_t last = waiting_threads.size(); 27 std::size_t last = waiting_threads.size();
70 if (num_to_wake > 0) 28 if (num_to_wake > 0) {
71 last = num_to_wake; 29 last = num_to_wake;
30 }
72 31
73 // Signal the waiting threads. 32 // Signal the waiting threads.
74 for (std::size_t i = 0; i < last; i++) { 33 for (std::size_t i = 0; i < last; i++) {
@@ -78,42 +37,41 @@ static void WakeThreads(std::vector<SharedPtr<Thread>>& waiting_threads, s32 num
78 waiting_threads[i]->ResumeFromWait(); 37 waiting_threads[i]->ResumeFromWait();
79 } 38 }
80} 39}
40} // Anonymous namespace
81 41
82// Signals an address being waited on. 42AddressArbiter::AddressArbiter(Core::System& system) : system{system} {}
83ResultCode SignalToAddress(VAddr address, s32 num_to_wake) { 43AddressArbiter::~AddressArbiter() = default;
84 std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
85 44
45ResultCode AddressArbiter::SignalToAddress(VAddr address, s32 num_to_wake) {
46 const std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
86 WakeThreads(waiting_threads, num_to_wake); 47 WakeThreads(waiting_threads, num_to_wake);
87 return RESULT_SUCCESS; 48 return RESULT_SUCCESS;
88} 49}
89 50
90// Signals an address being waited on and increments its value if equal to the value argument. 51ResultCode AddressArbiter::IncrementAndSignalToAddressIfEqual(VAddr address, s32 value,
91ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake) { 52 s32 num_to_wake) {
92 // Ensure that we can write to the address. 53 // Ensure that we can write to the address.
93 if (!Memory::IsValidVirtualAddress(address)) { 54 if (!Memory::IsValidVirtualAddress(address)) {
94 return ERR_INVALID_ADDRESS_STATE; 55 return ERR_INVALID_ADDRESS_STATE;
95 } 56 }
96 57
97 if (static_cast<s32>(Memory::Read32(address)) == value) { 58 if (static_cast<s32>(Memory::Read32(address)) != value) {
98 Memory::Write32(address, static_cast<u32>(value + 1));
99 } else {
100 return ERR_INVALID_STATE; 59 return ERR_INVALID_STATE;
101 } 60 }
102 61
62 Memory::Write32(address, static_cast<u32>(value + 1));
103 return SignalToAddress(address, num_to_wake); 63 return SignalToAddress(address, num_to_wake);
104} 64}
105 65
106// Signals an address being waited on and modifies its value based on waiting thread count if equal 66ResultCode AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value,
107// to the value argument. 67 s32 num_to_wake) {
108ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value,
109 s32 num_to_wake) {
110 // Ensure that we can write to the address. 68 // Ensure that we can write to the address.
111 if (!Memory::IsValidVirtualAddress(address)) { 69 if (!Memory::IsValidVirtualAddress(address)) {
112 return ERR_INVALID_ADDRESS_STATE; 70 return ERR_INVALID_ADDRESS_STATE;
113 } 71 }
114 72
115 // Get threads waiting on the address. 73 // Get threads waiting on the address.
116 std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address); 74 const std::vector<SharedPtr<Thread>> waiting_threads = GetThreadsWaitingOnAddress(address);
117 75
118 // Determine the modified value depending on the waiting count. 76 // Determine the modified value depending on the waiting count.
119 s32 updated_value; 77 s32 updated_value;
@@ -125,31 +83,31 @@ ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 valu
125 updated_value = value; 83 updated_value = value;
126 } 84 }
127 85
128 if (static_cast<s32>(Memory::Read32(address)) == value) { 86 if (static_cast<s32>(Memory::Read32(address)) != value) {
129 Memory::Write32(address, static_cast<u32>(updated_value));
130 } else {
131 return ERR_INVALID_STATE; 87 return ERR_INVALID_STATE;
132 } 88 }
133 89
90 Memory::Write32(address, static_cast<u32>(updated_value));
134 WakeThreads(waiting_threads, num_to_wake); 91 WakeThreads(waiting_threads, num_to_wake);
135 return RESULT_SUCCESS; 92 return RESULT_SUCCESS;
136} 93}
137 94
138// Waits on an address if the value passed is less than the argument value, optionally decrementing. 95ResultCode AddressArbiter::WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout,
139ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement) { 96 bool should_decrement) {
140 // Ensure that we can read the address. 97 // Ensure that we can read the address.
141 if (!Memory::IsValidVirtualAddress(address)) { 98 if (!Memory::IsValidVirtualAddress(address)) {
142 return ERR_INVALID_ADDRESS_STATE; 99 return ERR_INVALID_ADDRESS_STATE;
143 } 100 }
144 101
145 s32 cur_value = static_cast<s32>(Memory::Read32(address)); 102 const s32 cur_value = static_cast<s32>(Memory::Read32(address));
146 if (cur_value < value) { 103 if (cur_value >= value) {
147 if (should_decrement) {
148 Memory::Write32(address, static_cast<u32>(cur_value - 1));
149 }
150 } else {
151 return ERR_INVALID_STATE; 104 return ERR_INVALID_STATE;
152 } 105 }
106
107 if (should_decrement) {
108 Memory::Write32(address, static_cast<u32>(cur_value - 1));
109 }
110
153 // Short-circuit without rescheduling, if timeout is zero. 111 // Short-circuit without rescheduling, if timeout is zero.
154 if (timeout == 0) { 112 if (timeout == 0) {
155 return RESULT_TIMEOUT; 113 return RESULT_TIMEOUT;
@@ -158,8 +116,7 @@ ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool
158 return WaitForAddress(address, timeout); 116 return WaitForAddress(address, timeout);
159} 117}
160 118
161// Waits on an address if the value passed is equal to the argument value. 119ResultCode AddressArbiter::WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) {
162ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) {
163 // Ensure that we can read the address. 120 // Ensure that we can read the address.
164 if (!Memory::IsValidVirtualAddress(address)) { 121 if (!Memory::IsValidVirtualAddress(address)) {
165 return ERR_INVALID_ADDRESS_STATE; 122 return ERR_INVALID_ADDRESS_STATE;
@@ -175,4 +132,46 @@ ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout) {
175 132
176 return WaitForAddress(address, timeout); 133 return WaitForAddress(address, timeout);
177} 134}
178} // namespace Kernel::AddressArbiter 135
136ResultCode AddressArbiter::WaitForAddress(VAddr address, s64 timeout) {
137 SharedPtr<Thread> current_thread = system.CurrentScheduler().GetCurrentThread();
138 current_thread->SetArbiterWaitAddress(address);
139 current_thread->SetStatus(ThreadStatus::WaitArb);
140 current_thread->InvalidateWakeupCallback();
141
142 current_thread->WakeAfterDelay(timeout);
143
144 system.CpuCore(current_thread->GetProcessorID()).PrepareReschedule();
145 return RESULT_TIMEOUT;
146}
147
148std::vector<SharedPtr<Thread>> AddressArbiter::GetThreadsWaitingOnAddress(VAddr address) const {
149 const auto RetrieveWaitingThreads = [this](std::size_t core_index,
150 std::vector<SharedPtr<Thread>>& waiting_threads,
151 VAddr arb_addr) {
152 const auto& scheduler = system.Scheduler(core_index);
153 const auto& thread_list = scheduler.GetThreadList();
154
155 for (const auto& thread : thread_list) {
156 if (thread->GetArbiterWaitAddress() == arb_addr) {
157 waiting_threads.push_back(thread);
158 }
159 }
160 };
161
162 // Retrieve all threads that are waiting for this address.
163 std::vector<SharedPtr<Thread>> threads;
164 RetrieveWaitingThreads(0, threads, address);
165 RetrieveWaitingThreads(1, threads, address);
166 RetrieveWaitingThreads(2, threads, address);
167 RetrieveWaitingThreads(3, threads, address);
168
169 // Sort them by priority, such that the highest priority ones come first.
170 std::sort(threads.begin(), threads.end(),
171 [](const SharedPtr<Thread>& lhs, const SharedPtr<Thread>& rhs) {
172 return lhs->GetPriority() < rhs->GetPriority();
173 });
174
175 return threads;
176}
177} // namespace Kernel
diff --git a/src/core/hle/kernel/address_arbiter.h b/src/core/hle/kernel/address_arbiter.h
index b58f21bec..e0c36f2e3 100644
--- a/src/core/hle/kernel/address_arbiter.h
+++ b/src/core/hle/kernel/address_arbiter.h
@@ -5,28 +5,68 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "core/hle/kernel/address_arbiter.h"
8 9
9union ResultCode; 10union ResultCode;
10 11
11namespace Kernel::AddressArbiter { 12namespace Core {
13class System;
14}
12 15
13enum class ArbitrationType { 16namespace Kernel {
14 WaitIfLessThan = 0,
15 DecrementAndWaitIfLessThan = 1,
16 WaitIfEqual = 2,
17};
18 17
19enum class SignalType { 18class Thread;
20 Signal = 0, 19
21 IncrementAndSignalIfEqual = 1, 20class AddressArbiter {
22 ModifyByWaitingCountAndSignalIfEqual = 2, 21public:
23}; 22 enum class ArbitrationType {
23 WaitIfLessThan = 0,
24 DecrementAndWaitIfLessThan = 1,
25 WaitIfEqual = 2,
26 };
27
28 enum class SignalType {
29 Signal = 0,
30 IncrementAndSignalIfEqual = 1,
31 ModifyByWaitingCountAndSignalIfEqual = 2,
32 };
33
34 explicit AddressArbiter(Core::System& system);
35 ~AddressArbiter();
36
37 AddressArbiter(const AddressArbiter&) = delete;
38 AddressArbiter& operator=(const AddressArbiter&) = delete;
39
40 AddressArbiter(AddressArbiter&&) = default;
41 AddressArbiter& operator=(AddressArbiter&&) = delete;
24 42
25ResultCode SignalToAddress(VAddr address, s32 num_to_wake); 43 /// Signals an address being waited on.
26ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake); 44 ResultCode SignalToAddress(VAddr address, s32 num_to_wake);
27ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake);
28 45
29ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout, bool should_decrement); 46 /// Signals an address being waited on and increments its value if equal to the value argument.
30ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout); 47 ResultCode IncrementAndSignalToAddressIfEqual(VAddr address, s32 value, s32 num_to_wake);
48
49 /// Signals an address being waited on and modifies its value based on waiting thread count if
50 /// equal to the value argument.
51 ResultCode ModifyByWaitingCountAndSignalToAddressIfEqual(VAddr address, s32 value,
52 s32 num_to_wake);
53
54 /// Waits on an address if the value passed is less than the argument value,
55 /// optionally decrementing.
56 ResultCode WaitForAddressIfLessThan(VAddr address, s32 value, s64 timeout,
57 bool should_decrement);
58
59 /// Waits on an address if the value passed is equal to the argument value.
60 ResultCode WaitForAddressIfEqual(VAddr address, s32 value, s64 timeout);
61
62private:
63 // Waits on the given address with a timeout in nanoseconds
64 ResultCode WaitForAddress(VAddr address, s64 timeout);
65
66 // Gets the threads waiting on an address.
67 std::vector<SharedPtr<Thread>> GetThreadsWaitingOnAddress(VAddr address) const;
68
69 Core::System& system;
70};
31 71
32} // namespace Kernel::AddressArbiter 72} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index dd749eed4..04ea9349e 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -12,6 +12,7 @@
12 12
13#include "core/core.h" 13#include "core/core.h"
14#include "core/core_timing.h" 14#include "core/core_timing.h"
15#include "core/hle/kernel/address_arbiter.h"
15#include "core/hle/kernel/client_port.h" 16#include "core/hle/kernel/client_port.h"
16#include "core/hle/kernel/handle_table.h" 17#include "core/hle/kernel/handle_table.h"
17#include "core/hle/kernel/kernel.h" 18#include "core/hle/kernel/kernel.h"
@@ -86,11 +87,13 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] int cycles_
86} 87}
87 88
88struct KernelCore::Impl { 89struct KernelCore::Impl {
89 void Initialize(KernelCore& kernel, Core::Timing::CoreTiming& core_timing) { 90 explicit Impl(Core::System& system) : address_arbiter{system}, system{system} {}
91
92 void Initialize(KernelCore& kernel) {
90 Shutdown(); 93 Shutdown();
91 94
92 InitializeSystemResourceLimit(kernel); 95 InitializeSystemResourceLimit(kernel);
93 InitializeThreads(core_timing); 96 InitializeThreads();
94 } 97 }
95 98
96 void Shutdown() { 99 void Shutdown() {
@@ -122,9 +125,9 @@ struct KernelCore::Impl {
122 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess()); 125 ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
123 } 126 }
124 127
125 void InitializeThreads(Core::Timing::CoreTiming& core_timing) { 128 void InitializeThreads() {
126 thread_wakeup_event_type = 129 thread_wakeup_event_type =
127 core_timing.RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); 130 system.CoreTiming().RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
128 } 131 }
129 132
130 std::atomic<u32> next_object_id{0}; 133 std::atomic<u32> next_object_id{0};
@@ -135,6 +138,8 @@ struct KernelCore::Impl {
135 std::vector<SharedPtr<Process>> process_list; 138 std::vector<SharedPtr<Process>> process_list;
136 Process* current_process = nullptr; 139 Process* current_process = nullptr;
137 140
141 Kernel::AddressArbiter address_arbiter;
142
138 SharedPtr<ResourceLimit> system_resource_limit; 143 SharedPtr<ResourceLimit> system_resource_limit;
139 144
140 Core::Timing::EventType* thread_wakeup_event_type = nullptr; 145 Core::Timing::EventType* thread_wakeup_event_type = nullptr;
@@ -145,15 +150,18 @@ struct KernelCore::Impl {
145 /// Map of named ports managed by the kernel, which can be retrieved using 150 /// Map of named ports managed by the kernel, which can be retrieved using
146 /// the ConnectToPort SVC. 151 /// the ConnectToPort SVC.
147 NamedPortTable named_ports; 152 NamedPortTable named_ports;
153
154 // System context
155 Core::System& system;
148}; 156};
149 157
150KernelCore::KernelCore() : impl{std::make_unique<Impl>()} {} 158KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system)} {}
151KernelCore::~KernelCore() { 159KernelCore::~KernelCore() {
152 Shutdown(); 160 Shutdown();
153} 161}
154 162
155void KernelCore::Initialize(Core::Timing::CoreTiming& core_timing) { 163void KernelCore::Initialize() {
156 impl->Initialize(*this, core_timing); 164 impl->Initialize(*this);
157} 165}
158 166
159void KernelCore::Shutdown() { 167void KernelCore::Shutdown() {
@@ -184,6 +192,14 @@ const Process* KernelCore::CurrentProcess() const {
184 return impl->current_process; 192 return impl->current_process;
185} 193}
186 194
195AddressArbiter& KernelCore::AddressArbiter() {
196 return impl->address_arbiter;
197}
198
199const AddressArbiter& KernelCore::AddressArbiter() const {
200 return impl->address_arbiter;
201}
202
187void KernelCore::AddNamedPort(std::string name, SharedPtr<ClientPort> port) { 203void KernelCore::AddNamedPort(std::string name, SharedPtr<ClientPort> port) {
188 impl->named_ports.emplace(std::move(name), std::move(port)); 204 impl->named_ports.emplace(std::move(name), std::move(port));
189} 205}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 154bced42..4d292aca9 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -11,6 +11,10 @@
11template <typename T> 11template <typename T>
12class ResultVal; 12class ResultVal;
13 13
14namespace Core {
15class System;
16}
17
14namespace Core::Timing { 18namespace Core::Timing {
15class CoreTiming; 19class CoreTiming;
16struct EventType; 20struct EventType;
@@ -18,6 +22,7 @@ struct EventType;
18 22
19namespace Kernel { 23namespace Kernel {
20 24
25class AddressArbiter;
21class ClientPort; 26class ClientPort;
22class HandleTable; 27class HandleTable;
23class Process; 28class Process;
@@ -30,7 +35,14 @@ private:
30 using NamedPortTable = std::unordered_map<std::string, SharedPtr<ClientPort>>; 35 using NamedPortTable = std::unordered_map<std::string, SharedPtr<ClientPort>>;
31 36
32public: 37public:
33 KernelCore(); 38 /// Constructs an instance of the kernel using the given System
39 /// instance as a context for any necessary system-related state,
40 /// such as threads, CPU core state, etc.
41 ///
42 /// @post After execution of the constructor, the provided System
43 /// object *must* outlive the kernel instance itself.
44 ///
45 explicit KernelCore(Core::System& system);
34 ~KernelCore(); 46 ~KernelCore();
35 47
36 KernelCore(const KernelCore&) = delete; 48 KernelCore(const KernelCore&) = delete;
@@ -40,11 +52,7 @@ public:
40 KernelCore& operator=(KernelCore&&) = delete; 52 KernelCore& operator=(KernelCore&&) = delete;
41 53
42 /// Resets the kernel to a clean slate for use. 54 /// Resets the kernel to a clean slate for use.
43 /// 55 void Initialize();
44 /// @param core_timing CoreTiming instance used to create any necessary
45 /// kernel-specific callback events.
46 ///
47 void Initialize(Core::Timing::CoreTiming& core_timing);
48 56
49 /// Clears all resources in use by the kernel instance. 57 /// Clears all resources in use by the kernel instance.
50 void Shutdown(); 58 void Shutdown();
@@ -67,6 +75,12 @@ public:
67 /// Retrieves a const pointer to the current process. 75 /// Retrieves a const pointer to the current process.
68 const Process* CurrentProcess() const; 76 const Process* CurrentProcess() const;
69 77
78 /// Provides a reference to the kernel's address arbiter.
79 Kernel::AddressArbiter& AddressArbiter();
80
81 /// Provides a const reference to the kernel's address arbiter.
82 const Kernel::AddressArbiter& AddressArbiter() const;
83
70 /// Adds a port to the named port table 84 /// Adds a port to the named port table
71 void AddNamedPort(std::string name, SharedPtr<ClientPort> port); 85 void AddNamedPort(std::string name, SharedPtr<ClientPort> port);
72 86
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 223d717e2..75b88a333 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1478,13 +1478,14 @@ static ResultCode WaitForAddress(VAddr address, u32 type, s32 value, s64 timeout
1478 return ERR_INVALID_ADDRESS; 1478 return ERR_INVALID_ADDRESS;
1479 } 1479 }
1480 1480
1481 auto& address_arbiter = Core::System::GetInstance().Kernel().AddressArbiter();
1481 switch (static_cast<AddressArbiter::ArbitrationType>(type)) { 1482 switch (static_cast<AddressArbiter::ArbitrationType>(type)) {
1482 case AddressArbiter::ArbitrationType::WaitIfLessThan: 1483 case AddressArbiter::ArbitrationType::WaitIfLessThan:
1483 return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, false); 1484 return address_arbiter.WaitForAddressIfLessThan(address, value, timeout, false);
1484 case AddressArbiter::ArbitrationType::DecrementAndWaitIfLessThan: 1485 case AddressArbiter::ArbitrationType::DecrementAndWaitIfLessThan:
1485 return AddressArbiter::WaitForAddressIfLessThan(address, value, timeout, true); 1486 return address_arbiter.WaitForAddressIfLessThan(address, value, timeout, true);
1486 case AddressArbiter::ArbitrationType::WaitIfEqual: 1487 case AddressArbiter::ArbitrationType::WaitIfEqual:
1487 return AddressArbiter::WaitForAddressIfEqual(address, value, timeout); 1488 return address_arbiter.WaitForAddressIfEqual(address, value, timeout);
1488 default: 1489 default:
1489 LOG_ERROR(Kernel_SVC, 1490 LOG_ERROR(Kernel_SVC,
1490 "Invalid arbitration type, expected WaitIfLessThan, DecrementAndWaitIfLessThan " 1491 "Invalid arbitration type, expected WaitIfLessThan, DecrementAndWaitIfLessThan "
@@ -1509,13 +1510,14 @@ static ResultCode SignalToAddress(VAddr address, u32 type, s32 value, s32 num_to
1509 return ERR_INVALID_ADDRESS; 1510 return ERR_INVALID_ADDRESS;
1510 } 1511 }
1511 1512
1513 auto& address_arbiter = Core::System::GetInstance().Kernel().AddressArbiter();
1512 switch (static_cast<AddressArbiter::SignalType>(type)) { 1514 switch (static_cast<AddressArbiter::SignalType>(type)) {
1513 case AddressArbiter::SignalType::Signal: 1515 case AddressArbiter::SignalType::Signal:
1514 return AddressArbiter::SignalToAddress(address, num_to_wake); 1516 return address_arbiter.SignalToAddress(address, num_to_wake);
1515 case AddressArbiter::SignalType::IncrementAndSignalIfEqual: 1517 case AddressArbiter::SignalType::IncrementAndSignalIfEqual:
1516 return AddressArbiter::IncrementAndSignalToAddressIfEqual(address, value, num_to_wake); 1518 return address_arbiter.IncrementAndSignalToAddressIfEqual(address, value, num_to_wake);
1517 case AddressArbiter::SignalType::ModifyByWaitingCountAndSignalIfEqual: 1519 case AddressArbiter::SignalType::ModifyByWaitingCountAndSignalIfEqual:
1518 return AddressArbiter::ModifyByWaitingCountAndSignalToAddressIfEqual(address, value, 1520 return address_arbiter.ModifyByWaitingCountAndSignalToAddressIfEqual(address, value,
1519 num_to_wake); 1521 num_to_wake);
1520 default: 1522 default:
1521 LOG_ERROR(Kernel_SVC, 1523 LOG_ERROR(Kernel_SVC,
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp
index 9b8a44fa1..ea27ef90d 100644
--- a/src/tests/core/arm/arm_test_common.cpp
+++ b/src/tests/core/arm/arm_test_common.cpp
@@ -13,11 +13,11 @@
13namespace ArmTests { 13namespace ArmTests {
14 14
15TestEnvironment::TestEnvironment(bool mutable_memory_) 15TestEnvironment::TestEnvironment(bool mutable_memory_)
16 : mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) { 16 : mutable_memory(mutable_memory_),
17 17 test_memory(std::make_shared<TestMemory>(this)), kernel{Core::System::GetInstance()} {
18 auto process = Kernel::Process::Create(kernel, ""); 18 auto process = Kernel::Process::Create(kernel, "");
19 kernel.MakeCurrentProcess(process.get()); 19 kernel.MakeCurrentProcess(process.get());
20 page_table = &Core::CurrentProcess()->VMManager().page_table; 20 page_table = &process->VMManager().page_table;
21 21
22 std::fill(page_table->pointers.begin(), page_table->pointers.end(), nullptr); 22 std::fill(page_table->pointers.begin(), page_table->pointers.end(), nullptr);
23 page_table->special_regions.clear(); 23 page_table->special_regions.clear();