summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp121
1 files changed, 104 insertions, 17 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 4eb1d8703..9232f4d7e 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -3,9 +3,12 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <atomic> 5#include <atomic>
6#include <bitset>
6#include <functional> 7#include <functional>
7#include <memory> 8#include <memory>
8#include <mutex> 9#include <mutex>
10#include <thread>
11#include <unordered_map>
9#include <utility> 12#include <utility>
10 13
11#include "common/assert.h" 14#include "common/assert.h"
@@ -15,6 +18,7 @@
15#include "core/core.h" 18#include "core/core.h"
16#include "core/core_timing.h" 19#include "core/core_timing.h"
17#include "core/core_timing_util.h" 20#include "core/core_timing_util.h"
21#include "core/hardware_properties.h"
18#include "core/hle/kernel/client_port.h" 22#include "core/hle/kernel/client_port.h"
19#include "core/hle/kernel/errors.h" 23#include "core/hle/kernel/errors.h"
20#include "core/hle/kernel/handle_table.h" 24#include "core/hle/kernel/handle_table.h"
@@ -25,6 +29,7 @@
25#include "core/hle/kernel/scheduler.h" 29#include "core/hle/kernel/scheduler.h"
26#include "core/hle/kernel/synchronization.h" 30#include "core/hle/kernel/synchronization.h"
27#include "core/hle/kernel/thread.h" 31#include "core/hle/kernel/thread.h"
32#include "core/hle/kernel/time_manager.h"
28#include "core/hle/lock.h" 33#include "core/hle/lock.h"
29#include "core/hle/result.h" 34#include "core/hle/result.h"
30#include "core/memory.h" 35#include "core/memory.h"
@@ -44,7 +49,7 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
44 std::lock_guard lock{HLE::g_hle_lock}; 49 std::lock_guard lock{HLE::g_hle_lock};
45 50
46 std::shared_ptr<Thread> thread = 51 std::shared_ptr<Thread> thread =
47 system.Kernel().RetrieveThreadFromWakeupCallbackHandleTable(proper_handle); 52 system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
48 if (thread == nullptr) { 53 if (thread == nullptr) {
49 LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); 54 LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
50 return; 55 return;
@@ -97,8 +102,8 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_
97} 102}
98 103
99struct KernelCore::Impl { 104struct KernelCore::Impl {
100 explicit Impl(Core::System& system) 105 explicit Impl(Core::System& system, KernelCore& kernel)
101 : system{system}, global_scheduler{system}, synchronization{system} {} 106 : system{system}, global_scheduler{kernel}, synchronization{system}, time_manager{system} {}
102 107
103 void Initialize(KernelCore& kernel) { 108 void Initialize(KernelCore& kernel) {
104 Shutdown(); 109 Shutdown();
@@ -120,7 +125,7 @@ struct KernelCore::Impl {
120 125
121 system_resource_limit = nullptr; 126 system_resource_limit = nullptr;
122 127
123 thread_wakeup_callback_handle_table.Clear(); 128 global_handle_table.Clear();
124 thread_wakeup_event_type = nullptr; 129 thread_wakeup_event_type = nullptr;
125 preemption_event = nullptr; 130 preemption_event = nullptr;
126 131
@@ -138,8 +143,8 @@ struct KernelCore::Impl {
138 143
139 void InitializePhysicalCores() { 144 void InitializePhysicalCores() {
140 exclusive_monitor = 145 exclusive_monitor =
141 Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount()); 146 Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES);
142 for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) { 147 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
143 cores.emplace_back(system, i, *exclusive_monitor); 148 cores.emplace_back(system, i, *exclusive_monitor);
144 } 149 }
145 } 150 }
@@ -184,6 +189,50 @@ struct KernelCore::Impl {
184 system.Memory().SetCurrentPageTable(*process); 189 system.Memory().SetCurrentPageTable(*process);
185 } 190 }
186 191
192 void RegisterCoreThread(std::size_t core_id) {
193 std::unique_lock lock{register_thread_mutex};
194 const std::thread::id this_id = std::this_thread::get_id();
195 const auto it = host_thread_ids.find(this_id);
196 ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
197 ASSERT(it == host_thread_ids.end());
198 ASSERT(!registered_core_threads[core_id]);
199 host_thread_ids[this_id] = static_cast<u32>(core_id);
200 registered_core_threads.set(core_id);
201 }
202
203 void RegisterHostThread() {
204 std::unique_lock lock{register_thread_mutex};
205 const std::thread::id this_id = std::this_thread::get_id();
206 const auto it = host_thread_ids.find(this_id);
207 ASSERT(it == host_thread_ids.end());
208 host_thread_ids[this_id] = registered_thread_ids++;
209 }
210
211 u32 GetCurrentHostThreadID() const {
212 const std::thread::id this_id = std::this_thread::get_id();
213 const auto it = host_thread_ids.find(this_id);
214 if (it == host_thread_ids.end()) {
215 return Core::INVALID_HOST_THREAD_ID;
216 }
217 return it->second;
218 }
219
220 Core::EmuThreadHandle GetCurrentEmuThreadID() const {
221 Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
222 result.host_handle = GetCurrentHostThreadID();
223 if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) {
224 return result;
225 }
226 const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler();
227 const Kernel::Thread* current = sched.GetCurrentThread();
228 if (current != nullptr) {
229 result.guest_handle = current->GetGlobalHandle();
230 } else {
231 result.guest_handle = InvalidHandle;
232 }
233 return result;
234 }
235
187 std::atomic<u32> next_object_id{0}; 236 std::atomic<u32> next_object_id{0};
188 std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin}; 237 std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin};
189 std::atomic<u64> next_user_process_id{Process::ProcessIDMin}; 238 std::atomic<u64> next_user_process_id{Process::ProcessIDMin};
@@ -194,15 +243,16 @@ struct KernelCore::Impl {
194 Process* current_process = nullptr; 243 Process* current_process = nullptr;
195 Kernel::GlobalScheduler global_scheduler; 244 Kernel::GlobalScheduler global_scheduler;
196 Kernel::Synchronization synchronization; 245 Kernel::Synchronization synchronization;
246 Kernel::TimeManager time_manager;
197 247
198 std::shared_ptr<ResourceLimit> system_resource_limit; 248 std::shared_ptr<ResourceLimit> system_resource_limit;
199 249
200 std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type; 250 std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type;
201 std::shared_ptr<Core::Timing::EventType> preemption_event; 251 std::shared_ptr<Core::Timing::EventType> preemption_event;
202 252
203 // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, 253 // This is the kernel's handle table or supervisor handle table which
204 // allowing us to simply use a pool index or similar. 254 // stores all the objects in place.
205 Kernel::HandleTable thread_wakeup_callback_handle_table; 255 Kernel::HandleTable global_handle_table;
206 256
207 /// Map of named ports managed by the kernel, which can be retrieved using 257 /// Map of named ports managed by the kernel, which can be retrieved using
208 /// the ConnectToPort SVC. 258 /// the ConnectToPort SVC.
@@ -211,11 +261,17 @@ struct KernelCore::Impl {
211 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; 261 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
212 std::vector<Kernel::PhysicalCore> cores; 262 std::vector<Kernel::PhysicalCore> cores;
213 263
264 // 0-3 IDs represent core threads, >3 represent others
265 std::unordered_map<std::thread::id, u32> host_thread_ids;
266 u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES};
267 std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads;
268 std::mutex register_thread_mutex;
269
214 // System context 270 // System context
215 Core::System& system; 271 Core::System& system;
216}; 272};
217 273
218KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system)} {} 274KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system, *this)} {}
219KernelCore::~KernelCore() { 275KernelCore::~KernelCore() {
220 Shutdown(); 276 Shutdown();
221} 277}
@@ -232,9 +288,8 @@ std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const {
232 return impl->system_resource_limit; 288 return impl->system_resource_limit;
233} 289}
234 290
235std::shared_ptr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable( 291std::shared_ptr<Thread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const {
236 Handle handle) const { 292 return impl->global_handle_table.Get<Thread>(handle);
237 return impl->thread_wakeup_callback_handle_table.Get<Thread>(handle);
238} 293}
239 294
240void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) { 295void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) {
@@ -265,6 +320,14 @@ const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const {
265 return impl->global_scheduler; 320 return impl->global_scheduler;
266} 321}
267 322
323Kernel::Scheduler& KernelCore::Scheduler(std::size_t id) {
324 return impl->cores[id].Scheduler();
325}
326
327const Kernel::Scheduler& KernelCore::Scheduler(std::size_t id) const {
328 return impl->cores[id].Scheduler();
329}
330
268Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) { 331Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) {
269 return impl->cores[id]; 332 return impl->cores[id];
270} 333}
@@ -281,6 +344,14 @@ const Kernel::Synchronization& KernelCore::Synchronization() const {
281 return impl->synchronization; 344 return impl->synchronization;
282} 345}
283 346
347Kernel::TimeManager& KernelCore::TimeManager() {
348 return impl->time_manager;
349}
350
351const Kernel::TimeManager& KernelCore::TimeManager() const {
352 return impl->time_manager;
353}
354
284Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { 355Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
285 return *impl->exclusive_monitor; 356 return *impl->exclusive_monitor;
286} 357}
@@ -338,12 +409,28 @@ const std::shared_ptr<Core::Timing::EventType>& KernelCore::ThreadWakeupCallback
338 return impl->thread_wakeup_event_type; 409 return impl->thread_wakeup_event_type;
339} 410}
340 411
341Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() { 412Kernel::HandleTable& KernelCore::GlobalHandleTable() {
342 return impl->thread_wakeup_callback_handle_table; 413 return impl->global_handle_table;
414}
415
416const Kernel::HandleTable& KernelCore::GlobalHandleTable() const {
417 return impl->global_handle_table;
418}
419
420void KernelCore::RegisterCoreThread(std::size_t core_id) {
421 impl->RegisterCoreThread(core_id);
422}
423
424void KernelCore::RegisterHostThread() {
425 impl->RegisterHostThread();
426}
427
428u32 KernelCore::GetCurrentHostThreadID() const {
429 return impl->GetCurrentHostThreadID();
343} 430}
344 431
345const Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() const { 432Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadID() const {
346 return impl->thread_wakeup_callback_handle_table; 433 return impl->GetCurrentEmuThreadID();
347} 434}
348 435
349} // namespace Kernel 436} // namespace Kernel