From 4238754d8c3fd97153b2ade89477c0a2c39682a5 Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Wed, 17 Oct 2018 13:47:42 -0400
Subject: [PATCH 1/9] kernel/process: move next_process_id to kernel instance

---
 src/core/hle/kernel/kernel.cpp  | 3 ---
 src/core/hle/kernel/kernel.h    | 4 ++++
 src/core/hle/kernel/process.cpp | 3 +--
 src/core/hle/kernel/process.h   | 4 +---
 4 files changed, 6 insertions(+), 8 deletions(-)

diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index ba7223db4..306dc6cdd 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -23,9 +23,6 @@ KernelSystem::KernelSystem(u32 system_mode) {
     resource_limits = std::make_unique<ResourceLimitList>(*this);
     Kernel::ThreadingInit();
     Kernel::TimersInit();
-    // TODO(Subv): Start the process ids from 10 for now, as lower PIDs are
-    // reserved for low-level services
-    Process::next_process_id = 10;
 }
 
 /// Shutdown the kernel
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 98a5d14a2..015fbe87f 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -183,6 +183,10 @@ public:
 private:
     std::unique_ptr<ResourceLimitList> resource_limits;
     std::atomic<u32> next_object_id{0};
+
+    // TODO(Subv): Start the process ids from 10 for now, as lower PIDs are
+    // reserved for low-level services
+    u32 next_process_id = 10;
 };
 
 } // namespace Kernel
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index ae799d15f..7f089a4c4 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -32,8 +32,6 @@ SharedPtr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id)
 CodeSet::CodeSet(KernelSystem& kernel) : Object(kernel) {}
 CodeSet::~CodeSet() {}
 
