From 89edbe8aa20d278d6f2c5ab735163f0d96ff88d2 Mon Sep 17 00:00:00 2001
From: bunnei <bunneidev@gmail.com>
Date: Fri, 9 Apr 2021 22:42:23 -0700
Subject: [PATCH] hle: kernel: Refactor several threads/events/sharedmemory to
 use slab heaps.

---
 src/core/core.cpp                             |  2 +-
 src/core/hle/kernel/k_scheduler.cpp           | 16 +++---
 src/core/hle/kernel/k_scheduler.h             |  4 +-
 src/core/hle/kernel/kernel.cpp                | 50 +++++++++----------
 src/core/hle/kernel/process.cpp               |  2 +-
 src/core/hle/kernel/slab_helpers.h            | 16 +-----
 src/core/hle/kernel/svc.cpp                   |  4 +-
 src/core/hle/service/hid/controllers/npad.cpp |  8 ++-
 src/core/hle/service/hid/controllers/npad.h   |  5 +-
 src/core/hle/service/nvdrv/nvdrv.cpp          |  3 +-
 src/core/hle/service/nvdrv/nvdrv.h            |  2 +-
 11 files changed, 53 insertions(+), 59 deletions(-)

diff --git a/src/core/core.cpp b/src/core/core.cpp
index f050a8d4b6..b5bc903cd1 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -233,7 +233,7 @@ struct System::Impl {
         }
 
         telemetry_session->AddInitialInfo(*app_loader, fs_controller, *content_provider);
-        auto main_process = Kernel::Process::CreateWithKernel(system.Kernel());
+        auto main_process = Kernel::Process::Create(system.Kernel());
         ASSERT(Kernel::Process::Initialize(main_process, system, "main",
                                            Kernel::Process::ProcessType::Userland)
                    .IsSuccess());
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 1feda93031..38c6b50fa2 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -618,14 +618,17 @@ KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core
 }
 
 KScheduler::~KScheduler() {
-    idle_thread->Close();
+    if (idle_thread) {
+        idle_thread->Close();
+        idle_thread = nullptr;
+    }
 }
 
 KThread* KScheduler::GetCurrentThread() const {
     if (auto result = current_thread.load(); result) {
         return result;
     }
-    return idle_thread.get();
+    return idle_thread;
 }
 
 u64 KScheduler::GetLastContextSwitchTicks() const {
@@ -710,7 +713,7 @@ void KScheduler::ScheduleImpl() {
 
     // We never want to schedule a null thread, so use the idle thread if we don't have a next.
     if (next_thread == nullptr) {
-        next_thread = idle_thread.get();
+        next_thread = idle_thread;
     }
 
     // If we're not actually switching thread, there's nothing to do.
@@ -771,7 +774,7 @@ void KScheduler::SwitchToCurrent() {
                     break;
                 }
             }
-            auto thread = next_thread ? next_thread : idle_thread.get();
+            auto thread = next_thread ? next_thread : idle_thread;
             Common::Fiber::YieldTo(switch_fiber, *thread->GetHostContext());
         } while (!is_switch_pending());
     }
@@ -794,9 +797,8 @@ void KScheduler::UpdateLastContextSwitchTime(KThread* thread, Process* process)
 }
 
 void KScheduler::Initialize() {
-    idle_thread = std::make_unique<KThread>(system.Kernel());
-    KAutoObject::Create(idle_thread.get());
-    ASSERT(KThread::InitializeIdleThread(system, idle_thread.get(), core_id).IsSuccess());
+    idle_thread = KThread::Create(system.Kernel());
+    ASSERT(KThread::InitializeIdleThread(system, idle_thread, core_id).IsSuccess());
     idle_thread->SetName(fmt::format("IdleThread:{}", core_id));
 }
 
diff --git a/src/core/hle/kernel/k_scheduler.h b/src/core/hle/kernel/k_scheduler.h
index 8cb5f6f360..01387b8922 100644
--- a/src/core/hle/kernel/k_scheduler.h
+++ b/src/core/hle/kernel/k_scheduler.h
@@ -51,7 +51,7 @@ public:
 
     /// Returns true if the scheduler is idle
     [[nodiscard]] bool IsIdle() const {
-        return GetCurrentThread() == idle_thread.get();
+        return GetCurrentThread() == idle_thread;
     }
 
     /// Gets the timestamp for the last context switch in ticks.
@@ -173,7 +173,7 @@ private:
     KThread* prev_thread{};
     std::atomic<KThread*> current_thread{};
 
