kernel.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <array>
  5. #include <atomic>
  6. #include <bitset>
  7. #include <functional>
  8. #include <memory>
  9. #include <thread>
  10. #include <unordered_map>
  11. #include <utility>
  12. #include "common/assert.h"
  13. #include "common/logging/log.h"
  14. #include "common/microprofile.h"
  15. #include "common/thread.h"
  16. #include "core/arm/arm_interface.h"
  17. #include "core/arm/cpu_interrupt_handler.h"
  18. #include "core/arm/exclusive_monitor.h"
  19. #include "core/core.h"
  20. #include "core/core_timing.h"
  21. #include "core/core_timing_util.h"
  22. #include "core/cpu_manager.h"
  23. #include "core/device_memory.h"
  24. #include "core/hardware_properties.h"
  25. #include "core/hle/kernel/client_port.h"
  26. #include "core/hle/kernel/errors.h"
  27. #include "core/hle/kernel/handle_table.h"
  28. #include "core/hle/kernel/kernel.h"
  29. #include "core/hle/kernel/memory/memory_layout.h"
  30. #include "core/hle/kernel/memory/memory_manager.h"
  31. #include "core/hle/kernel/memory/slab_heap.h"
  32. #include "core/hle/kernel/physical_core.h"
  33. #include "core/hle/kernel/process.h"
  34. #include "core/hle/kernel/resource_limit.h"
  35. #include "core/hle/kernel/scheduler.h"
  36. #include "core/hle/kernel/shared_memory.h"
  37. #include "core/hle/kernel/synchronization.h"
  38. #include "core/hle/kernel/thread.h"
  39. #include "core/hle/kernel/time_manager.h"
  40. #include "core/hle/lock.h"
  41. #include "core/hle/result.h"
  42. #include "core/memory.h"
  43. MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
  44. namespace Kernel {
  45. struct KernelCore::Impl {
  46. explicit Impl(Core::System& system, KernelCore& kernel)
  47. : global_scheduler{kernel}, synchronization{system}, time_manager{system},
  48. global_handle_table{kernel}, system{system} {}
  49. void SetMulticore(bool is_multicore) {
  50. this->is_multicore = is_multicore;
  51. }
  52. void Initialize(KernelCore& kernel) {
  53. Shutdown();
  54. RegisterHostThread();
  55. InitializePhysicalCores();
  56. InitializeSystemResourceLimit(kernel);
  57. InitializeMemoryLayout();
  58. InitializePreemption(kernel);
  59. InitializeSchedulers();
  60. InitializeSuspendThreads();
  61. }
  62. void InitializeCores() {
  63. for (auto& core : cores) {
  64. core.Initialize(current_process->Is64BitProcess());
  65. }
  66. }
  67. void Shutdown() {
  68. next_object_id = 0;
  69. next_kernel_process_id = Process::InitialKIPIDMin;
  70. next_user_process_id = Process::ProcessIDMin;
  71. next_thread_id = 1;
  72. for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  73. if (suspend_threads[i]) {
  74. suspend_threads[i].reset();
  75. }
  76. }
  77. for (std::size_t i = 0; i < cores.size(); i++) {
  78. cores[i].Shutdown();
  79. schedulers[i].reset();
  80. }
  81. cores.clear();
  82. process_list.clear();
  83. current_process = nullptr;
  84. system_resource_limit = nullptr;
  85. global_handle_table.Clear();
  86. preemption_event = nullptr;
  87. global_scheduler.Shutdown();
  88. named_ports.clear();
  89. for (auto& core : cores) {
  90. core.Shutdown();
  91. }
  92. cores.clear();
  93. exclusive_monitor.reset();
  94. num_host_threads = 0;
  95. std::fill(register_host_thread_keys.begin(), register_host_thread_keys.end(),
  96. std::thread::id{});
  97. std::fill(register_host_thread_values.begin(), register_host_thread_values.end(), 0);
  98. }
  99. void InitializePhysicalCores() {
  100. exclusive_monitor =
  101. Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES);
  102. for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  103. schedulers[i] = std::make_unique<Kernel::Scheduler>(system, i);
  104. cores.emplace_back(i, system, *schedulers[i], interrupts);
  105. }
  106. }
  107. void InitializeSchedulers() {
  108. for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  109. cores[i].Scheduler().Initialize();
  110. }
  111. }
  112. // Creates the default system resource limit
  113. void InitializeSystemResourceLimit(KernelCore& kernel) {
  114. system_resource_limit = ResourceLimit::Create(kernel);
  115. // If setting the default system values fails, then something seriously wrong has occurred.
  116. ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x100000000)
  117. .IsSuccess());
  118. ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess());
  119. ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess());
  120. ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess());
  121. ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
  122. if (!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0) ||
  123. !system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0x60000)) {
  124. UNREACHABLE();
  125. }
  126. }
  127. void InitializePreemption(KernelCore& kernel) {
  128. preemption_event = Core::Timing::CreateEvent(
  129. "PreemptionCallback", [this, &kernel](std::uintptr_t, std::chrono::nanoseconds) {
  130. {
  131. SchedulerLock lock(kernel);
  132. global_scheduler.PreemptThreads();
  133. }
  134. const auto time_interval = std::chrono::nanoseconds{
  135. Core::Timing::msToCycles(std::chrono::milliseconds(10))};
  136. system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
  137. });
  138. const auto time_interval =
  139. std::chrono::nanoseconds{Core::Timing::msToCycles(std::chrono::milliseconds(10))};
  140. system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
  141. }
  142. void InitializeSuspendThreads() {
  143. for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  144. std::string name = "Suspend Thread Id:" + std::to_string(i);
  145. std::function<void(void*)> init_func = Core::CpuManager::GetSuspendThreadStartFunc();
  146. void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
  147. const auto type =
  148. static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_SUSPEND);
  149. auto thread_res =
  150. Thread::Create(system, type, std::move(name), 0, 0, 0, static_cast<u32>(i), 0,
  151. nullptr, std::move(init_func), init_func_parameter);
  152. suspend_threads[i] = std::move(thread_res).Unwrap();
  153. }
  154. }
  155. void MakeCurrentProcess(Process* process) {
  156. current_process = process;
  157. if (process == nullptr) {
  158. return;
  159. }
  160. const u32 core_id = GetCurrentHostThreadID();
  161. if (core_id < Core::Hardware::NUM_CPU_CORES) {
  162. system.Memory().SetCurrentPageTable(*process, core_id);
  163. }
  164. }
  165. void RegisterCoreThread(std::size_t core_id) {
  166. const std::thread::id this_id = std::this_thread::get_id();
  167. if (!is_multicore) {
  168. single_core_thread_id = this_id;
  169. }
  170. const auto end =
  171. register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
  172. const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
  173. ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
  174. ASSERT(it == end);
  175. InsertHostThread(static_cast<u32>(core_id));
  176. }
  177. void RegisterHostThread() {
  178. const std::thread::id this_id = std::this_thread::get_id();
  179. const auto end =
  180. register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
  181. const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
  182. if (it == end) {
  183. InsertHostThread(registered_thread_ids++);
  184. }
  185. }
  186. void InsertHostThread(u32 value) {
  187. const size_t index = num_host_threads++;
  188. ASSERT_MSG(index < NUM_REGISTRABLE_HOST_THREADS, "Too many host threads");
  189. register_host_thread_values[index] = value;
  190. register_host_thread_keys[index] = std::this_thread::get_id();
  191. }
  192. [[nodiscard]] u32 GetCurrentHostThreadID() const {
  193. const std::thread::id this_id = std::this_thread::get_id();
  194. if (!is_multicore && single_core_thread_id == this_id) {
  195. return static_cast<u32>(system.GetCpuManager().CurrentCore());
  196. }
  197. const auto end =
  198. register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
  199. const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
  200. if (it == end) {
  201. return Core::INVALID_HOST_THREAD_ID;
  202. }
  203. return register_host_thread_values[static_cast<size_t>(
  204. std::distance(register_host_thread_keys.begin(), it))];
  205. }
  206. Core::EmuThreadHandle GetCurrentEmuThreadID() const {
  207. Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
  208. result.host_handle = GetCurrentHostThreadID();
  209. if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) {
  210. return result;
  211. }
  212. const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler();
  213. const Kernel::Thread* current = sched.GetCurrentThread();
  214. if (current != nullptr && !current->IsPhantomMode()) {
  215. result.guest_handle = current->GetGlobalHandle();
  216. } else {
  217. result.guest_handle = InvalidHandle;
  218. }
  219. return result;
  220. }
  221. void InitializeMemoryLayout() {
  222. // Initialize memory layout
  223. constexpr Memory::MemoryLayout layout{Memory::MemoryLayout::GetDefaultLayout()};
  224. constexpr std::size_t hid_size{0x40000};
  225. constexpr std::size_t font_size{0x1100000};
  226. constexpr std::size_t irs_size{0x8000};
  227. constexpr std::size_t time_size{0x1000};
  228. constexpr PAddr hid_addr{layout.System().StartAddress()};
  229. constexpr PAddr font_pa{layout.System().StartAddress() + hid_size};
  230. constexpr PAddr irs_addr{layout.System().StartAddress() + hid_size + font_size};
  231. constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size};
  232. // Initialize memory manager
  233. memory_manager = std::make_unique<Memory::MemoryManager>();
  234. memory_manager->InitializeManager(Memory::MemoryManager::Pool::Application,
  235. layout.Application().StartAddress(),
  236. layout.Application().EndAddress());
  237. memory_manager->InitializeManager(Memory::MemoryManager::Pool::Applet,
  238. layout.Applet().StartAddress(),
  239. layout.Applet().EndAddress());
  240. memory_manager->InitializeManager(Memory::MemoryManager::Pool::System,
  241. layout.System().StartAddress(),
  242. layout.System().EndAddress());
  243. hid_shared_mem = Kernel::SharedMemory::Create(
  244. system.Kernel(), system.DeviceMemory(), nullptr,
  245. {hid_addr, hid_size / Memory::PageSize}, Memory::MemoryPermission::None,
  246. Memory::MemoryPermission::Read, hid_addr, hid_size, "HID:SharedMemory");
  247. font_shared_mem = Kernel::SharedMemory::Create(
  248. system.Kernel(), system.DeviceMemory(), nullptr,
  249. {font_pa, font_size / Memory::PageSize}, Memory::MemoryPermission::None,
  250. Memory::MemoryPermission::Read, font_pa, font_size, "Font:SharedMemory");
  251. irs_shared_mem = Kernel::SharedMemory::Create(
  252. system.Kernel(), system.DeviceMemory(), nullptr,
  253. {irs_addr, irs_size / Memory::PageSize}, Memory::MemoryPermission::None,
  254. Memory::MemoryPermission::Read, irs_addr, irs_size, "IRS:SharedMemory");
  255. time_shared_mem = Kernel::SharedMemory::Create(
  256. system.Kernel(), system.DeviceMemory(), nullptr,
  257. {time_addr, time_size / Memory::PageSize}, Memory::MemoryPermission::None,
  258. Memory::MemoryPermission::Read, time_addr, time_size, "Time:SharedMemory");
  259. // Allocate slab heaps
  260. user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::Page>>();
  261. // Initialize slab heaps
  262. constexpr u64 user_slab_heap_size{0x3de000};
  263. user_slab_heap_pages->Initialize(
  264. system.DeviceMemory().GetPointer(Core::DramMemoryMap::SlabHeapBase),
  265. user_slab_heap_size);
  266. }
  267. std::atomic<u32> next_object_id{0};
  268. std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin};
  269. std::atomic<u64> next_user_process_id{Process::ProcessIDMin};
  270. std::atomic<u64> next_thread_id{1};
  271. // Lists all processes that exist in the current session.
  272. std::vector<std::shared_ptr<Process>> process_list;
  273. Process* current_process = nullptr;
  274. Kernel::GlobalScheduler global_scheduler;
  275. Kernel::Synchronization synchronization;
  276. Kernel::TimeManager time_manager;
  277. std::shared_ptr<ResourceLimit> system_resource_limit;
  278. std::shared_ptr<Core::Timing::EventType> preemption_event;
  279. // This is the kernel's handle table or supervisor handle table which
  280. // stores all the objects in place.
  281. HandleTable global_handle_table;
  282. /// Map of named ports managed by the kernel, which can be retrieved using
  283. /// the ConnectToPort SVC.
  284. NamedPortTable named_ports;
  285. std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
  286. std::vector<Kernel::PhysicalCore> cores;
  287. // 0-3 IDs represent core threads, >3 represent others
  288. std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES};
  289. // Number of host threads is a relatively high number to avoid overflowing
  290. static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 64;
  291. std::atomic<size_t> num_host_threads{0};
  292. std::array<std::atomic<std::thread::id>, NUM_REGISTRABLE_HOST_THREADS>
  293. register_host_thread_keys{};
  294. std::array<std::atomic<u32>, NUM_REGISTRABLE_HOST_THREADS> register_host_thread_values{};
  295. // Kernel memory management
  296. std::unique_ptr<Memory::MemoryManager> memory_manager;
  297. std::unique_ptr<Memory::SlabHeap<Memory::Page>> user_slab_heap_pages;
  298. // Shared memory for services
  299. std::shared_ptr<Kernel::SharedMemory> hid_shared_mem;
  300. std::shared_ptr<Kernel::SharedMemory> font_shared_mem;
  301. std::shared_ptr<Kernel::SharedMemory> irs_shared_mem;
  302. std::shared_ptr<Kernel::SharedMemory> time_shared_mem;
  303. std::array<std::shared_ptr<Thread>, Core::Hardware::NUM_CPU_CORES> suspend_threads{};
  304. std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
  305. std::array<std::unique_ptr<Kernel::Scheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
  306. bool is_multicore{};
  307. std::thread::id single_core_thread_id{};
  308. std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{};
  309. // System context
  310. Core::System& system;
  311. };
  312. KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system, *this)} {}
  313. KernelCore::~KernelCore() {
  314. Shutdown();
  315. }
  316. void KernelCore::SetMulticore(bool is_multicore) {
  317. impl->SetMulticore(is_multicore);
  318. }
  319. void KernelCore::Initialize() {
  320. impl->Initialize(*this);
  321. }
  322. void KernelCore::InitializeCores() {
  323. impl->InitializeCores();
  324. }
  325. void KernelCore::Shutdown() {
  326. impl->Shutdown();
  327. }
  328. std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const {
  329. return impl->system_resource_limit;
  330. }
  331. std::shared_ptr<Thread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const {
  332. return impl->global_handle_table.Get<Thread>(handle);
  333. }
  334. void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) {
  335. impl->process_list.push_back(std::move(process));
  336. }
  337. void KernelCore::MakeCurrentProcess(Process* process) {
  338. impl->MakeCurrentProcess(process);
  339. }
  340. Process* KernelCore::CurrentProcess() {
  341. return impl->current_process;
  342. }
  343. const Process* KernelCore::CurrentProcess() const {
  344. return impl->current_process;
  345. }
  346. const std::vector<std::shared_ptr<Process>>& KernelCore::GetProcessList() const {
  347. return impl->process_list;
  348. }
  349. Kernel::GlobalScheduler& KernelCore::GlobalScheduler() {
  350. return impl->global_scheduler;
  351. }
  352. const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const {
  353. return impl->global_scheduler;
  354. }
  355. Kernel::Scheduler& KernelCore::Scheduler(std::size_t id) {
  356. return *impl->schedulers[id];
  357. }
  358. const Kernel::Scheduler& KernelCore::Scheduler(std::size_t id) const {
  359. return *impl->schedulers[id];
  360. }
  361. Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) {
  362. return impl->cores[id];
  363. }
  364. const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
  365. return impl->cores[id];
  366. }
  367. Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() {
  368. u32 core_id = impl->GetCurrentHostThreadID();
  369. ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
  370. return impl->cores[core_id];
  371. }
  372. const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
  373. u32 core_id = impl->GetCurrentHostThreadID();
  374. ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
  375. return impl->cores[core_id];
  376. }
  377. Kernel::Scheduler& KernelCore::CurrentScheduler() {
  378. u32 core_id = impl->GetCurrentHostThreadID();
  379. ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
  380. return *impl->schedulers[core_id];
  381. }
  382. const Kernel::Scheduler& KernelCore::CurrentScheduler() const {
  383. u32 core_id = impl->GetCurrentHostThreadID();
  384. ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
  385. return *impl->schedulers[core_id];
  386. }
  387. std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts() {
  388. return impl->interrupts;
  389. }
  390. const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts()
  391. const {
  392. return impl->interrupts;
  393. }
  394. Kernel::Synchronization& KernelCore::Synchronization() {
  395. return impl->synchronization;
  396. }
  397. const Kernel::Synchronization& KernelCore::Synchronization() const {
  398. return impl->synchronization;
  399. }
  400. Kernel::TimeManager& KernelCore::TimeManager() {
  401. return impl->time_manager;
  402. }
  403. const Kernel::TimeManager& KernelCore::TimeManager() const {
  404. return impl->time_manager;
  405. }
  406. Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
  407. return *impl->exclusive_monitor;
  408. }
  409. const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const {
  410. return *impl->exclusive_monitor;
  411. }
  412. void KernelCore::InvalidateAllInstructionCaches() {
  413. for (auto& physical_core : impl->cores) {
  414. physical_core.ArmInterface().ClearInstructionCache();
  415. }
  416. }
  417. void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
  418. for (auto& physical_core : impl->cores) {
  419. if (!physical_core.IsInitialized()) {
  420. continue;
  421. }
  422. physical_core.ArmInterface().InvalidateCacheRange(addr, size);
  423. }
  424. }
  425. void KernelCore::PrepareReschedule(std::size_t id) {
  426. // TODO: Reimplement, this
  427. }
  428. void KernelCore::AddNamedPort(std::string name, std::shared_ptr<ClientPort> port) {
  429. impl->named_ports.emplace(std::move(name), std::move(port));
  430. }
  431. KernelCore::NamedPortTable::iterator KernelCore::FindNamedPort(const std::string& name) {
  432. return impl->named_ports.find(name);
  433. }
  434. KernelCore::NamedPortTable::const_iterator KernelCore::FindNamedPort(
  435. const std::string& name) const {
  436. return impl->named_ports.find(name);
  437. }
  438. bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const {
  439. return port != impl->named_ports.cend();
  440. }
  441. u32 KernelCore::CreateNewObjectID() {
  442. return impl->next_object_id++;
  443. }
  444. u64 KernelCore::CreateNewThreadID() {
  445. return impl->next_thread_id++;
  446. }
  447. u64 KernelCore::CreateNewKernelProcessID() {
  448. return impl->next_kernel_process_id++;
  449. }
  450. u64 KernelCore::CreateNewUserProcessID() {
  451. return impl->next_user_process_id++;
  452. }
  453. Kernel::HandleTable& KernelCore::GlobalHandleTable() {
  454. return impl->global_handle_table;
  455. }
  456. const Kernel::HandleTable& KernelCore::GlobalHandleTable() const {
  457. return impl->global_handle_table;
  458. }
  459. void KernelCore::RegisterCoreThread(std::size_t core_id) {
  460. impl->RegisterCoreThread(core_id);
  461. }
  462. void KernelCore::RegisterHostThread() {
  463. impl->RegisterHostThread();
  464. }
  465. u32 KernelCore::GetCurrentHostThreadID() const {
  466. return impl->GetCurrentHostThreadID();
  467. }
  468. Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadID() const {
  469. return impl->GetCurrentEmuThreadID();
  470. }
  471. Memory::MemoryManager& KernelCore::MemoryManager() {
  472. return *impl->memory_manager;
  473. }
  474. const Memory::MemoryManager& KernelCore::MemoryManager() const {
  475. return *impl->memory_manager;
  476. }
  477. Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() {
  478. return *impl->user_slab_heap_pages;
  479. }
  480. const Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() const {
  481. return *impl->user_slab_heap_pages;
  482. }
  483. Kernel::SharedMemory& KernelCore::GetHidSharedMem() {
  484. return *impl->hid_shared_mem;
  485. }
  486. const Kernel::SharedMemory& KernelCore::GetHidSharedMem() const {
  487. return *impl->hid_shared_mem;
  488. }
  489. Kernel::SharedMemory& KernelCore::GetFontSharedMem() {
  490. return *impl->font_shared_mem;
  491. }
  492. const Kernel::SharedMemory& KernelCore::GetFontSharedMem() const {
  493. return *impl->font_shared_mem;
  494. }
  495. Kernel::SharedMemory& KernelCore::GetIrsSharedMem() {
  496. return *impl->irs_shared_mem;
  497. }
  498. const Kernel::SharedMemory& KernelCore::GetIrsSharedMem() const {
  499. return *impl->irs_shared_mem;
  500. }
  501. Kernel::SharedMemory& KernelCore::GetTimeSharedMem() {
  502. return *impl->time_shared_mem;
  503. }
  504. const Kernel::SharedMemory& KernelCore::GetTimeSharedMem() const {
  505. return *impl->time_shared_mem;
  506. }
  507. void KernelCore::Suspend(bool in_suspention) {
  508. const bool should_suspend = exception_exited || in_suspention;
  509. {
  510. SchedulerLock lock(*this);
  511. ThreadStatus status = should_suspend ? ThreadStatus::Ready : ThreadStatus::WaitSleep;
  512. for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  513. impl->suspend_threads[i]->SetStatus(status);
  514. }
  515. }
  516. }
  517. bool KernelCore::IsMulticore() const {
  518. return impl->is_multicore;
  519. }
  520. void KernelCore::ExceptionalExit() {
  521. exception_exited = true;
  522. Suspend(true);
  523. }
  524. void KernelCore::EnterSVCProfile() {
  525. std::size_t core = impl->GetCurrentHostThreadID();
  526. impl->svc_ticks[core] = MicroProfileEnter(MICROPROFILE_TOKEN(Kernel_SVC));
  527. }
  528. void KernelCore::ExitSVCProfile() {
  529. std::size_t core = impl->GetCurrentHostThreadID();
  530. MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[core]);
  531. }
  532. } // namespace Kernel