kernel.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  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 <mutex>
  10. #include <thread>
  11. #include <unordered_map>
  12. #include <utility>
  13. #include "common/assert.h"
  14. #include "common/logging/log.h"
  15. #include "common/microprofile.h"
  16. #include "common/thread.h"
  17. #include "core/arm/arm_interface.h"
  18. #include "core/arm/cpu_interrupt_handler.h"
  19. #include "core/arm/exclusive_monitor.h"
  20. #include "core/arm/unicorn/arm_unicorn.h"
  21. #include "core/core.h"
  22. #include "core/core_timing.h"
  23. #include "core/core_timing_util.h"
  24. #include "core/cpu_manager.h"
  25. #include "core/device_memory.h"
  26. #include "core/hardware_properties.h"
  27. #include "core/hle/kernel/client_port.h"
  28. #include "core/hle/kernel/errors.h"
  29. #include "core/hle/kernel/handle_table.h"
  30. #include "core/hle/kernel/kernel.h"
  31. #include "core/hle/kernel/memory/memory_layout.h"
  32. #include "core/hle/kernel/memory/memory_manager.h"
  33. #include "core/hle/kernel/memory/slab_heap.h"
  34. #include "core/hle/kernel/physical_core.h"
  35. #include "core/hle/kernel/process.h"
  36. #include "core/hle/kernel/resource_limit.h"
  37. #include "core/hle/kernel/scheduler.h"
  38. #include "core/hle/kernel/shared_memory.h"
  39. #include "core/hle/kernel/synchronization.h"
  40. #include "core/hle/kernel/thread.h"
  41. #include "core/hle/kernel/time_manager.h"
  42. #include "core/hle/lock.h"
  43. #include "core/hle/result.h"
  44. #include "core/memory.h"
  45. #ifdef ARCHITECTURE_x86_64
  46. #include "core/arm/dynarmic/arm_dynarmic_32.h"
  47. #include "core/arm/dynarmic/arm_dynarmic_64.h"
  48. #endif
  49. MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
  50. namespace Kernel {
  51. /**
  52. * Callback that will wake up the thread it was scheduled for
  53. * @param thread_handle The handle of the thread that's been awoken
  54. * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
  55. */
  56. static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] s64 cycles_late) {
  57. UNREACHABLE();
  58. const auto proper_handle = static_cast<Handle>(thread_handle);
  59. const auto& system = Core::System::GetInstance();
  60. // Lock the global kernel mutex when we enter the kernel HLE.
  61. std::lock_guard lock{HLE::g_hle_lock};
  62. std::shared_ptr<Thread> thread =
  63. system.Kernel().RetrieveThreadFromGlobalHandleTable(proper_handle);
  64. if (thread == nullptr) {
  65. LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
  66. return;
  67. }
  68. bool resume = true;
  69. if (thread->GetStatus() == ThreadStatus::WaitSynch ||
  70. thread->GetStatus() == ThreadStatus::WaitHLEEvent) {
  71. // Remove the thread from each of its waiting objects' waitlists
  72. for (const auto& object : thread->GetSynchronizationObjects()) {
  73. object->RemoveWaitingThread(thread);
  74. }
  75. thread->ClearSynchronizationObjects();
  76. // Invoke the wakeup callback before clearing the wait objects
  77. if (thread->HasWakeupCallback()) {
  78. resume = thread->InvokeWakeupCallback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
  79. }
  80. } else if (thread->GetStatus() == ThreadStatus::WaitMutex ||
  81. thread->GetStatus() == ThreadStatus::WaitCondVar) {
  82. thread->SetMutexWaitAddress(0);
  83. thread->SetWaitHandle(0);
  84. if (thread->GetStatus() == ThreadStatus::WaitCondVar) {
  85. thread->GetOwnerProcess()->RemoveConditionVariableThread(thread);
  86. thread->SetCondVarWaitAddress(0);
  87. }
  88. auto* const lock_owner = thread->GetLockOwner();
  89. // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance
  90. // and don't have a lock owner unless SignalProcessWideKey was called first and the thread
  91. // wasn't awakened due to the mutex already being acquired.
  92. if (lock_owner != nullptr) {
  93. lock_owner->RemoveMutexWaiter(thread);
  94. }
  95. }
  96. if (thread->GetStatus() == ThreadStatus::WaitArb) {
  97. auto& address_arbiter = thread->GetOwnerProcess()->GetAddressArbiter();
  98. address_arbiter.HandleWakeupThread(thread);
  99. }
  100. if (resume) {
  101. if (thread->GetStatus() == ThreadStatus::WaitCondVar ||
  102. thread->GetStatus() == ThreadStatus::WaitArb) {
  103. thread->SetWaitSynchronizationResult(RESULT_TIMEOUT);
  104. }
  105. thread->ResumeFromWait();
  106. }
  107. }
  108. struct KernelCore::Impl {
  109. explicit Impl(Core::System& system, KernelCore& kernel)
  110. : global_scheduler{kernel}, synchronization{system}, time_manager{system}, system{system} {}
  111. void SetMulticore(bool is_multicore) {
  112. this->is_multicore = is_multicore;
  113. }
  114. void Initialize(KernelCore& kernel) {
  115. Shutdown();
  116. RegisterHostThread();
  117. InitializePhysicalCores();
  118. InitializeSystemResourceLimit(kernel);
  119. InitializeMemoryLayout();
  120. InitializeThreads();
  121. InitializePreemption(kernel);
  122. InitializeSchedulers();
  123. InitializeSuspendThreads();
  124. }
  125. void Shutdown() {
  126. next_object_id = 0;
  127. next_kernel_process_id = Process::InitialKIPIDMin;
  128. next_user_process_id = Process::ProcessIDMin;
  129. next_thread_id = 1;
  130. for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  131. if (suspend_threads[i]) {
  132. suspend_threads[i].reset();
  133. }
  134. }
  135. for (std::size_t i = 0; i < cores.size(); i++) {
  136. cores[i].Shutdown();
  137. }
  138. cores.clear();
  139. registered_core_threads.reset();
  140. process_list.clear();
  141. current_process = nullptr;
  142. system_resource_limit = nullptr;
  143. global_handle_table.Clear();
  144. thread_wakeup_event_type = nullptr;
  145. preemption_event = nullptr;
  146. global_scheduler.Shutdown();
  147. named_ports.clear();
  148. for (auto& core : cores) {
  149. core.Shutdown();
  150. }
  151. cores.clear();
  152. exclusive_monitor.reset();
  153. host_thread_ids.clear();
  154. }
  155. void InitializePhysicalCores() {
  156. exclusive_monitor =
  157. Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES);
  158. for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  159. #ifdef ARCHITECTURE_x86_64
  160. arm_interfaces_32[i] =
  161. std::make_unique<Core::ARM_Dynarmic_32>(system, interrupts, *exclusive_monitor, i);
  162. arm_interfaces_64[i] =
  163. std::make_unique<Core::ARM_Dynarmic_64>(system, interrupts, *exclusive_monitor, i);
  164. #else
  165. arm_interfaces_32[i] = std::make_shared<Core::ARM_Unicorn>(
  166. system, interrupts, ARM_Unicorn::Arch::AArch32, i);
  167. arm_interfaces_64[i] = std::make_shared<Core::ARM_Unicorn>(
  168. system, interrupts, ARM_Unicorn::Arch::AArch64, i);
  169. LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
  170. #endif
  171. cores.emplace_back(system, i, *exclusive_monitor, interrupts[i], *arm_interfaces_32[i],
  172. *arm_interfaces_64[i]);
  173. }
  174. }
  175. void InitializeSchedulers() {
  176. for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  177. cores[i].Scheduler().Initialize();
  178. }
  179. }
  180. // Creates the default system resource limit
  181. void InitializeSystemResourceLimit(KernelCore& kernel) {
  182. system_resource_limit = ResourceLimit::Create(kernel);
  183. // If setting the default system values fails, then something seriously wrong has occurred.
  184. ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x100000000)
  185. .IsSuccess());
  186. ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess());
  187. ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess());
  188. ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess());
  189. ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
  190. if (!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0) ||
  191. !system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0x60000)) {
  192. UNREACHABLE();
  193. }
  194. }
  195. void InitializeThreads() {
  196. thread_wakeup_event_type =
  197. Core::Timing::CreateEvent("ThreadWakeupCallback", ThreadWakeupCallback);
  198. }
  199. void InitializePreemption(KernelCore& kernel) {
  200. preemption_event = Core::Timing::CreateEvent(
  201. "PreemptionCallback", [this, &kernel](u64 userdata, s64 cycles_late) {
  202. {
  203. SchedulerLock lock(kernel);
  204. global_scheduler.PreemptThreads();
  205. }
  206. s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10));
  207. system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
  208. });
  209. s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10));
  210. system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
  211. }
  212. void InitializeSuspendThreads() {
  213. for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  214. std::string name = "Suspend Thread Id:" + std::to_string(i);
  215. std::function<void(void*)> init_func =
  216. system.GetCpuManager().GetSuspendThreadStartFunc();
  217. void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
  218. ThreadType type =
  219. static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_SUSPEND);
  220. auto thread_res = Thread::Create(system, type, name, 0, 0, 0, static_cast<u32>(i), 0,
  221. nullptr, std::move(init_func), init_func_parameter);
  222. suspend_threads[i] = std::move(thread_res).Unwrap();
  223. }
  224. }
  225. void MakeCurrentProcess(Process* process) {
  226. current_process = process;
  227. if (process == nullptr) {
  228. return;
  229. }
  230. for (auto& core : cores) {
  231. core.SetIs64Bit(process->Is64BitProcess());
  232. }
  233. u32 core_id = GetCurrentHostThreadID();
  234. if (core_id < Core::Hardware::NUM_CPU_CORES) {
  235. system.Memory().SetCurrentPageTable(*process, core_id);
  236. }
  237. }
  238. void RegisterCoreThread(std::size_t core_id) {
  239. std::unique_lock lock{register_thread_mutex};
  240. if (!is_multicore) {
  241. single_core_thread_id = std::this_thread::get_id();
  242. }
  243. const std::thread::id this_id = std::this_thread::get_id();
  244. const auto it = host_thread_ids.find(this_id);
  245. ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
  246. ASSERT(it == host_thread_ids.end());
  247. ASSERT(!registered_core_threads[core_id]);
  248. host_thread_ids[this_id] = static_cast<u32>(core_id);
  249. registered_core_threads.set(core_id);
  250. }
  251. void RegisterHostThread() {
  252. std::unique_lock lock{register_thread_mutex};
  253. const std::thread::id this_id = std::this_thread::get_id();
  254. const auto it = host_thread_ids.find(this_id);
  255. if (it != host_thread_ids.end()) {
  256. return;
  257. }
  258. host_thread_ids[this_id] = registered_thread_ids++;
  259. }
  260. u32 GetCurrentHostThreadID() const {
  261. const std::thread::id this_id = std::this_thread::get_id();
  262. if (!is_multicore) {
  263. if (single_core_thread_id == this_id) {
  264. return static_cast<u32>(system.GetCpuManager().CurrentCore());
  265. }
  266. }
  267. const auto it = host_thread_ids.find(this_id);
  268. if (it == host_thread_ids.end()) {
  269. return Core::INVALID_HOST_THREAD_ID;
  270. }
  271. return it->second;
  272. }
  273. Core::EmuThreadHandle GetCurrentEmuThreadID() const {
  274. Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
  275. result.host_handle = GetCurrentHostThreadID();
  276. if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) {
  277. return result;
  278. }
  279. const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler();
  280. const Kernel::Thread* current = sched.GetCurrentThread();
  281. if (current != nullptr && !current->IsPhantomMode()) {
  282. result.guest_handle = current->GetGlobalHandle();
  283. } else {
  284. result.guest_handle = InvalidHandle;
  285. }
  286. return result;
  287. }
  288. void InitializeMemoryLayout() {
  289. // Initialize memory layout
  290. constexpr Memory::MemoryLayout layout{Memory::MemoryLayout::GetDefaultLayout()};
  291. constexpr std::size_t hid_size{0x40000};
  292. constexpr std::size_t font_size{0x1100000};
  293. constexpr std::size_t irs_size{0x8000};
  294. constexpr std::size_t time_size{0x1000};
  295. constexpr PAddr hid_addr{layout.System().StartAddress()};
  296. constexpr PAddr font_pa{layout.System().StartAddress() + hid_size};
  297. constexpr PAddr irs_addr{layout.System().StartAddress() + hid_size + font_size};
  298. constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size};
  299. // Initialize memory manager
  300. memory_manager = std::make_unique<Memory::MemoryManager>();
  301. memory_manager->InitializeManager(Memory::MemoryManager::Pool::Application,
  302. layout.Application().StartAddress(),
  303. layout.Application().EndAddress());
  304. memory_manager->InitializeManager(Memory::MemoryManager::Pool::Applet,
  305. layout.Applet().StartAddress(),
  306. layout.Applet().EndAddress());
  307. memory_manager->InitializeManager(Memory::MemoryManager::Pool::System,
  308. layout.System().StartAddress(),
  309. layout.System().EndAddress());
  310. hid_shared_mem = Kernel::SharedMemory::Create(
  311. system.Kernel(), system.DeviceMemory(), nullptr,
  312. {hid_addr, hid_size / Memory::PageSize}, Memory::MemoryPermission::None,
  313. Memory::MemoryPermission::Read, hid_addr, hid_size, "HID:SharedMemory");
  314. font_shared_mem = Kernel::SharedMemory::Create(
  315. system.Kernel(), system.DeviceMemory(), nullptr,
  316. {font_pa, font_size / Memory::PageSize}, Memory::MemoryPermission::None,
  317. Memory::MemoryPermission::Read, font_pa, font_size, "Font:SharedMemory");
  318. irs_shared_mem = Kernel::SharedMemory::Create(
  319. system.Kernel(), system.DeviceMemory(), nullptr,
  320. {irs_addr, irs_size / Memory::PageSize}, Memory::MemoryPermission::None,
  321. Memory::MemoryPermission::Read, irs_addr, irs_size, "IRS:SharedMemory");
  322. time_shared_mem = Kernel::SharedMemory::Create(
  323. system.Kernel(), system.DeviceMemory(), nullptr,
  324. {time_addr, time_size / Memory::PageSize}, Memory::MemoryPermission::None,
  325. Memory::MemoryPermission::Read, time_addr, time_size, "Time:SharedMemory");
  326. // Allocate slab heaps
  327. user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::Page>>();
  328. // Initialize slab heaps
  329. constexpr u64 user_slab_heap_size{0x3de000};
  330. user_slab_heap_pages->Initialize(
  331. system.DeviceMemory().GetPointer(Core::DramMemoryMap::SlabHeapBase),
  332. user_slab_heap_size);
  333. }
  334. std::atomic<u32> next_object_id{0};
  335. std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin};
  336. std::atomic<u64> next_user_process_id{Process::ProcessIDMin};
  337. std::atomic<u64> next_thread_id{1};
  338. // Lists all processes that exist in the current session.
  339. std::vector<std::shared_ptr<Process>> process_list;
  340. Process* current_process = nullptr;
  341. Kernel::GlobalScheduler global_scheduler;
  342. Kernel::Synchronization synchronization;
  343. Kernel::TimeManager time_manager;
  344. std::shared_ptr<ResourceLimit> system_resource_limit;
  345. std::shared_ptr<Core::Timing::EventType> thread_wakeup_event_type;
  346. std::shared_ptr<Core::Timing::EventType> preemption_event;
  347. // This is the kernel's handle table or supervisor handle table which
  348. // stores all the objects in place.
  349. Kernel::HandleTable global_handle_table;
  350. /// Map of named ports managed by the kernel, which can be retrieved using
  351. /// the ConnectToPort SVC.
  352. NamedPortTable named_ports;
  353. std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
  354. std::vector<Kernel::PhysicalCore> cores;
  355. // 0-3 IDs represent core threads, >3 represent others
  356. std::unordered_map<std::thread::id, u32> host_thread_ids;
  357. u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES};
  358. std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads;
  359. std::mutex register_thread_mutex;
  360. // Kernel memory management
  361. std::unique_ptr<Memory::MemoryManager> memory_manager;
  362. std::unique_ptr<Memory::SlabHeap<Memory::Page>> user_slab_heap_pages;
  363. // Shared memory for services
  364. std::shared_ptr<Kernel::SharedMemory> hid_shared_mem;
  365. std::shared_ptr<Kernel::SharedMemory> font_shared_mem;
  366. std::shared_ptr<Kernel::SharedMemory> irs_shared_mem;
  367. std::shared_ptr<Kernel::SharedMemory> time_shared_mem;
  368. std::array<std::shared_ptr<Thread>, Core::Hardware::NUM_CPU_CORES> suspend_threads{};
  369. std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
  370. std::array<std::unique_ptr<Core::ARM_Interface>, Core::Hardware::NUM_CPU_CORES>
  371. arm_interfaces_32{};
  372. std::array<std::unique_ptr<Core::ARM_Interface>, Core::Hardware::NUM_CPU_CORES>
  373. arm_interfaces_64{};
  374. bool is_multicore{};
  375. std::thread::id single_core_thread_id{};
  376. std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{};
  377. // System context
  378. Core::System& system;
  379. };
  380. KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system, *this)} {}
  381. KernelCore::~KernelCore() {
  382. Shutdown();
  383. }
  384. void KernelCore::SetMulticore(bool is_multicore) {
  385. impl->SetMulticore(is_multicore);
  386. }
  387. void KernelCore::Initialize() {
  388. impl->Initialize(*this);
  389. }
  390. void KernelCore::Shutdown() {
  391. impl->Shutdown();
  392. }
  393. std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const {
  394. return impl->system_resource_limit;
  395. }
  396. std::shared_ptr<Thread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const {
  397. return impl->global_handle_table.Get<Thread>(handle);
  398. }
  399. void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) {
  400. impl->process_list.push_back(std::move(process));
  401. }
  402. void KernelCore::MakeCurrentProcess(Process* process) {
  403. impl->MakeCurrentProcess(process);
  404. }
  405. Process* KernelCore::CurrentProcess() {
  406. return impl->current_process;
  407. }
  408. const Process* KernelCore::CurrentProcess() const {
  409. return impl->current_process;
  410. }
  411. const std::vector<std::shared_ptr<Process>>& KernelCore::GetProcessList() const {
  412. return impl->process_list;
  413. }
  414. Kernel::GlobalScheduler& KernelCore::GlobalScheduler() {
  415. return impl->global_scheduler;
  416. }
  417. const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const {
  418. return impl->global_scheduler;
  419. }
  420. Kernel::Scheduler& KernelCore::Scheduler(std::size_t id) {
  421. return impl->cores[id].Scheduler();
  422. }
  423. const Kernel::Scheduler& KernelCore::Scheduler(std::size_t id) const {
  424. return impl->cores[id].Scheduler();
  425. }
  426. Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) {
  427. return impl->cores[id];
  428. }
  429. const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
  430. return impl->cores[id];
  431. }
  432. Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() {
  433. u32 core_id = impl->GetCurrentHostThreadID();
  434. ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
  435. return impl->cores[core_id];
  436. }
  437. const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
  438. u32 core_id = impl->GetCurrentHostThreadID();
  439. ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
  440. return impl->cores[core_id];
  441. }
  442. Kernel::Scheduler& KernelCore::CurrentScheduler() {
  443. return CurrentPhysicalCore().Scheduler();
  444. }
  445. const Kernel::Scheduler& KernelCore::CurrentScheduler() const {
  446. return CurrentPhysicalCore().Scheduler();
  447. }
  448. Kernel::Synchronization& KernelCore::Synchronization() {
  449. return impl->synchronization;
  450. }
  451. const Kernel::Synchronization& KernelCore::Synchronization() const {
  452. return impl->synchronization;
  453. }
  454. Kernel::TimeManager& KernelCore::TimeManager() {
  455. return impl->time_manager;
  456. }
  457. const Kernel::TimeManager& KernelCore::TimeManager() const {
  458. return impl->time_manager;
  459. }
  460. Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
  461. return *impl->exclusive_monitor;
  462. }
  463. const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const {
  464. return *impl->exclusive_monitor;
  465. }
  466. void KernelCore::InvalidateAllInstructionCaches() {
  467. for (std::size_t i = 0; i < impl->global_scheduler.CpuCoresCount(); i++) {
  468. PhysicalCore(i).ArmInterface().ClearInstructionCache();
  469. }
  470. }
  471. void KernelCore::PrepareReschedule(std::size_t id) {
  472. if (id < impl->global_scheduler.CpuCoresCount()) {
  473. impl->cores[id].Stop();
  474. }
  475. }
  476. void KernelCore::AddNamedPort(std::string name, std::shared_ptr<ClientPort> port) {
  477. impl->named_ports.emplace(std::move(name), std::move(port));
  478. }
  479. KernelCore::NamedPortTable::iterator KernelCore::FindNamedPort(const std::string& name) {
  480. return impl->named_ports.find(name);
  481. }
  482. KernelCore::NamedPortTable::const_iterator KernelCore::FindNamedPort(
  483. const std::string& name) const {
  484. return impl->named_ports.find(name);
  485. }
  486. bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const {
  487. return port != impl->named_ports.cend();
  488. }
  489. u32 KernelCore::CreateNewObjectID() {
  490. return impl->next_object_id++;
  491. }
  492. u64 KernelCore::CreateNewThreadID() {
  493. return impl->next_thread_id++;
  494. }
  495. u64 KernelCore::CreateNewKernelProcessID() {
  496. return impl->next_kernel_process_id++;
  497. }
  498. u64 KernelCore::CreateNewUserProcessID() {
  499. return impl->next_user_process_id++;
  500. }
  501. const std::shared_ptr<Core::Timing::EventType>& KernelCore::ThreadWakeupCallbackEventType() const {
  502. return impl->thread_wakeup_event_type;
  503. }
  504. Kernel::HandleTable& KernelCore::GlobalHandleTable() {
  505. return impl->global_handle_table;
  506. }
  507. const Kernel::HandleTable& KernelCore::GlobalHandleTable() const {
  508. return impl->global_handle_table;
  509. }
  510. void KernelCore::RegisterCoreThread(std::size_t core_id) {
  511. impl->RegisterCoreThread(core_id);
  512. }
  513. void KernelCore::RegisterHostThread() {
  514. impl->RegisterHostThread();
  515. }
  516. u32 KernelCore::GetCurrentHostThreadID() const {
  517. return impl->GetCurrentHostThreadID();
  518. }
  519. Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadID() const {
  520. return impl->GetCurrentEmuThreadID();
  521. }
  522. Memory::MemoryManager& KernelCore::MemoryManager() {
  523. return *impl->memory_manager;
  524. }
  525. const Memory::MemoryManager& KernelCore::MemoryManager() const {
  526. return *impl->memory_manager;
  527. }
  528. Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() {
  529. return *impl->user_slab_heap_pages;
  530. }
  531. const Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() const {
  532. return *impl->user_slab_heap_pages;
  533. }
  534. Kernel::SharedMemory& KernelCore::GetHidSharedMem() {
  535. return *impl->hid_shared_mem;
  536. }
  537. const Kernel::SharedMemory& KernelCore::GetHidSharedMem() const {
  538. return *impl->hid_shared_mem;
  539. }
  540. Kernel::SharedMemory& KernelCore::GetFontSharedMem() {
  541. return *impl->font_shared_mem;
  542. }
  543. const Kernel::SharedMemory& KernelCore::GetFontSharedMem() const {
  544. return *impl->font_shared_mem;
  545. }
  546. Kernel::SharedMemory& KernelCore::GetIrsSharedMem() {
  547. return *impl->irs_shared_mem;
  548. }
  549. const Kernel::SharedMemory& KernelCore::GetIrsSharedMem() const {
  550. return *impl->irs_shared_mem;
  551. }
  552. Kernel::SharedMemory& KernelCore::GetTimeSharedMem() {
  553. return *impl->time_shared_mem;
  554. }
  555. const Kernel::SharedMemory& KernelCore::GetTimeSharedMem() const {
  556. return *impl->time_shared_mem;
  557. }
  558. void KernelCore::Suspend(bool in_suspention) {
  559. const bool should_suspend = exception_exited || in_suspention;
  560. {
  561. SchedulerLock lock(*this);
  562. ThreadStatus status = should_suspend ? ThreadStatus::Ready : ThreadStatus::WaitSleep;
  563. for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
  564. impl->suspend_threads[i]->SetStatus(status);
  565. }
  566. }
  567. }
  568. bool KernelCore::IsMulticore() const {
  569. return impl->is_multicore;
  570. }
  571. void KernelCore::ExceptionalExit() {
  572. exception_exited = true;
  573. Suspend(true);
  574. }
  575. void KernelCore::EnterSVCProfile() {
  576. std::size_t core = impl->GetCurrentHostThreadID();
  577. impl->svc_ticks[core] = MicroProfileEnter(MICROPROFILE_TOKEN(Kernel_SVC));
  578. }
  579. void KernelCore::ExitSVCProfile() {
  580. std::size_t core = impl->GetCurrentHostThreadID();
  581. MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[core]);
  582. }
  583. } // namespace Kernel