-    std::unique_ptr<KThread> idle_thread;
+    KThread* idle_thread{};
 
     std::shared_ptr<Common::Fiber> switch_fiber{};
 
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 43bce18635..1b7ba39f44 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -102,15 +102,21 @@ struct KernelCore::Impl {
         next_user_process_id = Process::ProcessIDMin;
         next_thread_id = 1;
 
-        for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
-            if (suspend_threads[i]) {
-                suspend_threads[i]->Close();
+        for (s32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
+            if (suspend_threads[core_id]) {
+                suspend_threads[core_id]->Close();
+                suspend_threads[core_id] = nullptr;
             }
+
+            schedulers[core_id].reset();
         }
 
         cores.clear();
 
-        current_process = nullptr;
+        if (current_process) {
+            current_process->Close();
+            current_process = nullptr;
+        }
 
         global_handle_table.Clear();
 
@@ -195,10 +201,9 @@ struct KernelCore::Impl {
 
     void InitializeSuspendThreads() {
         for (s32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
-            suspend_threads[core_id] = std::make_unique<KThread>(system.Kernel());
-            KAutoObject::Create(suspend_threads[core_id].get());
-            ASSERT(KThread::InitializeHighPriorityThread(system, suspend_threads[core_id].get(), {},
-                                                         {}, core_id)
+            suspend_threads[core_id] = KThread::Create(system.Kernel());
+            ASSERT(KThread::InitializeHighPriorityThread(system, suspend_threads[core_id], {}, {},
+                                                         core_id)
                        .IsSuccess());
             suspend_threads[core_id]->SetName(fmt::format("SuspendThread:{}", core_id));
         }
@@ -577,15 +582,10 @@ struct KernelCore::Impl {
         const PAddr irs_phys_addr{system_pool.GetAddress() + hid_size + font_size};
         const PAddr time_phys_addr{system_pool.GetAddress() + hid_size + font_size + irs_size};
 
-        hid_shared_mem = std::make_unique<KSharedMemory>(system.Kernel());
-        font_shared_mem = std::make_unique<KSharedMemory>(system.Kernel());
-        irs_shared_mem = std::make_unique<KSharedMemory>(system.Kernel());
-        time_shared_mem = std::make_unique<KSharedMemory>(system.Kernel());
-
-        KAutoObject::Create(hid_shared_mem.get());
-        KAutoObject::Create(font_shared_mem.get());
-        KAutoObject::Create(irs_shared_mem.get());
-        KAutoObject::Create(time_shared_mem.get());
+        hid_shared_mem = KSharedMemory::Create(system.Kernel());
+        font_shared_mem = KSharedMemory::Create(system.Kernel());
+        irs_shared_mem = KSharedMemory::Create(system.Kernel());
+        time_shared_mem = KSharedMemory::Create(system.Kernel());
 
         hid_shared_mem->Initialize(system.Kernel(), system.DeviceMemory(), nullptr,
                                    {hid_phys_addr, hid_size / PageSize}, KMemoryPermission::None,
@@ -656,10 +656,10 @@ struct KernelCore::Impl {
     std::unique_ptr<KSlabHeap<Page>> user_slab_heap_pages;
 
     // Shared memory for services
-    std::unique_ptr<Kernel::KSharedMemory> hid_shared_mem;
-    std::unique_ptr<Kernel::KSharedMemory> font_shared_mem;
-    std::unique_ptr<Kernel::KSharedMemory> irs_shared_mem;
-    std::unique_ptr<Kernel::KSharedMemory> time_shared_mem;
+    Kernel::KSharedMemory* hid_shared_mem{};
+    Kernel::KSharedMemory* font_shared_mem{};
+    Kernel::KSharedMemory* irs_shared_mem{};
+    Kernel::KSharedMemory* time_shared_mem{};
 
     // Threads used for services
     std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads;
@@ -668,7 +668,7 @@ struct KernelCore::Impl {
     // the release of itself
     std::unique_ptr<Common::ThreadWorker> service_thread_manager;
 
-    std::array<std::unique_ptr<KThread>, Core::Hardware::NUM_CPU_CORES> suspend_threads;
+    std::array<KThread*, Core::Hardware::NUM_CPU_CORES> suspend_threads;
     std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
     std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
 
@@ -938,9 +938,9 @@ void KernelCore::Suspend(bool in_suspention) {
     {
         KScopedSchedulerLock lock(*this);
         const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting;
-        for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
-            impl->suspend_threads[i]->SetState(state);
-            impl->suspend_threads[i]->SetWaitReasonForDebugging(
+        for (s32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
+            impl->suspend_threads[core_id]->SetState(state);
+            impl->suspend_threads[core_id]->SetWaitReasonForDebugging(
                 ThreadWaitReasonForDebugging::Suspended);
         }
     }
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index fe4558648a..8088c634f8 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -41,7 +41,7 @@ void SetupMainThread(Core::System& system, Process& owner_process, u32 priority,
     const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart();
     ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1));
 
-    KThread* thread = KThread::CreateWithKernel(system.Kernel());
+    KThread* thread = KThread::Create(system.Kernel());
     ASSERT(KThread::InitializeUserThread(system, thread, entry_point, 0, stack_top, priority,
                                          owner_process.GetIdealCoreId(), &owner_process)
                .IsSuccess());
diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h
index 4f23ddabf2..66954b6b25 100644
--- a/src/core/hle/kernel/slab_helpers.h
+++ b/src/core/hle/kernel/slab_helpers.h
@@ -67,10 +67,6 @@ class KAutoObjectWithSlabHeapAndContainer : public Base {
 
 private:
     static Derived* Allocate(KernelCore& kernel) {
-        return kernel.SlabHeap<Derived>().Allocate();
-    }
-
-    static Derived* AllocateWithKernel(KernelCore& kernel) {
         return kernel.SlabHeap<Derived>().AllocateWithKernel(kernel);
     }
 
@@ -120,16 +116,8 @@ public:
         kernel.ObjectListContainer().Initialize();
     }
 
-    static Derived* Create() {
-        Derived* obj = Allocate();
-        if (obj != nullptr) {
-            KAutoObject::Create(obj);
-        }
-        return obj;
-    }
-
-    static Derived* CreateWithKernel(KernelCore& kernel) {
-        Derived* obj = AllocateWithKernel(kernel);
+    static Derived* Create(KernelCore& kernel) {
+        Derived* obj = Allocate(kernel);
         if (obj != nullptr) {
             KAutoObject::Create(obj);
         }
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index b143a51c7d..8050359be5 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1431,7 +1431,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
     }
 
     // Create the thread.
-    KThread* thread = KThread::CreateWithKernel(kernel);
+    KThread* thread = KThread::Create(kernel);
     if (!thread) {
         LOG_ERROR(Kernel_SVC, "Unable to create new threads. Thread creation limit reached.");
         return ResultOutOfResource;
@@ -1953,7 +1953,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o
     HandleTable& handle_table = kernel.CurrentProcess()->GetHandleTable();
 
     // Create a new event.
-    KEvent* event = KEvent::CreateWithKernel(kernel);
+    KEvent* event = KEvent::Create(kernel);
     R_UNLESS(event != nullptr, ResultOutOfResource);
 
     // Initialize the event.
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 753875d6ee..77768ca7d8 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -253,8 +253,7 @@ void Controller_NPad::InitNewlyAddedController(std::size_t controller_idx) {
 void Controller_NPad::OnInit() {
     auto& kernel = system.Kernel();
     for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
-        styleset_changed_events[i] = std::make_unique<Kernel::KEvent>(kernel);
-        Kernel::KAutoObject::Create(styleset_changed_events[i].get());
+        styleset_changed_events[i] = Kernel::KEvent::Create(kernel);
         styleset_changed_events[i]->Initialize(fmt::format("npad:NpadStyleSetChanged_{}", i));
     }
 
@@ -341,6 +340,11 @@ void Controller_NPad::OnRelease() {
             VibrateControllerAtIndex(npad_idx, device_idx, {});
         }
     }
+
+    for (std::size_t i = 0; i < styleset_changed_events.size(); ++i) {
+        styleset_changed_events[i]->Close();
+        styleset_changed_events[i] = nullptr;
+    }
 }
 
 void Controller_NPad::RequestPadStateUpdate(u32 npad_id) {
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 515cf7c371..b3de272b6c 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -573,8 +573,9 @@ private:
     NpadHandheldActivationMode handheld_activation_mode{NpadHandheldActivationMode::Dual};
     NpadCommunicationMode communication_mode{NpadCommunicationMode::Default};
     // Each controller should have their own styleset changed event
-    std::array<std::unique_ptr<Kernel::KEvent>, 10> styleset_changed_events;
-    std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10> last_vibration_timepoints;
+    std::array<Kernel::KEvent*, 10> styleset_changed_events{};
+    std::array<std::array<std::chrono::steady_clock::time_point, 2>, 10>
+        last_vibration_timepoints{};
     std::array<std::array<VibrationValue, 2>, 10> latest_vibration_values{};
     bool permit_vibration_session_enabled{false};
     std::array<std::array<bool, 2>, 10> vibration_devices_mounted{};
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp
index 64bdb0722d..2fbf61cd65 100644
--- a/src/core/hle/service/nvdrv/nvdrv.cpp
+++ b/src/core/hle/service/nvdrv/nvdrv.cpp
@@ -42,8 +42,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger
 Module::Module(Core::System& system) : syncpoint_manager{system.GPU()} {
     auto& kernel = system.Kernel();
     for (u32 i = 0; i < MaxNvEvents; i++) {
-        events_interface.events[i].event = std::make_unique<Kernel::KEvent>(kernel);
-        Kernel::KAutoObject::Create(events_interface.events[i].event.get());
+        events_interface.events[i].event = Kernel::KEvent::Create(kernel);
         events_interface.events[i].event->Initialize(fmt::format("NVDRV::NvEvent_{}", i));
         events_interface.status[i] = EventState::Free;
         events_interface.registered[i] = false;
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h
index 76f77cbb19..ea5dbbdf99 100644
--- a/src/core/hle/service/nvdrv/nvdrv.h
+++ b/src/core/hle/service/nvdrv/nvdrv.h
@@ -35,7 +35,7 @@ class nvdevice;
 
 /// Represents an Nvidia event
 struct NvEvent {
-    std::unique_ptr<Kernel::KEvent> event;
+    Kernel::KEvent* event{};
     Fence fence{};
 };