-u32 Process::next_process_id;
-
 SharedPtr<Process> KernelSystem::CreateProcess(SharedPtr<CodeSet> code_set) {
     SharedPtr<Process> process(new Process(*this));
 
@@ -41,6 +39,7 @@ SharedPtr<Process> KernelSystem::CreateProcess(SharedPtr<CodeSet> code_set) {
     process->flags.raw = 0;
     process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
     process->status = ProcessStatus::Created;
+    process->process_id = ++next_process_id;
 
     process_list.push_back(process);
     return process;
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index a141dff4c..70be04ff5 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -123,8 +123,6 @@ public:
         return HANDLE_TYPE;
     }
 
-    static u32 next_process_id;
-
     SharedPtr<CodeSet> codeset;
     /// Resource limit descriptor for this process
     SharedPtr<ResourceLimit> resource_limit;
@@ -145,7 +143,7 @@ public:
     ProcessStatus status;
 
     /// The id of this process
-    u32 process_id = next_process_id++;
+    u32 process_id;
 
     /**
      * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them

From d9342622b031f6ce9721e9560971769f2dd941ec Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Wed, 17 Oct 2018 14:06:47 -0400
Subject: [PATCH 2/9] kennel/process: move process list to kernel instance

---
 src/core/hle/kernel/kernel.h        | 7 +++++++
 src/core/hle/kernel/process.cpp     | 9 +--------
 src/core/hle/kernel/process.h       | 5 -----
 src/core/hle/kernel/thread.cpp      | 1 -
 src/core/hle/service/fs/fs_user.cpp | 2 +-
 5 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 015fbe87f..d3907a382 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -7,6 +7,7 @@
 #include <atomic>
 #include <memory>
 #include <string>
+#include <vector>
 #include <boost/smart_ptr/intrusive_ptr.hpp>
 #include "common/common_types.h"
 #include "core/hle/result.h"
@@ -180,6 +181,9 @@ public:
 
     u32 GenerateObjectID();
 
+    /// Retrieves a process from the current list of processes.
+    SharedPtr<Process> GetProcessById(u32 process_id) const;
+
 private:
     std::unique_ptr<ResourceLimitList> resource_limits;
     std::atomic<u32> next_object_id{0};
@@ -187,6 +191,9 @@ private:
     // TODO(Subv): Start the process ids from 10 for now, as lower PIDs are
     // reserved for low-level services
     u32 next_process_id = 10;
+
+    // Lists all processes that exist in the current session.
+    std::vector<SharedPtr<Process>> process_list;
 };
 
 } // namespace Kernel
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 7f089a4c4..23a4684a6 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -17,9 +17,6 @@
 
 namespace Kernel {
 
-// Lists all processes that exist in the current session.
-static std::vector<SharedPtr<Process>> process_list;
-
 SharedPtr<CodeSet> KernelSystem::CreateCodeSet(std::string name, u64 program_id) {
     SharedPtr<CodeSet> codeset(new CodeSet(*this));
 
@@ -306,11 +303,7 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
 Kernel::Process::Process(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
 Kernel::Process::~Process() {}
 
-void ClearProcessList() {
-    process_list.clear();
-}
-
-SharedPtr<Process> GetProcessById(u32 process_id) {
+SharedPtr<Process> KernelSystem::GetProcessById(u32 process_id) const {
     auto itr = std::find_if(
         process_list.begin(), process_list.end(),
         [&](const SharedPtr<Process>& process) { return process->process_id == process_id; });
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 70be04ff5..89ce9bf8a 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -198,10 +198,5 @@ private:
     KernelSystem& kernel;
 };
 
-void ClearProcessList();
-
-/// Retrieves a process from the current list of processes.
-SharedPtr<Process> GetProcessById(u32 process_id);
-
 extern SharedPtr<Process> g_current_process;
 } // namespace Kernel
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 6844e76d5..99d9df133 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -516,7 +516,6 @@ void ThreadingShutdown() {
     }
     thread_list.clear();
     ready_queue.clear();
-    ClearProcessList();
 }
 
 const std::vector<SharedPtr<Thread>>& GetThreadList() {
diff --git a/src/core/hle/service/fs/fs_user.cpp b/src/core/hle/service/fs/fs_user.cpp
index 7b1316e48..f9b883fe7 100644
--- a/src/core/hle/service/fs/fs_user.cpp
+++ b/src/core/hle/service/fs/fs_user.cpp
@@ -619,7 +619,7 @@ void FS_USER::GetProgramLaunchInfo(Kernel::HLERequestContext& ctx) {
 
     // TODO(Subv): The real FS service manages its own process list and only checks the processes
     // that were registered with the 'fs:REG' service.
-    auto process = Kernel::GetProcessById(process_id);
+    auto process = system.Kernel().GetProcessById(process_id);
 
     IPC::RequestBuilder rb = rp.MakeBuilder(5, 0);
 

From 8fb3d8ff38907ddb28526a66a04505c0cefe9b58 Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Wed, 17 Oct 2018 15:23:56 -0400
Subject: [PATCH 3/9] kernel/process: move current process to kernel instance

Two functional change:
QueryProcessMemory uses the process passed from handle instead current_process
Thread::Stop() uses TLS from owner_process instead of current_process
---
 src/core/core.cpp                           |  6 ++-
 src/core/core.h                             |  3 ++
 src/core/file_sys/archive_savedata.cpp      | 10 +++--
 src/core/file_sys/archive_selfncch.cpp      |  3 +-
 src/core/hle/kernel/handle_table.cpp        |  5 ++-
 src/core/hle/kernel/kernel.cpp              |  9 ++++-
 src/core/hle/kernel/kernel.h                |  5 +++
 src/core/hle/kernel/process.cpp             |  2 -
 src/core/hle/kernel/process.h               |  2 -
 src/core/hle/kernel/shared_memory.cpp       |  4 +-
 src/core/hle/kernel/svc.cpp                 | 45 ++++++++++++---------
 src/core/hle/kernel/thread.cpp              |  8 ++--
 src/core/hle/service/apt/applet_manager.cpp |  2 +-
 src/core/hle/service/cecd/cecd.cpp          |  4 +-
 src/core/hle/service/cecd/cecd.h            |  2 +
 src/core/hle/service/service.cpp            |  9 +++--
 src/core/memory.cpp                         | 20 +++++----
 src/tests/core/arm/arm_test_common.cpp      | 10 +++--
 src/tests/core/arm/arm_test_common.h        |  2 +-
 19 files changed, 96 insertions(+), 55 deletions(-)

diff --git a/src/core/core.cpp b/src/core/core.cpp
index 4d4379299..910083644 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -126,7 +126,9 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file
         return init_result;
     }
 
-    const Loader::ResultStatus load_result{app_loader->Load(Kernel::g_current_process)};
+    Kernel::SharedPtr<Kernel::Process> process;
+    const Loader::ResultStatus load_result{app_loader->Load(process)};
+    kernel->SetCurrentProcess(process);
     if (Loader::ResultStatus::Success != load_result) {
         LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<u32>(load_result));
         System::Shutdown();
@@ -140,7 +142,7 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file
             return ResultStatus::ErrorLoader;
         }
     }
-    Memory::SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table);
+    Memory::SetCurrentPageTable(&kernel->GetCurrentProcess()->vm_manager.page_table);
     status = ResultStatus::Success;
     m_emu_window = &emu_window;
     m_filepath = filepath;
diff --git a/src/core/core.h b/src/core/core.h
index 9341f79a4..ea986f433 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -251,8 +251,11 @@ private:
 
     std::unique_ptr<Service::FS::ArchiveManager> archive_manager;
 
+public: // HACK: this is temporary exposed for tests,
+        // due to WIP kernel refactor causing desync state in memory
     std::unique_ptr<Kernel::KernelSystem> kernel;
 
+private:
     static System s_instance;
 
     ResultStatus status = ResultStatus::Success;
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp
index d551f590f..6e518af8b 100644
--- a/src/core/file_sys/archive_savedata.cpp
+++ b/src/core/file_sys/archive_savedata.cpp
@@ -3,6 +3,7 @@
 // Refer to the license.txt file included.
 
 #include <utility>
+#include "core/core.h"
 #include "core/file_sys/archive_savedata.h"
 #include "core/hle/kernel/process.h"
 
@@ -16,16 +17,19 @@ ArchiveFactory_SaveData::ArchiveFactory_SaveData(
     : sd_savedata_source(std::move(sd_savedata)) {}
 
 ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const Path& path) {
-    return sd_savedata_source->Open(Kernel::g_current_process->codeset->program_id);
+    return sd_savedata_source->Open(
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id);
 }
 
 ResultCode ArchiveFactory_SaveData::Format(const Path& path,
                                            const FileSys::ArchiveFormatInfo& format_info) {
-    return sd_savedata_source->Format(Kernel::g_current_process->codeset->program_id, format_info);
+    return sd_savedata_source->Format(
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id, format_info);
 }
 
 ResultVal<ArchiveFormatInfo> ArchiveFactory_SaveData::GetFormatInfo(const Path& path) const {
-    return sd_savedata_source->GetFormatInfo(Kernel::g_current_process->codeset->program_id);
+    return sd_savedata_source->GetFormatInfo(
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id);
 }
 
 } // namespace FileSys
diff --git a/src/core/file_sys/archive_selfncch.cpp b/src/core/file_sys/archive_selfncch.cpp
index 14be1f966..dc2c61666 100644
--- a/src/core/file_sys/archive_selfncch.cpp
+++ b/src/core/file_sys/archive_selfncch.cpp
@@ -7,6 +7,7 @@
 #include "common/common_types.h"
 #include "common/logging/log.h"
 #include "common/swap.h"
+#include "core/core.h"
 #include "core/file_sys/archive_selfncch.h"
 #include "core/file_sys/errors.h"
 #include "core/file_sys/ivfc_archive.h"
@@ -279,7 +280,7 @@ void ArchiveFactory_SelfNCCH::Register(Loader::AppLoader& app_loader) {
 
 ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SelfNCCH::Open(const Path& path) {
     auto archive = std::make_unique<SelfNCCHArchive>(
-        ncch_data[Kernel::g_current_process->codeset->program_id]);
+        ncch_data[Core::System::GetInstance().Kernel().GetCurrentProcess()->codeset->program_id]);
     return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
 }
 
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index a0805a752..99b65fa93 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -5,6 +5,7 @@
 #include <utility>
 #include "common/assert.h"
 #include "common/logging/log.h"
+#include "core/core.h" // TODO: for current_process. Remove this later
 #include "core/hle/kernel/errors.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/process.h"
@@ -76,7 +77,9 @@ SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
     if (handle == CurrentThread) {
         return GetCurrentThread();
     } else if (handle == CurrentProcess) {
-        return g_current_process;
+        // TODO: should this return HandleTable's parent process, or kernel's current process?
+        // Should change this either way
+        return Core::System::GetInstance().Kernel().GetCurrentProcess();
     }
 
     if (!IsValid(handle)) {
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 306dc6cdd..bed63ff91 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -30,7 +30,6 @@ KernelSystem::~KernelSystem() {
     g_handle_table.Clear(); // Free all kernel objects
 
     Kernel::ThreadingShutdown();
-    g_current_process = nullptr;
 
     Kernel::TimersShutdown();
     Kernel::MemoryShutdown();
@@ -48,4 +47,12 @@ u32 KernelSystem::GenerateObjectID() {
     return next_object_id++;
 }
 
+SharedPtr<Process> KernelSystem::GetCurrentProcess() const {
+    return current_process;
+}
+
+void KernelSystem::SetCurrentProcess(SharedPtr<Process> process) {
+    current_process = std::move(process);
+}
+
 } // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index d3907a382..d461dc6e8 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -184,6 +184,9 @@ public:
     /// Retrieves a process from the current list of processes.
     SharedPtr<Process> GetProcessById(u32 process_id) const;
 
+    SharedPtr<Process> GetCurrentProcess() const;
+    void SetCurrentProcess(SharedPtr<Process> process);
+
 private:
     std::unique_ptr<ResourceLimitList> resource_limits;
     std::atomic<u32> next_object_id{0};
@@ -194,6 +197,8 @@ private:
 
     // Lists all processes that exist in the current session.
     std::vector<SharedPtr<Process>> process_list;
+
+    SharedPtr<Process> current_process;
 };
 
 } // namespace Kernel
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 23a4684a6..c6be6effc 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -313,6 +313,4 @@ SharedPtr<Process> KernelSystem::GetProcessById(u32 process_id) const {
 
     return *itr;
 }
-
-SharedPtr<Process> g_current_process;
 } // namespace Kernel
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 89ce9bf8a..762e0c0a1 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -197,6 +197,4 @@ private:
     friend class KernelSystem;
     KernelSystem& kernel;
 };
-
-extern SharedPtr<Process> g_current_process;
 } // namespace Kernel
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 35bd53003..70a937222 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -52,8 +52,8 @@ SharedPtr<SharedMemory> KernelSystem::CreateSharedMemory(SharedPtr<Process> owne
         }
 
         // Refresh the address mappings for the current process.
-        if (Kernel::g_current_process != nullptr) {
-            Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
+        if (current_process != nullptr) {
+            current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
         }
     } else {
         auto& vm_manager = shared_memory->owner_process->vm_manager;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index c2eeb786f..b27ee5293 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -83,7 +83,7 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
     }
     VMAPermission vma_permissions = (VMAPermission)permissions;
 
-    auto& process = *g_current_process;
+    auto& process = *Core::System::GetInstance().Kernel().GetCurrentProcess();
 
     switch (operation & MEMOP_OPERATION_MASK) {
     case MEMOP_FREE: {
@@ -145,16 +145,17 @@ static ResultCode ControlMemory(u32* out_addr, u32 operation, u32 addr0, u32 add
 }
 
 static void ExitProcess() {
-    LOG_INFO(Kernel_SVC, "Process {} exiting", g_current_process->process_id);
+    SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
+    LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->process_id);
 
-    ASSERT_MSG(g_current_process->status == ProcessStatus::Running, "Process has already exited");
+    ASSERT_MSG(current_process->status == ProcessStatus::Running, "Process has already exited");
 
-    g_current_process->status = ProcessStatus::Exited;
+    current_process->status = ProcessStatus::Exited;
 
     // Stop all the process threads that are currently waiting for objects.
     auto& thread_list = GetThreadList();
     for (auto& thread : thread_list) {
-        if (thread->owner_process != g_current_process)
+        if (thread->owner_process != current_process)
             continue;
 
         if (thread == GetCurrentThread())
@@ -195,7 +196,8 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
     case MemoryPermission::WriteExecute:
     case MemoryPermission::ReadWriteExecute:
     case MemoryPermission::DontCare:
-        return shared_memory->Map(g_current_process.get(), addr, permissions_type,
+        return shared_memory->Map(Core::System::GetInstance().Kernel().GetCurrentProcess().get(),
+                                  addr, permissions_type,
                                   static_cast<MemoryPermission>(other_permissions));
     default:
         LOG_ERROR(Kernel_SVC, "unknown permissions=0x{:08X}", permissions);
@@ -213,7 +215,8 @@ static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) {
     if (shared_memory == nullptr)
         return ERR_INVALID_HANDLE;
 
-    return shared_memory->Unmap(g_current_process.get(), addr);
+    return shared_memory->Unmap(Core::System::GetInstance().Kernel().GetCurrentProcess().get(),
+                                addr);
 }
 
 /// Connect to an OS service given the port name, returns the handle to the port to out
@@ -733,14 +736,16 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point
         return ERR_OUT_OF_RANGE;
     }
 
-    SharedPtr<ResourceLimit>& resource_limit = g_current_process->resource_limit;
+    SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
+
+    SharedPtr<ResourceLimit>& resource_limit = current_process->resource_limit;
     if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
         return ERR_NOT_AUTHORIZED;
     }
 
     if (processor_id == ThreadProcessorIdDefault) {
         // Set the target CPU to the one specified in the process' exheader.
-        processor_id = g_current_process->ideal_processor;
+        processor_id = current_process->ideal_processor;
         ASSERT(processor_id != ThreadProcessorIdDefault);
     }
 
@@ -761,9 +766,9 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point
         break;
     }
 
-    CASCADE_RESULT(SharedPtr<Thread> thread, Core::System::GetInstance().Kernel().CreateThread(
-                                                 name, entry_point, priority, arg, processor_id,
-                                                 stack_top, g_current_process));
+    CASCADE_RESULT(SharedPtr<Thread> thread,
+                   Core::System::GetInstance().Kernel().CreateThread(
+                       name, entry_point, priority, arg, processor_id, stack_top, current_process));
 
     thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO |
                               FPSCR_ROUND_TOZERO); // 0x03C00000
@@ -810,7 +815,8 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
 
     // Note: The kernel uses the current process's resource limit instead of
     // the one from the thread owner's resource limit.
-    SharedPtr<ResourceLimit>& resource_limit = g_current_process->resource_limit;
+    SharedPtr<ResourceLimit>& resource_limit =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->resource_limit;
     if (resource_limit->GetMaxResourceValue(ResourceTypes::PRIORITY) > priority) {
         return ERR_NOT_AUTHORIZED;
     }
@@ -1097,16 +1103,18 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
         return ERR_INVALID_ADDRESS;
     }
 
+    SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
+
     // When trying to create a memory block with address = 0,
     // if the process has the Shared Device Memory flag in the exheader,
     // then we have to allocate from the same region as the caller process instead of the BASE
     // region.
     MemoryRegion region = MemoryRegion::BASE;
-    if (addr == 0 && g_current_process->flags.shared_device_mem)
-        region = g_current_process->flags.memory_region;
+    if (addr == 0 && current_process->flags.shared_device_mem)
+        region = current_process->flags.memory_region;
 
     shared_memory = Core::System::GetInstance().Kernel().CreateSharedMemory(
-        g_current_process, size, static_cast<MemoryPermission>(my_permission),
+        current_process, size, static_cast<MemoryPermission>(my_permission),
         static_cast<MemoryPermission>(other_permission), addr, region);
     CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(shared_memory)));
 
@@ -1407,8 +1415,9 @@ void CallSVC(u32 immediate) {
     // Lock the global kernel mutex when we enter the kernel HLE.
     std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
 
-    ASSERT_MSG(g_current_process->status == ProcessStatus::Running,
-               "Running threads from exiting processes is unimplemented");
+    DEBUG_ASSERT_MSG(Core::System::GetInstance().Kernel().GetCurrentProcess()->status ==
+                         ProcessStatus::Running,
+                     "Running threads from exiting processes is unimplemented");
 
     const FunctionDef* info = GetSVCInfo(immediate);
     if (info) {
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 99d9df133..bc4aba38b 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -96,7 +96,7 @@ void Thread::Stop() {
     u32 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
     u32 tls_slot =
         ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE;
-    Kernel::g_current_process->tls_slots[tls_page].reset(tls_slot);
+    owner_process->tls_slots[tls_page].reset(tls_slot);
 }
 
 /**
@@ -127,7 +127,7 @@ static void SwitchContext(Thread* new_thread) {
         // Cancel any outstanding wakeup events for this thread
         CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle);
 
-        auto previous_process = Kernel::g_current_process;
+        auto previous_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
 
         current_thread = new_thread;
 
@@ -135,8 +135,8 @@ static void SwitchContext(Thread* new_thread) {
         new_thread->status = ThreadStatus::Running;
 
         if (previous_process != current_thread->owner_process) {
-            Kernel::g_current_process = current_thread->owner_process;
-            SetCurrentPageTable(&Kernel::g_current_process->vm_manager.page_table);
+            Core::System::GetInstance().Kernel().SetCurrentProcess(current_thread->owner_process);
+            SetCurrentPageTable(&current_thread->owner_process->vm_manager.page_table);
         }
 
         Core::CPU().LoadContext(new_thread->context);
diff --git a/src/core/hle/service/apt/applet_manager.cpp b/src/core/hle/service/apt/applet_manager.cpp
index bc02c5eb6..076f5f6cf 100644
--- a/src/core/hle/service/apt/applet_manager.cpp
+++ b/src/core/hle/service/apt/applet_manager.cpp
@@ -258,7 +258,7 @@ ResultVal<AppletManager::InitializeResult> AppletManager::Initialize(AppletId ap
     slot_data->applet_id = static_cast<AppletId>(app_id);
     // Note: In the real console the title id of a given applet slot is set by the APT module when
     // calling StartApplication.
-    slot_data->title_id = Kernel::g_current_process->codeset->program_id;
+    slot_data->title_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
     slot_data->attributes.raw = attributes.raw;
 
     if (slot_data->applet_id == AppletId::Application ||
diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp
index f2759e7fc..df217d76e 100644
--- a/src/core/hle/service/cecd/cecd.cpp
+++ b/src/core/hle/service/cecd/cecd.cpp
@@ -97,7 +97,7 @@ void Module::Interface::Open(Kernel::HLERequestContext& ctx) {
 
         if (path_type == CecDataPathType::MboxProgramId) {
             std::vector<u8> program_id(8);
-            u64_le le_program_id = Kernel::g_current_process->codeset->program_id;
+            u64_le le_program_id = cecd->system.Kernel().GetCurrentProcess()->codeset->program_id;
             std::memcpy(program_id.data(), &le_program_id, sizeof(u64));
             session_data->file->Write(0, sizeof(u64), true, program_id.data());
             session_data->file->Close();
@@ -1351,7 +1351,7 @@ Module::SessionData::~SessionData() {
 Module::Interface::Interface(std::shared_ptr<Module> cecd, const char* name, u32 max_session)
     : ServiceFramework(name, max_session), cecd(std::move(cecd)) {}
 
-Module::Module(Core::System& system) {
+Module::Module(Core::System& system) : system(system) {
     using namespace Kernel;
     cecinfo_event = system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "CECD::cecinfo_event");
     change_state_event =
diff --git a/src/core/hle/service/cecd/cecd.h b/src/core/hle/service/cecd/cecd.h
index 3102bc318..d8023f5cf 100644
--- a/src/core/hle/service/cecd/cecd.h
+++ b/src/core/hle/service/cecd/cecd.h
@@ -610,6 +610,8 @@ private:
 
     Kernel::SharedPtr<Kernel::Event> cecinfo_event;
     Kernel::SharedPtr<Kernel::Event> change_state_event;
+
+    Core::System& system;
 };
 
 /// Initialize CECD service(s)
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 6bdafd0e8..117bf2b2c 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -188,11 +188,13 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses
         return ReportUnimplementedFunction(cmd_buf, info);
     }
 
+    Kernel::SharedPtr<Kernel::Process> current_process =
+        Core::System::GetInstance().Kernel().GetCurrentProcess();
+
     // TODO(yuriks): The kernel should be the one handling this as part of translation after
     // everything else is migrated
     Kernel::HLERequestContext context(std::move(server_session));
-    context.PopulateFromIncomingCommandBuffer(cmd_buf, *Kernel::g_current_process,
-                                              Kernel::g_handle_table);
+    context.PopulateFromIncomingCommandBuffer(cmd_buf, *current_process, Kernel::g_handle_table);
 
     LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName().c_str(), cmd_buf));
     handler_invoker(this, info->handler_callback, context);
@@ -204,8 +206,7 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses
     // the thread to sleep then the writing of the command buffer will be deferred to the wakeup
     // callback.
     if (thread->status == Kernel::ThreadStatus::Running) {
-        context.WriteToOutgoingCommandBuffer(cmd_buf, *Kernel::g_current_process,
-                                             Kernel::g_handle_table);
+        context.WriteToOutgoingCommandBuffer(cmd_buf, *current_process, Kernel::g_handle_table);
     }
 }
 
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 52252c932..f109c752f 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -111,7 +111,7 @@ static u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) {
  * using a VMA from the current process.
  */
 static u8* GetPointerFromVMA(VAddr vaddr) {
-    return GetPointerFromVMA(*Kernel::g_current_process, vaddr);
+    return GetPointerFromVMA(*Core::System::GetInstance().Kernel().GetCurrentProcess(), vaddr);
 }
 
 /**
@@ -128,7 +128,8 @@ static MMIORegionPointer GetMMIOHandler(const PageTable& page_table, VAddr vaddr
 }
 
 static MMIORegionPointer GetMMIOHandler(VAddr vaddr) {
-    const PageTable& page_table = Kernel::g_current_process->vm_manager.page_table;
+    const PageTable& page_table =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->vm_manager.page_table;
     return GetMMIOHandler(page_table, vaddr);
 }
 
@@ -229,7 +230,7 @@ bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) {
 }
 
 bool IsValidVirtualAddress(const VAddr vaddr) {
-    return IsValidVirtualAddress(*Kernel::g_current_process, vaddr);
+    return IsValidVirtualAddress(*Core::System::GetInstance().Kernel().GetCurrentProcess(), vaddr);
 }
 
 bool IsValidPhysicalAddress(const PAddr paddr) {
@@ -524,7 +525,8 @@ void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_
 }
 
 void ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_t size) {
-    ReadBlock(*Kernel::g_current_process, src_addr, dest_buffer, size);
+    ReadBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), src_addr, dest_buffer,
+              size);
 }
 
 void Write8(const VAddr addr, const u8 data) {
@@ -592,7 +594,8 @@ void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const voi
 }
 
 void WriteBlock(const VAddr dest_addr, const void* src_buffer, const std::size_t size) {
-    WriteBlock(*Kernel::g_current_process, dest_addr, src_buffer, size);
+    WriteBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), dest_addr, src_buffer,
+               size);
 }
 
 void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) {
@@ -644,7 +647,7 @@ void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std:
 }
 
 void ZeroBlock(const VAddr dest_addr, const std::size_t size) {
-    ZeroBlock(*Kernel::g_current_process, dest_addr, size);
+    ZeroBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), dest_addr, size);
 }
 
 void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
@@ -699,7 +702,7 @@ void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr,
 }
 
 void CopyBlock(VAddr dest_addr, VAddr src_addr, const std::size_t size) {
-    CopyBlock(*Kernel::g_current_process, dest_addr, src_addr, size);
+    CopyBlock(*Core::System::GetInstance().Kernel().GetCurrentProcess(), dest_addr, src_addr, size);
 }
 
 template <>
@@ -778,7 +781,8 @@ std::optional<VAddr> PhysicalToVirtualAddress(const PAddr addr) {
     } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) {
         return addr - VRAM_PADDR + VRAM_VADDR;
     } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) {
-        return addr - FCRAM_PADDR + Kernel::g_current_process->GetLinearHeapAreaAddress();
+        return addr - FCRAM_PADDR +
+               Core::System::GetInstance().Kernel().GetCurrentProcess()->GetLinearHeapAreaAddress();
     } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) {
         return addr - DSP_RAM_PADDR + DSP_RAM_VADDR;
     } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) {
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp
index 4706c2512..1127a504f 100644
--- a/src/tests/core/arm/arm_test_common.cpp
+++ b/src/tests/core/arm/arm_test_common.cpp
@@ -17,10 +17,14 @@ TestEnvironment::TestEnvironment(bool mutable_memory_)
     : mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) {
 
     CoreTiming::Init();
-    kernel = std::make_unique<Kernel::KernelSystem>(0);
+    // HACK: some memory functions are currently referring kernel from the global instance,
+    //       so we need to create the kernel object there.
+    //       Change this when all global states are eliminated.
+    Core::System::GetInstance().kernel = std::make_unique<Kernel::KernelSystem>(0);
+    kernel = Core::System::GetInstance().kernel.get();
 
-    Kernel::g_current_process = kernel->CreateProcess(kernel->CreateCodeSet("", 0));
-    page_table = &Kernel::g_current_process->vm_manager.page_table;
+    kernel->SetCurrentProcess(kernel->CreateProcess(kernel->CreateCodeSet("", 0)));
+    page_table = &kernel->GetCurrentProcess()->vm_manager.page_table;
 
     page_table->pointers.fill(nullptr);
     page_table->attributes.fill(Memory::PageType::Unmapped);
diff --git a/src/tests/core/arm/arm_test_common.h b/src/tests/core/arm/arm_test_common.h
index 4f396416f..b52d26e3c 100644
--- a/src/tests/core/arm/arm_test_common.h
+++ b/src/tests/core/arm/arm_test_common.h
@@ -80,7 +80,7 @@ private:
     std::shared_ptr<TestMemory> test_memory;
     std::vector<WriteRecord> write_records;
 
-    std::unique_ptr<Kernel::KernelSystem> kernel;
+    Kernel::KernelSystem* kernel;
 };
 
 } // namespace ArmTests

From 5b45a3e1b57d9636c5ef7e2a954820f9c88a78b7 Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Thu, 18 Oct 2018 21:40:22 -0400
Subject: [PATCH 4/9] Kernel/Timer: use unordered_map for callback recording

---
 src/core/hle/kernel/timer.cpp | 31 ++++++++++++++++++-------------
 src/core/hle/kernel/timer.h   |  4 ++--
 2 files changed, 20 insertions(+), 15 deletions(-)

diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 8ef96e058..d9d89abd0 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -3,6 +3,7 @@
 // Refer to the license.txt file included.
 
 #include <cinttypes>
+#include <unordered_map>
 #include "common/assert.h"
 #include "common/logging/log.h"
 #include "core/core_timing.h"
@@ -15,12 +16,15 @@ namespace Kernel {
 
 /// The event type of the generic timer callback event
 static CoreTiming::EventType* timer_callback_event_type = nullptr;
-// TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future, allowing
-//               us to simply use a pool index or similar.
-static Kernel::HandleTable timer_callback_handle_table;
+
+static u64 next_timer_callback_id;
+static std::unordered_map<u64, Timer*> timer_callback_table;
 
 Timer::Timer(KernelSystem& kernel) : WaitObject(kernel) {}
-Timer::~Timer() {}
+Timer::~Timer() {
+    Cancel();
+    timer_callback_table.erase(callback_id);
+}
 
 SharedPtr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string name) {
     SharedPtr<Timer> timer(new Timer(*this));
@@ -30,7 +34,8 @@ SharedPtr<Timer> KernelSystem::CreateTimer(ResetType reset_type, std::string nam
     timer->name = std::move(name);
     timer->initial_delay = 0;
     timer->interval_delay = 0;
-    timer->callback_handle = timer_callback_handle_table.Create(timer).Unwrap();
+    timer->callback_id = ++next_timer_callback_id;
+    timer_callback_table[timer->callback_id] = timer.get();
 
     return timer;
 }
@@ -57,12 +62,12 @@ void Timer::Set(s64 initial, s64 interval) {
         // Immediately invoke the callback
         Signal(0);
     } else {
-        CoreTiming::ScheduleEvent(nsToCycles(initial), timer_callback_event_type, callback_handle);
+        CoreTiming::ScheduleEvent(nsToCycles(initial), timer_callback_event_type, callback_id);
     }
 }
 
 void Timer::Cancel() {
-    CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle);
+    CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_id);
 }
 
 void Timer::Clear() {
@@ -87,17 +92,16 @@ void Timer::Signal(s64 cycles_late) {
     if (interval_delay != 0) {
         // Reschedule the timer with the interval delay
         CoreTiming::ScheduleEvent(nsToCycles(interval_delay) - cycles_late,
-                                  timer_callback_event_type, callback_handle);
+                                  timer_callback_event_type, callback_id);
     }
 }
 
 /// The timer callback event, called when a timer is fired
-static void TimerCallback(u64 timer_handle, s64 cycles_late) {
-    SharedPtr<Timer> timer =
-        timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle));
+static void TimerCallback(u64 callback_id, s64 cycles_late) {
+    SharedPtr<Timer> timer = timer_callback_table.at(callback_id);
 
     if (timer == nullptr) {
-        LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:08x}", timer_handle);
+        LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016x}", callback_id);
         return;
     }
 
@@ -105,7 +109,8 @@ static void TimerCallback(u64 timer_handle, s64 cycles_late) {
 }
 
 void TimersInit() {
-    timer_callback_handle_table.Clear();
+    next_timer_callback_id = 0;
+    timer_callback_table.clear();
     timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
 }
 
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index c039bb4f1..653dacb5b 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -71,8 +71,8 @@ private:
     bool signaled;    ///< Whether the timer has been signaled or not
     std::string name; ///< Name of timer (optional)
 
-    /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
-    Handle callback_handle;
+    /// ID used as userdata to reference this object when inserting into the CoreTiming queue.
+    u64 callback_id;
 
     friend class KernelSystem;
 };

From fda2a5cf5492ca7db730636cf47e918b84c2b4bb Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Thu, 18 Oct 2018 22:19:29 -0400
Subject: [PATCH 5/9] kernel/thread: use std::unordered_map for callback record

---
 src/core/hle/kernel/thread.cpp | 25 ++++++++++++-------------
 src/core/hle/kernel/thread.h   |  3 ---
 2 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index bc4aba38b..220e6aa17 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -4,6 +4,7 @@
 
 #include <algorithm>
 #include <list>
+#include <unordered_map>
 #include <vector>
 #include "common/assert.h"
 #include "common/common_types.h"
@@ -37,9 +38,8 @@ void Thread::Acquire(Thread* thread) {
     ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
 }
 
-// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
-//               us to simply use a pool index or similar.
-static Kernel::HandleTable wakeup_callback_handle_table;
+static u64 next_callback_id;
+static std::unordered_map<u64, Thread*> wakeup_callback_table;
 
 // Lists all thread ids that aren't deleted/etc.
 static std::vector<SharedPtr<Thread>> thread_list;
@@ -69,9 +69,8 @@ Thread* GetCurrentThread() {
 
 void Thread::Stop() {
     // Cancel any outstanding wakeup events for this thread
-    CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
-    wakeup_callback_handle_table.Close(callback_handle);
-    callback_handle = 0;
+    CoreTiming::UnscheduleEvent(ThreadWakeupEventType, thread_id);
+    wakeup_callback_table.erase(thread_id);
 
     // Clean up thread from ready queue
     // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
@@ -125,7 +124,7 @@ static void SwitchContext(Thread* new_thread) {
                    "Thread must be ready to become running.");
 
         // Cancel any outstanding wakeup events for this thread
-        CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->callback_handle);
+        CoreTiming::UnscheduleEvent(ThreadWakeupEventType, new_thread->thread_id);
 
         auto previous_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
 
@@ -185,13 +184,13 @@ void ExitCurrentThread() {
 
 /**
  * Callback that will wake up the thread it was scheduled for
- * @param thread_handle The handle of the thread that's been awoken
+ * @param thread_id The ID of the thread that's been awoken
  * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
  */
-static void ThreadWakeupCallback(u64 thread_handle, s64 cycles_late) {
-    SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>((Handle)thread_handle);
+static void ThreadWakeupCallback(u64 thread_id, s64 cycles_late) {
+    SharedPtr<Thread> thread = wakeup_callback_table.at(thread_id);
     if (thread == nullptr) {
-        LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", (Handle)thread_handle);
+        LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", thread_id);
         return;
     }
 
@@ -217,7 +216,7 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
     if (nanoseconds == -1)
         return;
 
-    CoreTiming::ScheduleEvent(nsToCycles(nanoseconds), ThreadWakeupEventType, callback_handle);
+    CoreTiming::ScheduleEvent(nsToCycles(nanoseconds), ThreadWakeupEventType, thread_id);
 }
 
 void Thread::ResumeFromWait() {
@@ -359,7 +358,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr
     thread->wait_objects.clear();
     thread->wait_address = 0;
     thread->name = std::move(name);
-    thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
+    wakeup_callback_table[thread->thread_id] = thread.get();
     thread->owner_process = owner_process;
 
     // Find the next available TLS index, and mark it as used
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 9e6a22759..bb0ab5b15 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -199,9 +199,6 @@ public:
 
     std::string name;
 
-    /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
-    Handle callback_handle;
-
     using WakeupCallback = void(ThreadWakeupReason reason, SharedPtr<Thread> thread,
                                 SharedPtr<WaitObject> object);
     // Callback that will be invoked when the thread is resumed from a waiting state. If the thread

From eb285c33fd2751b8f03afb5b8e207cfa6e4b17cc Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Fri, 19 Oct 2018 21:04:18 -0400
Subject: [PATCH 6/9] kernel: make handle table per-process

---
 src/core/hle/kernel/handle_table.cpp  |   9 +-
 src/core/hle/kernel/handle_table.h    |   6 +-
 src/core/hle/kernel/hle_ipc.cpp       |  15 ++-
 src/core/hle/kernel/hle_ipc.h         |   6 +-
 src/core/hle/kernel/ipc.cpp           |   6 +-
 src/core/hle/kernel/kernel.cpp        |   2 -
 src/core/hle/kernel/process.cpp       |   3 +-
 src/core/hle/kernel/process.h         |   3 +
 src/core/hle/kernel/svc.cpp           | 167 +++++++++++++++++---------
 src/core/hle/service/service.cpp      |   4 +-
 src/tests/core/hle/kernel/hle_ipc.cpp |  67 ++++++-----
 11 files changed, 169 insertions(+), 119 deletions(-)

diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index 99b65fa93..87ba03f36 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -5,7 +5,6 @@
 #include <utility>
 #include "common/assert.h"
 #include "common/logging/log.h"
-#include "core/core.h" // TODO: for current_process. Remove this later
 #include "core/hle/kernel/errors.h"
 #include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/process.h"
@@ -13,9 +12,7 @@
 
 namespace Kernel {
 
-HandleTable g_handle_table;
-
-HandleTable::HandleTable() {
+HandleTable::HandleTable(KernelSystem& kernel) : kernel(kernel) {
     next_generation = 1;
     Clear();
 }
@@ -77,9 +74,7 @@ SharedPtr<Object> HandleTable::GetGeneric(Handle handle) const {
     if (handle == CurrentThread) {
         return GetCurrentThread();
     } else if (handle == CurrentProcess) {
-        // TODO: should this return HandleTable's parent process, or kernel's current process?
-        // Should change this either way
-        return Core::System::GetInstance().Kernel().GetCurrentProcess();
+        return kernel.GetCurrentProcess();
     }
 
     if (!IsValid(handle)) {
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
index 5497dd74a..00cb47a33 100644
--- a/src/core/hle/kernel/handle_table.h
+++ b/src/core/hle/kernel/handle_table.h
@@ -42,7 +42,7 @@ enum KernelHandle : Handle {
  */
 class HandleTable final : NonCopyable {
 public:
-    HandleTable();
+    explicit HandleTable(KernelSystem& kernel);
 
     /**
      * Allocates a handle for the given object.
@@ -119,8 +119,8 @@ private:
 
     /// Head of the free slots linked list.
     u16 next_free_slot;
+
+    KernelSystem& kernel;
 };
 
-extern HandleTable g_handle_table;
-
 } // namespace Kernel
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 1da7c8a81..a72d33dd9 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -50,7 +50,7 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
         std::array<u32_le, IPC::COMMAND_BUFFER_LENGTH + 2 * IPC::MAX_STATIC_BUFFERS> cmd_buff;
         Memory::ReadBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
                           cmd_buff.size() * sizeof(u32));
-        context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process, Kernel::g_handle_table);
+        context.WriteToOutgoingCommandBuffer(cmd_buff.data(), *process);
         // Copy the translated command buffer back into the thread's command buffer area.
         Memory::WriteBlock(*process, thread->GetCommandBufferAddress(), cmd_buff.data(),
                            cmd_buff.size() * sizeof(u32));
@@ -98,8 +98,7 @@ void HLERequestContext::AddStaticBuffer(u8 buffer_id, std::vector<u8> data) {
 }
 
 ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf,
-                                                                Process& src_process,
-                                                                HandleTable& src_table) {
+                                                                Process& src_process) {
     IPC::Header header{src_cmdbuf[0]};
 
     std::size_t untranslated_size = 1u + header.normal_params_size;
@@ -122,10 +121,10 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
                 Handle handle = src_cmdbuf[i];
                 SharedPtr<Object> object = nullptr;
                 if (handle != 0) {
-                    object = src_table.GetGeneric(handle);
+                    object = src_process.handle_table.GetGeneric(handle);
                     ASSERT(object != nullptr); // TODO(yuriks): Return error
                     if (descriptor == IPC::DescriptorType::MoveHandle) {
-                        src_table.Close(handle);
+                        src_process.handle_table.Close(handle);
                     }
                 }
 
@@ -163,8 +162,8 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const u32_le* sr
     return RESULT_SUCCESS;
 }
 
-ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process,
-                                                           HandleTable& dst_table) const {
+ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf,
+                                                           Process& dst_process) const {
     IPC::Header header{cmd_buf[0]};
 
     std::size_t untranslated_size = 1u + header.normal_params_size;
@@ -189,7 +188,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, P
                 Handle handle = 0;
                 if (object != nullptr) {
                     // TODO(yuriks): Figure out the proper error handling for if this fails
-                    handle = dst_table.Create(object).Unwrap();
+                    handle = dst_process.handle_table.Create(object).Unwrap();
                 }
                 dst_cmdbuf[i++] = handle;
             }
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index 3a2b81b16..a41264834 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -226,11 +226,9 @@ public:
     MappedBuffer& GetMappedBuffer(u32 id_from_cmdbuf);
 
     /// Populates this context with data from the requesting process/thread.
-    ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process,
-                                                 HandleTable& src_table);
+    ResultCode PopulateFromIncomingCommandBuffer(const u32_le* src_cmdbuf, Process& src_process);
     /// Writes data from this context back to the requesting process/thread.
-    ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process,
-                                            HandleTable& dst_table) const;
+    ResultCode WriteToOutgoingCommandBuffer(u32_le* dst_cmdbuf, Process& dst_process) const;
 
 private:
     std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
diff --git a/src/core/hle/kernel/ipc.cpp b/src/core/hle/kernel/ipc.cpp
index 8db9d241f..b50a2429f 100644
--- a/src/core/hle/kernel/ipc.cpp
+++ b/src/core/hle/kernel/ipc.cpp
@@ -60,9 +60,9 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
                 } else if (handle == CurrentProcess) {
                     object = src_process;
                 } else if (handle != 0) {
-                    object = g_handle_table.GetGeneric(handle);
+                    object = src_process->handle_table.GetGeneric(handle);
                     if (descriptor == IPC::DescriptorType::MoveHandle) {
-                        g_handle_table.Close(handle);
+                        src_process->handle_table.Close(handle);
                     }
                 }
 
@@ -73,7 +73,7 @@ ResultCode TranslateCommandBuffer(SharedPtr<Thread> src_thread, SharedPtr<Thread
                     continue;
                 }
 
-                auto result = g_handle_table.Create(std::move(object));
+                auto result = dst_process->handle_table.Create(std::move(object));
                 cmd_buf[i++] = result.ValueOr(0);
             }
             break;
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index bed63ff91..afe6af195 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -27,8 +27,6 @@ KernelSystem::KernelSystem(u32 system_mode) {
 
 /// Shutdown the kernel
 KernelSystem::~KernelSystem() {
-    g_handle_table.Clear(); // Free all kernel objects
-
     Kernel::ThreadingShutdown();
 
     Kernel::TimersShutdown();
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index c6be6effc..21204eeb8 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -300,7 +300,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
     return RESULT_SUCCESS;
 }
 
-Kernel::Process::Process(KernelSystem& kernel) : Object(kernel), kernel(kernel) {}
+Kernel::Process::Process(KernelSystem& kernel)
+    : Object(kernel), handle_table(kernel), kernel(kernel) {}
 Kernel::Process::~Process() {}
 
 SharedPtr<Process> KernelSystem::GetProcessById(u32 process_id) const {
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 762e0c0a1..fa04d8c42 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -13,6 +13,7 @@
 #include <boost/container/static_vector.hpp>
 #include "common/bit_field.h"
 #include "common/common_types.h"
+#include "core/hle/kernel/handle_table.h"
 #include "core/hle/kernel/object.h"
 #include "core/hle/kernel/vm_manager.h"
 
@@ -123,6 +124,8 @@ public:
         return HANDLE_TYPE;
     }
 
+    HandleTable handle_table;
+
     SharedPtr<CodeSet> codeset;
     /// Resource limit descriptor for this process
     SharedPtr<ResourceLimit> resource_limit;
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index b27ee5293..94a820f34 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -182,7 +182,9 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
               "otherpermission={}",
               handle, addr, permissions, other_permissions);
 
-    SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(handle);
+    SharedPtr<SharedMemory> shared_memory =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<SharedMemory>(
+            handle);
     if (shared_memory == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -211,12 +213,12 @@ static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) {
 
     // TODO(Subv): Return E0A01BF5 if the address is not in the application's heap
 
-    SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(handle);
+    SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
+    SharedPtr<SharedMemory> shared_memory = current_process->handle_table.Get<SharedMemory>(handle);
     if (shared_memory == nullptr)
         return ERR_INVALID_HANDLE;
 
-    return shared_memory->Unmap(Core::System::GetInstance().Kernel().GetCurrentProcess().get(),
-                                addr);
+    return shared_memory->Unmap(current_process.get(), addr);
 }
 
 /// Connect to an OS service given the port name, returns the handle to the port to out
@@ -244,13 +246,17 @@ static ResultCode ConnectToPort(Handle* out_handle, VAddr port_name_address) {
     CASCADE_RESULT(client_session, client_port->Connect());
 
     // Return the client session
-    CASCADE_RESULT(*out_handle, g_handle_table.Create(client_session));
+    CASCADE_RESULT(*out_handle,
+                   Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Create(
+                       client_session));
     return RESULT_SUCCESS;
 }
 
 /// Makes a blocking IPC call to an OS service.
 static ResultCode SendSyncRequest(Handle handle) {
-    SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle);
+    SharedPtr<ClientSession> session =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<ClientSession>(
+            handle);
     if (session == nullptr) {
         return ERR_INVALID_HANDLE;
     }
@@ -265,12 +271,14 @@ static ResultCode SendSyncRequest(Handle handle) {
 /// Close a handle
 static ResultCode CloseHandle(Handle handle) {
     LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
-    return g_handle_table.Close(handle);
+    return Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Close(handle);
 }
 
 /// Wait for a handle to synchronize, timeout after the specified nanoseconds
 static ResultCode WaitSynchronization1(Handle handle, s64 nano_seconds) {
-    auto object = g_handle_table.Get<WaitObject>(handle);
+    auto object =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<WaitObject>(
+            handle);
     Thread* thread = GetCurrentThread();
 
     if (object == nullptr)
@@ -341,7 +349,9 @@ static ResultCode WaitSynchronizationN(s32* out, VAddr handles_address, s32 hand
 
     for (int i = 0; i < handle_count; ++i) {
         Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
-        auto object = g_handle_table.Get<WaitObject>(handle);
+        auto object =
+            Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<WaitObject>(
+                handle);
         if (object == nullptr)
             return ERR_INVALID_HANDLE;
         objects[i] = object;
@@ -505,9 +515,11 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
     using ObjectPtr = SharedPtr<WaitObject>;
     std::vector<ObjectPtr> objects(handle_count);
 
+    SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
+
     for (int i = 0; i < handle_count; ++i) {
         Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
-        auto object = g_handle_table.Get<WaitObject>(handle);
+        auto object = current_process->handle_table.Get<WaitObject>(handle);
         if (object == nullptr)
             return ERR_INVALID_HANDLE;
         objects[i] = object;
@@ -518,7 +530,7 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
     u32* cmd_buff = GetCommandBuffer();
     IPC::Header header{cmd_buff[0]};
     if (reply_target != 0 && header.command_id != 0xFFFF) {
-        auto session = g_handle_table.Get<ServerSession>(reply_target);
+        auto session = current_process->handle_table.Get<ServerSession>(reply_target);
         if (session == nullptr)
             return ERR_INVALID_HANDLE;
 
@@ -618,8 +630,10 @@ static ResultCode ReplyAndReceive(s32* index, VAddr handles_address, s32 handle_
 
 /// Create an address arbiter (to allocate access to shared resources)
 static ResultCode CreateAddressArbiter(Handle* out_handle) {
-    SharedPtr<AddressArbiter> arbiter = Core::System::GetInstance().Kernel().CreateAddressArbiter();
-    CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(arbiter)));
+    KernelSystem& kernel = Core::System::GetInstance().Kernel();
+    SharedPtr<AddressArbiter> arbiter = kernel.CreateAddressArbiter();
+    CASCADE_RESULT(*out_handle,
+                   kernel.GetCurrentProcess()->handle_table.Create(std::move(arbiter)));
     LOG_TRACE(Kernel_SVC, "returned handle=0x{:08X}", *out_handle);
     return RESULT_SUCCESS;
 }
@@ -630,7 +644,9 @@ static ResultCode ArbitrateAddress(Handle handle, u32 address, u32 type, u32 val
     LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}, address=0x{:08X}, type=0x{:08X}, value=0x{:08X}",
               handle, address, type, value);
 
-    SharedPtr<AddressArbiter> arbiter = g_handle_table.Get<AddressArbiter>(handle);
+    SharedPtr<AddressArbiter> arbiter =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<AddressArbiter>(
+            handle);
     if (arbiter == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -678,11 +694,12 @@ static void OutputDebugString(VAddr address, int len) {
 static ResultCode GetResourceLimit(Handle* resource_limit, Handle process_handle) {
     LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
 
-    SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
+    SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
+    SharedPtr<Process> process = current_process->handle_table.Get<Process>(process_handle);
     if (process == nullptr)
         return ERR_INVALID_HANDLE;
 
-    CASCADE_RESULT(*resource_limit, g_handle_table.Create(process->resource_limit));
+    CASCADE_RESULT(*resource_limit, current_process->handle_table.Create(process->resource_limit));
 
     return RESULT_SUCCESS;
 }
@@ -694,7 +711,8 @@ static ResultCode GetResourceLimitCurrentValues(VAddr values, Handle resource_li
               resource_limit_handle, names, name_count);
 
     SharedPtr<ResourceLimit> resource_limit =
-        g_handle_table.Get<ResourceLimit>(resource_limit_handle);
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<ResourceLimit>(
+            resource_limit_handle);
     if (resource_limit == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -714,7 +732,8 @@ static ResultCode GetResourceLimitLimitValues(VAddr values, Handle resource_limi
               resource_limit_handle, names, name_count);
 
     SharedPtr<ResourceLimit> resource_limit =
-        g_handle_table.Get<ResourceLimit>(resource_limit_handle);
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<ResourceLimit>(
+            resource_limit_handle);
     if (resource_limit == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -773,7 +792,7 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point
     thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO |
                               FPSCR_ROUND_TOZERO); // 0x03C00000
 
-    CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(thread)));
+    CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(thread)));
 
     Core::System::GetInstance().PrepareReschedule();
 
@@ -795,7 +814,8 @@ static void ExitThread() {
 
 /// Gets the priority for the specified thread
 static ResultCode GetThreadPriority(u32* priority, Handle handle) {
-    const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle);
+    const SharedPtr<Thread> thread =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(handle);
     if (thread == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -809,7 +829,8 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
         return ERR_OUT_OF_RANGE;
     }
 
-    SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle);
+    SharedPtr<Thread> thread =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(handle);
     if (thread == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -834,9 +855,10 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
 
 /// Create a mutex
 static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
-    SharedPtr<Mutex> mutex = Core::System::GetInstance().Kernel().CreateMutex(initial_locked != 0);
+    KernelSystem& kernel = Core::System::GetInstance().Kernel();
+    SharedPtr<Mutex> mutex = kernel.CreateMutex(initial_locked != 0);
     mutex->name = fmt::format("mutex-{:08x}", Core::CPU().GetReg(14));
-    CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(mutex)));
+    CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(mutex)));
 
     LOG_TRACE(Kernel_SVC, "called initial_locked={} : created handle=0x{:08X}",
               initial_locked ? "true" : "false", *out_handle);
@@ -848,7 +870,8 @@ static ResultCode CreateMutex(Handle* out_handle, u32 initial_locked) {
 static ResultCode ReleaseMutex(Handle handle) {
     LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}", handle);
 
-    SharedPtr<Mutex> mutex = g_handle_table.Get<Mutex>(handle);
+    SharedPtr<Mutex> mutex =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Mutex>(handle);
     if (mutex == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -859,7 +882,9 @@ static ResultCode ReleaseMutex(Handle handle) {
 static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
     LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
 
-    const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
+    const SharedPtr<Process> process =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Process>(
+            process_handle);
     if (process == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -871,7 +896,9 @@ static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
 static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
     LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
 
-    const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
+    const SharedPtr<Thread> thread =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(
+            thread_handle);
     if (thread == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -887,7 +914,8 @@ static ResultCode GetProcessIdOfThread(u32* process_id, Handle thread_handle) {
 static ResultCode GetThreadId(u32* thread_id, Handle handle) {
     LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", handle);
 
-    const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle);
+    const SharedPtr<Thread> thread =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Thread>(handle);
     if (thread == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -897,10 +925,12 @@ static ResultCode GetThreadId(u32* thread_id, Handle handle) {
 
 /// Creates a semaphore
 static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max_count) {
+    KernelSystem& kernel = Core::System::GetInstance().Kernel();
     CASCADE_RESULT(SharedPtr<Semaphore> semaphore,
-                   Core::System::GetInstance().Kernel().CreateSemaphore(initial_count, max_count));
+                   kernel.CreateSemaphore(initial_count, max_count));
     semaphore->name = fmt::format("semaphore-{:08x}", Core::CPU().GetReg(14));
-    CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(semaphore)));
+    CASCADE_RESULT(*out_handle,
+                   kernel.GetCurrentProcess()->handle_table.Create(std::move(semaphore)));
 
     LOG_TRACE(Kernel_SVC, "called initial_count={}, max_count={}, created handle=0x{:08X}",
               initial_count, max_count, *out_handle);
@@ -911,7 +941,9 @@ static ResultCode CreateSemaphore(Handle* out_handle, s32 initial_count, s32 max
 static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count) {
     LOG_TRACE(Kernel_SVC, "called release_count={}, handle=0x{:08X}", release_count, handle);
 
-    SharedPtr<Semaphore> semaphore = g_handle_table.Get<Semaphore>(handle);
+    SharedPtr<Semaphore> semaphore =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Semaphore>(
+            handle);
     if (semaphore == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -923,7 +955,9 @@ static ResultCode ReleaseSemaphore(s32* count, Handle handle, s32 release_count)
 /// Query process memory
 static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_info,
                                      Handle process_handle, u32 addr) {
-    SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
+    SharedPtr<Process> process =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Process>(
+            process_handle);
     if (process == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -949,9 +983,10 @@ static ResultCode QueryMemory(MemoryInfo* memory_info, PageInfo* page_info, u32
 
 /// Create an event
 static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
-    SharedPtr<Event> evt = Core::System::GetInstance().Kernel().CreateEvent(
-        static_cast<ResetType>(reset_type), fmt::format("event-{:08x}", Core::CPU().GetReg(14)));
-    CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(evt)));
+    KernelSystem& kernel = Core::System::GetInstance().Kernel();
+    SharedPtr<Event> evt = kernel.CreateEvent(static_cast<ResetType>(reset_type),
+                                              fmt::format("event-{:08x}", Core::CPU().GetReg(14)));
+    CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(evt)));
 
     LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type,
               *out_handle);
@@ -960,7 +995,9 @@ static ResultCode CreateEvent(Handle* out_handle, u32 reset_type) {
 
 /// Duplicates a kernel handle
 static ResultCode DuplicateHandle(Handle* out, Handle handle) {
-    CASCADE_RESULT(*out, g_handle_table.Duplicate(handle));
+    CASCADE_RESULT(
+        *out,
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Duplicate(handle));
     LOG_TRACE(Kernel_SVC, "duplicated 0x{:08X} to 0x{:08X}", handle, *out);
     return RESULT_SUCCESS;
 }
@@ -969,7 +1006,8 @@ static ResultCode DuplicateHandle(Handle* out, Handle handle) {
 static ResultCode SignalEvent(Handle handle) {
     LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle);
 
-    SharedPtr<Event> evt = g_handle_table.Get<Event>(handle);
+    SharedPtr<Event> evt =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Event>(handle);
     if (evt == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -982,7 +1020,8 @@ static ResultCode SignalEvent(Handle handle) {
 static ResultCode ClearEvent(Handle handle) {
     LOG_TRACE(Kernel_SVC, "called event=0x{:08X}", handle);
 
-    SharedPtr<Event> evt = g_handle_table.Get<Event>(handle);
+    SharedPtr<Event> evt =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Event>(handle);
     if (evt == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -992,9 +1031,10 @@ static ResultCode ClearEvent(Handle handle) {
 
 /// Creates a timer
 static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
-    SharedPtr<Timer> timer = Core::System::GetInstance().Kernel().CreateTimer(
+    KernelSystem& kernel = Core::System::GetInstance().Kernel();
+    SharedPtr<Timer> timer = kernel.CreateTimer(
         static_cast<ResetType>(reset_type), fmt ::format("timer-{:08x}", Core::CPU().GetReg(14)));
-    CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(timer)));
+    CASCADE_RESULT(*out_handle, kernel.GetCurrentProcess()->handle_table.Create(std::move(timer)));
 
     LOG_TRACE(Kernel_SVC, "called reset_type=0x{:08X} : created handle=0x{:08X}", reset_type,
               *out_handle);
@@ -1005,7 +1045,8 @@ static ResultCode CreateTimer(Handle* out_handle, u32 reset_type) {
 static ResultCode ClearTimer(Handle handle) {
     LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle);
 
-    SharedPtr<Timer> timer = g_handle_table.Get<Timer>(handle);
+    SharedPtr<Timer> timer =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Timer>(handle);
     if (timer == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -1021,7 +1062,8 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
         return ERR_OUT_OF_RANGE_KERNEL;
     }
 
-    SharedPtr<Timer> timer = g_handle_table.Get<Timer>(handle);
+    SharedPtr<Timer> timer =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Timer>(handle);
     if (timer == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -1034,7 +1076,8 @@ static ResultCode SetTimer(Handle handle, s64 initial, s64 interval) {
 static ResultCode CancelTimer(Handle handle) {
     LOG_TRACE(Kernel_SVC, "called timer=0x{:08X}", handle);
 
-    SharedPtr<Timer> timer = g_handle_table.Get<Timer>(handle);
+    SharedPtr<Timer> timer =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Timer>(handle);
     if (timer == nullptr)
         return ERR_INVALID_HANDLE;
 
@@ -1116,7 +1159,7 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
     shared_memory = Core::System::GetInstance().Kernel().CreateSharedMemory(
         current_process, size, static_cast<MemoryPermission>(my_permission),
         static_cast<MemoryPermission>(other_permission), addr, region);
-    CASCADE_RESULT(*out_handle, g_handle_table.Create(std::move(shared_memory)));
+    CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(shared_memory)));
 
     LOG_WARNING(Kernel_SVC, "called addr=0x{:08X}", addr);
     return RESULT_SUCCESS;
@@ -1127,48 +1170,58 @@ static ResultCode CreatePort(Handle* server_port, Handle* client_port, VAddr nam
     // TODO(Subv): Implement named ports.
     ASSERT_MSG(name_address == 0, "Named ports are currently unimplemented");
 
-    auto ports = Core::System::GetInstance().Kernel().CreatePortPair(max_sessions);
-    CASCADE_RESULT(*client_port,
-                   g_handle_table.Create(std::move(std::get<SharedPtr<ClientPort>>(ports))));
+    KernelSystem& kernel = Core::System::GetInstance().Kernel();
+    SharedPtr<Process> current_process = kernel.GetCurrentProcess();
+
+    auto ports = kernel.CreatePortPair(max_sessions);
+    CASCADE_RESULT(*client_port, current_process->handle_table.Create(
+                                     std::move(std::get<SharedPtr<ClientPort>>(ports))));
     // Note: The 3DS kernel also leaks the client port handle if the server port handle fails to be
     // created.
-    CASCADE_RESULT(*server_port,
-                   g_handle_table.Create(std::move(std::get<SharedPtr<ServerPort>>(ports))));
+    CASCADE_RESULT(*server_port, current_process->handle_table.Create(
+                                     std::move(std::get<SharedPtr<ServerPort>>(ports))));
 
     LOG_TRACE(Kernel_SVC, "called max_sessions={}", max_sessions);
     return RESULT_SUCCESS;
 }
 
 static ResultCode CreateSessionToPort(Handle* out_client_session, Handle client_port_handle) {
-    SharedPtr<ClientPort> client_port = g_handle_table.Get<ClientPort>(client_port_handle);
+    SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
+    SharedPtr<ClientPort> client_port =
+        current_process->handle_table.Get<ClientPort>(client_port_handle);
     if (client_port == nullptr)
         return ERR_INVALID_HANDLE;
 
     CASCADE_RESULT(auto session, client_port->Connect());
-    CASCADE_RESULT(*out_client_session, g_handle_table.Create(std::move(session)));
+    CASCADE_RESULT(*out_client_session, current_process->handle_table.Create(std::move(session)));
     return RESULT_SUCCESS;
 }
 
 static ResultCode CreateSession(Handle* server_session, Handle* client_session) {
-    auto sessions = Core::System::GetInstance().Kernel().CreateSessionPair();
+    KernelSystem& kernel = Core::System::GetInstance().Kernel();
+    auto sessions = kernel.CreateSessionPair();
+
+    SharedPtr<Process> current_process = kernel.GetCurrentProcess();
 
     auto& server = std::get<SharedPtr<ServerSession>>(sessions);
-    CASCADE_RESULT(*server_session, g_handle_table.Create(std::move(server)));
+    CASCADE_RESULT(*server_session, current_process->handle_table.Create(std::move(server)));
 
     auto& client = std::get<SharedPtr<ClientSession>>(sessions);
-    CASCADE_RESULT(*client_session, g_handle_table.Create(std::move(client)));
+    CASCADE_RESULT(*client_session, current_process->handle_table.Create(std::move(client)));
 
     LOG_TRACE(Kernel_SVC, "called");
     return RESULT_SUCCESS;
 }
 
 static ResultCode AcceptSession(Handle* out_server_session, Handle server_port_handle) {
-    SharedPtr<ServerPort> server_port = g_handle_table.Get<ServerPort>(server_port_handle);
+    SharedPtr<Process> current_process = Core::System::GetInstance().Kernel().GetCurrentProcess();
+    SharedPtr<ServerPort> server_port =
+        current_process->handle_table.Get<ServerPort>(server_port_handle);
     if (server_port == nullptr)
         return ERR_INVALID_HANDLE;
 
     CASCADE_RESULT(auto session, server_port->Accept());
-    CASCADE_RESULT(*out_server_session, g_handle_table.Create(std::move(session)));
+    CASCADE_RESULT(*out_server_session, current_process->handle_table.Create(std::move(session)));
     return RESULT_SUCCESS;
 }
 
@@ -1218,7 +1271,9 @@ static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) {
 static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) {
     LOG_TRACE(Kernel_SVC, "called process=0x{:08X} type={}", process_handle, type);
 
-    SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
+    SharedPtr<Process> process =
+        Core::System::GetInstance().Kernel().GetCurrentProcess()->handle_table.Get<Process>(
+            process_handle);
     if (process == nullptr)
         return ERR_INVALID_HANDLE;
 
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 117bf2b2c..1217376b1 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -194,7 +194,7 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses
     // TODO(yuriks): The kernel should be the one handling this as part of translation after
     // everything else is migrated
     Kernel::HLERequestContext context(std::move(server_session));
-    context.PopulateFromIncomingCommandBuffer(cmd_buf, *current_process, Kernel::g_handle_table);
+    context.PopulateFromIncomingCommandBuffer(cmd_buf, *current_process);
 
     LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName().c_str(), cmd_buf));
     handler_invoker(this, info->handler_callback, context);
@@ -206,7 +206,7 @@ void ServiceFrameworkBase::HandleSyncRequest(SharedPtr<ServerSession> server_ses
     // the thread to sleep then the writing of the command buffer will be deferred to the wakeup
     // callback.
     if (thread->status == Kernel::ThreadStatus::Running) {
-        context.WriteToOutgoingCommandBuffer(cmd_buf, *current_process, Kernel::g_handle_table);
+        context.WriteToOutgoingCommandBuffer(cmd_buf, *current_process);
     }
 }
 
diff --git a/src/tests/core/hle/kernel/hle_ipc.cpp b/src/tests/core/hle/kernel/hle_ipc.cpp
index 9e093f4e4..068d767b6 100644
--- a/src/tests/core/hle/kernel/hle_ipc.cpp
+++ b/src/tests/core/hle/kernel/hle_ipc.cpp
@@ -26,14 +26,13 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
     HLERequestContext context(std::move(session));
 
     auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
-    HandleTable handle_table;
 
     SECTION("works with empty cmdbuf") {
         const u32_le input[]{
             IPC::MakeHeader(0x1234, 0, 0),
         };
 
-        context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
+        context.PopulateFromIncomingCommandBuffer(input, *process);
 
         REQUIRE(context.CommandBuffer()[0] == 0x12340000);
     }
@@ -46,7 +45,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
             0xAABBCCDD,
         };
 
-        context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
+        context.PopulateFromIncomingCommandBuffer(input, *process);
 
         auto* output = context.CommandBuffer();
         REQUIRE(output[1] == 0x12345678);
@@ -56,34 +55,34 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
 
     SECTION("translates move handles") {
         auto a = MakeObject(kernel);
-        Handle a_handle = handle_table.Create(a).Unwrap();
+        Handle a_handle = process->handle_table.Create(a).Unwrap();
         const u32_le input[]{
             IPC::MakeHeader(0, 0, 2),
             IPC::MoveHandleDesc(1),
             a_handle,
         };
 
-        context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
+        context.PopulateFromIncomingCommandBuffer(input, *process);
 
         auto* output = context.CommandBuffer();
         REQUIRE(context.GetIncomingHandle(output[2]) == a);
-        REQUIRE(handle_table.GetGeneric(a_handle) == nullptr);
+        REQUIRE(process->handle_table.GetGeneric(a_handle) == nullptr);
     }
 
     SECTION("translates copy handles") {
         auto a = MakeObject(kernel);
-        Handle a_handle = handle_table.Create(a).Unwrap();
+        Handle a_handle = process->handle_table.Create(a).Unwrap();
         const u32_le input[]{
             IPC::MakeHeader(0, 0, 2),
             IPC::CopyHandleDesc(1),
             a_handle,
         };
 
-        context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
+        context.PopulateFromIncomingCommandBuffer(input, *process);
 
         auto* output = context.CommandBuffer();
         REQUIRE(context.GetIncomingHandle(output[2]) == a);
-        REQUIRE(handle_table.GetGeneric(a_handle) == a);
+        REQUIRE(process->handle_table.GetGeneric(a_handle) == a);
     }
 
     SECTION("translates multi-handle descriptors") {
@@ -91,12 +90,15 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
         auto b = MakeObject(kernel);
         auto c = MakeObject(kernel);
         const u32_le input[]{
-            IPC::MakeHeader(0, 0, 5),        IPC::MoveHandleDesc(2),
-            handle_table.Create(a).Unwrap(), handle_table.Create(b).Unwrap(),
-            IPC::MoveHandleDesc(1),          handle_table.Create(c).Unwrap(),
+            IPC::MakeHeader(0, 0, 5),
+            IPC::MoveHandleDesc(2),
+            process->handle_table.Create(a).Unwrap(),
+            process->handle_table.Create(b).Unwrap(),
+            IPC::MoveHandleDesc(1),
+            process->handle_table.Create(c).Unwrap(),
         };
 
-        context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
+        context.PopulateFromIncomingCommandBuffer(input, *process);
 
         auto* output = context.CommandBuffer();
         REQUIRE(context.GetIncomingHandle(output[2]) == a);
@@ -111,7 +113,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
             0,
         };
 
-        auto result = context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
+        auto result = context.PopulateFromIncomingCommandBuffer(input, *process);
 
         REQUIRE(result == RESULT_SUCCESS);
         auto* output = context.CommandBuffer();
@@ -125,7 +127,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
             0x98989898,
         };
 
-        context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
+        context.PopulateFromIncomingCommandBuffer(input, *process);
 
         REQUIRE(context.CommandBuffer()[2] == process->process_id);
     }
@@ -145,7 +147,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
             target_address,
         };
 
-        context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
+        context.PopulateFromIncomingCommandBuffer(input, *process);
 
         CHECK(context.GetStaticBuffer(0) == *buffer);
 
@@ -166,7 +168,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
             target_address,
         };
 
-        context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
+        context.PopulateFromIncomingCommandBuffer(input, *process);
 
         std::vector<u8> other_buffer(buffer->size());
         context.GetMappedBuffer(0).Read(other_buffer.data(), 0, buffer->size());
@@ -199,7 +201,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
             0x12345678,
             0xABCDEF00,
             IPC::MoveHandleDesc(1),
-            handle_table.Create(a).Unwrap(),
+            process->handle_table.Create(a).Unwrap(),
             IPC::CallingPidDesc(),
             0,
             IPC::StaticBufferDesc(buffer_static->size(), 0),
@@ -208,7 +210,7 @@ TEST_CASE("HLERequestContext::PopulateFromIncomingCommandBuffer", "[core][kernel
             target_address_mapped,
         };
 
-        context.PopulateFromIncomingCommandBuffer(input, *process, handle_table);
+        context.PopulateFromIncomingCommandBuffer(input, *process);
 
         auto* output = context.CommandBuffer();
         CHECK(output[1] == 0x12345678);
@@ -236,14 +238,13 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
     HLERequestContext context(std::move(session));
 
     auto process = kernel.CreateProcess(kernel.CreateCodeSet("", 0));
-    HandleTable handle_table;
     auto* input = context.CommandBuffer();
     u32_le output[IPC::COMMAND_BUFFER_LENGTH];
 
     SECTION("works with empty cmdbuf") {
         input[0] = IPC::MakeHeader(0x1234, 0, 0);
 
-        context.WriteToOutgoingCommandBuffer(output, *process, handle_table);
+        context.WriteToOutgoingCommandBuffer(output, *process);
 
         REQUIRE(output[0] == 0x12340000);
     }
@@ -254,7 +255,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
         input[2] = 0x21122112;
         input[3] = 0xAABBCCDD;
 
-        context.WriteToOutgoingCommandBuffer(output, *process, handle_table);
+        context.WriteToOutgoingCommandBuffer(output, *process);
 
         REQUIRE(output[1] == 0x12345678);
         REQUIRE(output[2] == 0x21122112);
@@ -270,10 +271,10 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
         input[3] = IPC::CopyHandleDesc(1);
         input[4] = context.AddOutgoingHandle(b);
 
-        context.WriteToOutgoingCommandBuffer(output, *process, handle_table);
+        context.WriteToOutgoingCommandBuffer(output, *process);
 
-        REQUIRE(handle_table.GetGeneric(output[2]) == a);
-        REQUIRE(handle_table.GetGeneric(output[4]) == b);
+        REQUIRE(process->handle_table.GetGeneric(output[2]) == a);
+        REQUIRE(process->handle_table.GetGeneric(output[4]) == b);
     }
 
     SECTION("translates null handles") {
@@ -281,7 +282,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
         input[1] = IPC::MoveHandleDesc(1);
         input[2] = context.AddOutgoingHandle(nullptr);
 
-        auto result = context.WriteToOutgoingCommandBuffer(output, *process, handle_table);
+        auto result = context.WriteToOutgoingCommandBuffer(output, *process);
 
         REQUIRE(result == RESULT_SUCCESS);
         REQUIRE(output[2] == 0);
@@ -298,11 +299,11 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
         input[4] = IPC::CopyHandleDesc(1);
         input[5] = context.AddOutgoingHandle(c);
 
-        context.WriteToOutgoingCommandBuffer(output, *process, handle_table);
+        context.WriteToOutgoingCommandBuffer(output, *process);
 
-        REQUIRE(handle_table.GetGeneric(output[2]) == a);
-        REQUIRE(handle_table.GetGeneric(output[3]) == b);
-        REQUIRE(handle_table.GetGeneric(output[5]) == c);
+        REQUIRE(process->handle_table.GetGeneric(output[2]) == a);
+        REQUIRE(process->handle_table.GetGeneric(output[3]) == b);
+        REQUIRE(process->handle_table.GetGeneric(output[5]) == c);
     }
 
     SECTION("translates StaticBuffer descriptors") {
@@ -329,7 +330,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
             IPC::StaticBufferDesc(output_buffer->size(), 0);
         output_cmdbuff[IPC::COMMAND_BUFFER_LENGTH + 1] = target_address;
 
-        context.WriteToOutgoingCommandBuffer(output_cmdbuff.data(), *process, handle_table);
+        context.WriteToOutgoingCommandBuffer(output_cmdbuff.data(), *process);
 
         CHECK(*output_buffer == input_buffer);
         REQUIRE(process->vm_manager.UnmapRange(target_address, output_buffer->size()) ==
@@ -352,7 +353,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
             target_address,
         };
 
-        context.PopulateFromIncomingCommandBuffer(input_cmdbuff, *process, handle_table);
+        context.PopulateFromIncomingCommandBuffer(input_cmdbuff, *process);
 
         context.GetMappedBuffer(0).Write(input_buffer.data(), 0, input_buffer.size());
 
@@ -360,7 +361,7 @@ TEST_CASE("HLERequestContext::WriteToOutgoingCommandBuffer", "[core][kernel]") {
         input[1] = IPC::MappedBufferDesc(output_buffer->size(), IPC::W);
         input[2] = 0;
 
-        context.WriteToOutgoingCommandBuffer(output, *process, handle_table);
+        context.WriteToOutgoingCommandBuffer(output, *process);
 
         CHECK(output[1] == IPC::MappedBufferDesc(output_buffer->size(), IPC::W));
         CHECK(output[2] == target_address);

From 8d32843d68907de5cdbe438eb917faf25259f123 Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Tue, 23 Oct 2018 10:06:32 -0400
Subject: [PATCH 7/9] thread/kernel: remove unused callback_id

we use the thread id for the same purpose now
---
 src/core/hle/kernel/thread.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 220e6aa17..69680acf8 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -38,7 +38,6 @@ void Thread::Acquire(Thread* thread) {
     ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
 }
 
-static u64 next_callback_id;
 static std::unordered_map<u64, Thread*> wakeup_callback_table;
 
 // Lists all thread ids that aren't deleted/etc.

From e5c5d1eccee6dbeb4d2e20dd3d1a80e8f0b4ce26 Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Thu, 25 Oct 2018 19:54:06 -0400
Subject: [PATCH 8/9] Kernel: change owner_process in Thread/SharedMemory to
 raw pointer

Otherwise circular ownership would form in Process->handle_table->thread->owner_process
---
 src/core/hle/kernel/kernel.h          | 4 ++--
 src/core/hle/kernel/shared_memory.cpp | 2 +-
 src/core/hle/kernel/shared_memory.h   | 2 +-
 src/core/hle/kernel/svc.cpp           | 8 ++++----
 src/core/hle/kernel/thread.cpp        | 5 ++---
 src/core/hle/kernel/thread.h          | 2 +-
 6 files changed, 11 insertions(+), 12 deletions(-)

diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index d461dc6e8..223b3ce37 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -102,7 +102,7 @@ public:
      */
     ResultVal<SharedPtr<Thread>> CreateThread(std::string name, VAddr entry_point, u32 priority,
                                               u32 arg, s32 processor_id, VAddr stack_top,
-                                              SharedPtr<Process> owner_process);
+                                              Process* owner_process);
 
     /**
      * Creates a semaphore.
@@ -156,7 +156,7 @@ public:
      * linear heap.
      * @param name Optional object name, used for debugging purposes.
      */
-    SharedPtr<SharedMemory> CreateSharedMemory(SharedPtr<Process> owner_process, u32 size,
+    SharedPtr<SharedMemory> CreateSharedMemory(Process* owner_process, u32 size,
                                                MemoryPermission permissions,
                                                MemoryPermission other_permissions,
                                                VAddr address = 0,
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index 70a937222..4f0b2e8ee 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -14,7 +14,7 @@ namespace Kernel {
 SharedMemory::SharedMemory(KernelSystem& kernel) : Object(kernel) {}
 SharedMemory::~SharedMemory() {}
 
-SharedPtr<SharedMemory> KernelSystem::CreateSharedMemory(SharedPtr<Process> owner_process, u32 size,
+SharedPtr<SharedMemory> KernelSystem::CreateSharedMemory(Process* owner_process, u32 size,
                                                          MemoryPermission permissions,
                                                          MemoryPermission other_permissions,
                                                          VAddr address, MemoryRegion region,
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index d5d862927..18a87b9fe 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -58,7 +58,7 @@ public:
     u8* GetPointer(u32 offset = 0);
 
     /// Process that created this shared memory block.
-    SharedPtr<Process> owner_process;
+    Process* owner_process;
     /// Address of shared memory block in the owner process if specified.
     VAddr base_address;
     /// Physical address of the shared memory block in the linear heap if no address was specified
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 94a820f34..0e7a21c0a 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -785,9 +785,9 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point
         break;
     }
 
-    CASCADE_RESULT(SharedPtr<Thread> thread,
-                   Core::System::GetInstance().Kernel().CreateThread(
-                       name, entry_point, priority, arg, processor_id, stack_top, current_process));
+    CASCADE_RESULT(SharedPtr<Thread> thread, Core::System::GetInstance().Kernel().CreateThread(
+                                                 name, entry_point, priority, arg, processor_id,
+                                                 stack_top, current_process.get()));
 
     thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO |
                               FPSCR_ROUND_TOZERO); // 0x03C00000
@@ -1157,7 +1157,7 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
         region = current_process->flags.memory_region;
 
     shared_memory = Core::System::GetInstance().Kernel().CreateSharedMemory(
-        current_process, size, static_cast<MemoryPermission>(my_permission),
+        current_process.get(), size, static_cast<MemoryPermission>(my_permission),
         static_cast<MemoryPermission>(other_permission), addr, region);
     CASCADE_RESULT(*out_handle, current_process->handle_table.Create(std::move(shared_memory)));
 
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 69680acf8..11ea54fbd 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -320,8 +320,7 @@ static void ResetThreadContext(const std::unique_ptr<ARM_Interface::ThreadContex
 
 ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr entry_point,
                                                         u32 priority, u32 arg, s32 processor_id,
-                                                        VAddr stack_top,
-                                                        SharedPtr<Process> owner_process) {
+                                                        VAddr stack_top, Process* owner_process) {
     // Check if priority is in ranged. Lowest priority -> highest priority id.
     if (priority > ThreadPrioLowest) {
         LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
@@ -447,7 +446,7 @@ SharedPtr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 pri
     // Initialize new "main" thread
     auto thread_res =
         kernel.CreateThread("main", entry_point, priority, 0, owner_process->ideal_processor,
-                            Memory::HEAP_VADDR_END, owner_process);
+                            Memory::HEAP_VADDR_END, owner_process.get());
 
     SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
 
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index bb0ab5b15..9c7dd45cc 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -189,7 +189,7 @@ public:
     /// Mutexes that this thread is currently waiting for.
     boost::container::flat_set<SharedPtr<Mutex>> pending_mutexes;
 
-    SharedPtr<Process> owner_process; ///< Process that owns this thread
+    Process* owner_process; ///< Process that owns this thread
 
     /// Objects that the thread is waiting on, in the same order as they were
     // passed to WaitSynchronization1/N.

From 8ad6cbfde2bcd59ad1571eb06085b37ca67e5bde Mon Sep 17 00:00:00 2001
From: Weiyi Wang <wwylele@gmail.com>
Date: Fri, 26 Oct 2018 09:37:46 -0400
Subject: [PATCH 9/9] kernel/thread: change owner_process parameter to
 reference

To enforce a valid process object
---
 src/core/hle/kernel/kernel.h   |  2 +-
 src/core/hle/kernel/svc.cpp    |  2 +-
 src/core/hle/kernel/thread.cpp | 14 +++++++-------
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 223b3ce37..344635c6a 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -102,7 +102,7 @@ public:
      */
     ResultVal<SharedPtr<Thread>> CreateThread(std::string name, VAddr entry_point, u32 priority,
                                               u32 arg, s32 processor_id, VAddr stack_top,
-                                              Process* owner_process);
+                                              Process& owner_process);
 
     /**
      * Creates a semaphore.
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 0e7a21c0a..6a33736ba 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -787,7 +787,7 @@ static ResultCode CreateThread(Handle* out_handle, u32 priority, u32 entry_point
 
     CASCADE_RESULT(SharedPtr<Thread> thread, Core::System::GetInstance().Kernel().CreateThread(
                                                  name, entry_point, priority, arg, processor_id,
-                                                 stack_top, current_process.get()));
+                                                 stack_top, *current_process));
 
     thread->context->SetFpscr(FPSCR_DEFAULT_NAN | FPSCR_FLUSH_TO_ZERO |
                               FPSCR_ROUND_TOZERO); // 0x03C00000
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 11ea54fbd..a7b6eba1e 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -320,7 +320,7 @@ static void ResetThreadContext(const std::unique_ptr<ARM_Interface::ThreadContex
 
 ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr entry_point,
                                                         u32 priority, u32 arg, s32 processor_id,
-                                                        VAddr stack_top, Process* owner_process) {
+                                                        VAddr stack_top, Process& owner_process) {
     // Check if priority is in ranged. Lowest priority -> highest priority id.
     if (priority > ThreadPrioLowest) {
         LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
@@ -334,7 +334,7 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr
 
     // TODO(yuriks): Other checks, returning 0xD9001BEA
 
-    if (!Memory::IsValidVirtualAddress(*owner_process, entry_point)) {
+    if (!Memory::IsValidVirtualAddress(owner_process, entry_point)) {
         LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:08x}", name, entry_point);
         // TODO: Verify error
         return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
@@ -357,10 +357,10 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr
     thread->wait_address = 0;
     thread->name = std::move(name);
     wakeup_callback_table[thread->thread_id] = thread.get();
-    thread->owner_process = owner_process;
+    thread->owner_process = &owner_process;
 
     // Find the next available TLS index, and mark it as used
-    auto& tls_slots = owner_process->tls_slots;
+    auto& tls_slots = owner_process.tls_slots;
 
     auto [available_page, available_slot, needs_allocation] = GetFreeThreadLocalSlot(tls_slots);
 
@@ -381,13 +381,13 @@ ResultVal<SharedPtr<Thread>> KernelSystem::CreateThread(std::string name, VAddr
         // Allocate some memory from the end of the linear heap for this region.
         linheap_memory->insert(linheap_memory->end(), Memory::PAGE_SIZE, 0);
         memory_region->used += Memory::PAGE_SIZE;
-        owner_process->linear_heap_used += Memory::PAGE_SIZE;
+        owner_process.linear_heap_used += Memory::PAGE_SIZE;
 
         tls_slots.emplace_back(0); // The page is completely available at the start
         available_page = tls_slots.size() - 1;
         available_slot = 0; // Use the first slot in the new page
 
-        auto& vm_manager = owner_process->vm_manager;
+        auto& vm_manager = owner_process.vm_manager;
         vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
 
         // Map the page to the current process' address space.
@@ -446,7 +446,7 @@ SharedPtr<Thread> SetupMainThread(KernelSystem& kernel, u32 entry_point, u32 pri
     // Initialize new "main" thread
     auto thread_res =
         kernel.CreateThread("main", entry_point, priority, 0, owner_process->ideal_processor,
-                            Memory::HEAP_VADDR_END, owner_process.get());
+                            Memory::HEAP_VADDR_END, *owner_process);
 
     SharedPtr<Thread> thread = std::move(thread_res).Unwrap();