diff options
| author | bunnei <bunneidev@gmail.com> | 2018-08-30 10:02:50 -0400 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-08-30 10:02:50 -0400 | 
| commit | 5094dfa081c7275e35496374a42996b11f0f6005 (patch) | |
| tree | 8cdfb8c270c6299a1b172fb9c14856684bedf084 | |
| parent | 42ef40884f222bfd0dfa08cd56e01e89b0e2ab0f (diff) | |
| parent | 0cbcd6ec9aeeafc298fe2e6e4ac10d68bb7267c5 (diff) | |
Merge pull request #1198 from lioncash/kernel
kernel: Eliminate kernel global state
54 files changed, 671 insertions, 442 deletions
| diff --git a/src/core/core.cpp b/src/core/core.cpp index 07da4c493..2293669e5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -171,6 +171,14 @@ const std::shared_ptr<Kernel::Scheduler>& System::Scheduler(size_t core_index) {      return cpu_cores[core_index]->Scheduler();  } +Kernel::KernelCore& System::Kernel() { +    return kernel; +} + +const Kernel::KernelCore& System::Kernel() const { +    return kernel; +} +  ARM_Interface& System::ArmInterface(size_t core_index) {      ASSERT(core_index < NUM_CPU_CORES);      return cpu_cores[core_index]->ArmInterface(); @@ -185,12 +193,13 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {      LOG_DEBUG(HW_Memory, "initialized OK");      CoreTiming::Init(); +    kernel.Initialize();      // Create a default fs if one doesn't already exist.      if (virtual_filesystem == nullptr)          virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>(); -    current_process = Kernel::Process::Create("main"); +    current_process = Kernel::Process::Create(kernel, "main");      cpu_barrier = std::make_shared<CpuBarrier>();      cpu_exclusive_monitor = Cpu::MakeExclusiveMonitor(cpu_cores.size()); @@ -201,7 +210,6 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {      telemetry_session = std::make_unique<Core::TelemetrySession>();      service_manager = std::make_shared<Service::SM::ServiceManager>(); -    Kernel::Init();      Service::Init(service_manager, virtual_filesystem);      GDBStub::Init(); @@ -246,7 +254,6 @@ void System::Shutdown() {      renderer.reset();      GDBStub::Shutdown();      Service::Shutdown(); -    Kernel::Shutdown();      service_manager.reset();      telemetry_session.reset();      gpu_core.reset(); @@ -265,7 +272,8 @@ void System::Shutdown() {      }      cpu_barrier.reset(); -    // Close core timing +    // Shutdown kernel and core timing +    kernel.Shutdown();      CoreTiming::Shutdown();      // Close app loader diff --git a/src/core/core.h b/src/core/core.h index 321104585..2c18f7193 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -12,6 +12,7 @@  #include "common/common_types.h"  #include "core/arm/exclusive_monitor.h"  #include "core/core_cpu.h" +#include "core/hle/kernel/kernel.h"  #include "core/hle/kernel/object.h"  #include "core/hle/kernel/scheduler.h"  #include "core/loader/loader.h" @@ -188,6 +189,12 @@ public:          return current_process;      } +    /// Provides a reference to the kernel instance. +    Kernel::KernelCore& Kernel(); + +    /// Provides a constant reference to the kernel instance. +    const Kernel::KernelCore& Kernel() const; +      /// Gets the name of the current game      Loader::ResultStatus GetGameName(std::string& out) const {          if (app_loader == nullptr) @@ -246,6 +253,7 @@ private:       */      ResultStatus Init(Frontend::EmuWindow& emu_window); +    Kernel::KernelCore kernel;      /// RealVfsFilesystem instance      FileSys::VirtualFilesystem virtual_filesystem;      /// AppLoader used to load the current executing application diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index d3a734831..0f3ffdb60 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -12,6 +12,7 @@  #include <utility>  #include "common/assert.h"  #include "common/common_types.h" +#include "core/core.h"  #include "core/hle/ipc.h"  #include "core/hle/kernel/client_port.h"  #include "core/hle/kernel/client_session.h" @@ -135,7 +136,9 @@ public:          if (context->Session()->IsDomain()) {              context->AddDomainObject(std::move(iface));          } else { -            auto sessions = Kernel::ServerSession::CreateSessionPair(iface->GetServiceName()); +            auto& kernel = Core::System::GetInstance().Kernel(); +            auto sessions = +                Kernel::ServerSession::CreateSessionPair(kernel, iface->GetServiceName());              auto server = std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions);              auto client = std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions);              iface->ClientConnected(server); diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index 134e41ebc..873d6c516 100644 --- a/src/core/hle/kernel/client_port.cpp +++ b/src/core/hle/kernel/client_port.cpp @@ -14,7 +14,7 @@  namespace Kernel { -ClientPort::ClientPort() = default; +ClientPort::ClientPort(KernelCore& kernel) : Object{kernel} {}  ClientPort::~ClientPort() = default;  ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() { @@ -27,7 +27,7 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {      active_sessions++;      // Create a new session pair, let the created sessions inherit the parent port's HLE handler. -    auto sessions = ServerSession::CreateSessionPair(server_port->GetName(), this); +    auto sessions = ServerSession::CreateSessionPair(kernel, server_port->GetName(), this);      if (server_port->hle_handler)          server_port->hle_handler->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions)); diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h index b1269ea5c..f3dfebbb1 100644 --- a/src/core/hle/kernel/client_port.h +++ b/src/core/hle/kernel/client_port.h @@ -11,8 +11,9 @@  namespace Kernel { -class ServerPort;  class ClientSession; +class KernelCore; +class ServerPort;  class ClientPort final : public Object {  public: @@ -44,7 +45,7 @@ public:      void ConnectionClosed();  private: -    ClientPort(); +    explicit ClientPort(KernelCore& kernel);      ~ClientPort() override;      SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port. diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp index fdffc648d..c114eaf99 100644 --- a/src/core/hle/kernel/client_session.cpp +++ b/src/core/hle/kernel/client_session.cpp @@ -11,7 +11,7 @@  namespace Kernel { -ClientSession::ClientSession() = default; +ClientSession::ClientSession(KernelCore& kernel) : Object{kernel} {}  ClientSession::~ClientSession() {      // This destructor will be called automatically when the last ClientSession handle is closed by      // the emulated application. diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h index dabd93ed7..439fbdb35 100644 --- a/src/core/hle/kernel/client_session.h +++ b/src/core/hle/kernel/client_session.h @@ -12,8 +12,9 @@  namespace Kernel { -class ServerSession; +class KernelCore;  class Session; +class ServerSession;  class Thread;  class ClientSession final : public Object { @@ -41,7 +42,7 @@ public:      std::shared_ptr<Session> parent;  private: -    ClientSession(); +    explicit ClientSession(KernelCore& kernel);      ~ClientSession() override;  }; diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp index 5623c4b6a..8967e602e 100644 --- a/src/core/hle/kernel/event.cpp +++ b/src/core/hle/kernel/event.cpp @@ -10,11 +10,11 @@  namespace Kernel { -Event::Event() {} -Event::~Event() {} +Event::Event(KernelCore& kernel) : WaitObject{kernel} {} +Event::~Event() = default; -SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) { -    SharedPtr<Event> evt(new Event); +SharedPtr<Event> Event::Create(KernelCore& kernel, ResetType reset_type, std::string name) { +    SharedPtr<Event> evt(new Event(kernel));      evt->signaled = false;      evt->reset_type = reset_type; diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h index 3c20c05e8..27d6126b0 100644 --- a/src/core/hle/kernel/event.h +++ b/src/core/hle/kernel/event.h @@ -10,14 +10,18 @@  namespace Kernel { +class KernelCore; +  class Event final : public WaitObject {  public:      /**       * Creates an event +     * @param kernel The kernel instance to create this event under.       * @param reset_type ResetType describing how to create event       * @param name Optional name of event       */ -    static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown"); +    static SharedPtr<Event> Create(KernelCore& kernel, ResetType reset_type, +                                   std::string name = "Unknown");      std::string GetTypeName() const override {          return "Event"; @@ -44,7 +48,7 @@ public:      void Clear();  private: -    Event(); +    explicit Event(KernelCore& kernel);      ~Event() override;      ResetType reset_type; ///< Current ResetType diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index 6d9f7a02b..3a079b9a9 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/src/core/hle/kernel/handle_table.cpp @@ -13,8 +13,6 @@  namespace Kernel { -HandleTable g_handle_table; -  HandleTable::HandleTable() {      next_generation = 1;      Clear(); diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h index aee3583e8..cac928adb 100644 --- a/src/core/hle/kernel/handle_table.h +++ b/src/core/hle/kernel/handle_table.h @@ -121,6 +121,4 @@ private:      u16 next_free_slot;  }; -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 82a3fb5a8..db7aef766 100644 --- a/src/core/hle/kernel/hle_ipc.cpp +++ b/src/core/hle/kernel/hle_ipc.cpp @@ -13,6 +13,7 @@  #include "common/common_funcs.h"  #include "common/common_types.h"  #include "common/logging/log.h" +#include "core/core.h"  #include "core/hle/ipc_helpers.h"  #include "core/hle/kernel/event.h"  #include "core/hle/kernel/handle_table.h" @@ -51,7 +52,9 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,      if (!event) {          // Create event if not provided -        event = Kernel::Event::Create(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason); +        auto& kernel = Core::System::GetInstance().Kernel(); +        event = +            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);      }      event->Clear(); @@ -90,12 +93,14 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {              rp.Skip(2, false);          }          if (incoming) { +            auto& handle_table = Core::System::GetInstance().Kernel().HandleTable(); +              // Populate the object lists with the data in the IPC request.              for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) { -                copy_objects.push_back(Kernel::g_handle_table.GetGeneric(rp.Pop<Handle>())); +                copy_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));              }              for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { -                move_objects.push_back(Kernel::g_handle_table.GetGeneric(rp.Pop<Handle>())); +                move_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));              }          } else {              // For responses we just ignore the handles, they're empty and will be populated when @@ -230,17 +235,19 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(const Thread& thread)          ASSERT(copy_objects.size() == handle_descriptor_header->num_handles_to_copy);          ASSERT(move_objects.size() == handle_descriptor_header->num_handles_to_move); +        auto& handle_table = Core::System::GetInstance().Kernel().HandleTable(); +          // We don't make a distinction between copy and move handles when translating since HLE          // services don't deal with handles directly. However, the guest applications might check          // for specific values in each of these descriptors.          for (auto& object : copy_objects) {              ASSERT(object != nullptr); -            dst_cmdbuf[current_offset++] = Kernel::g_handle_table.Create(object).Unwrap(); +            dst_cmdbuf[current_offset++] = handle_table.Create(object).Unwrap();          }          for (auto& object : move_objects) {              ASSERT(object != nullptr); -            dst_cmdbuf[current_offset++] = Kernel::g_handle_table.Create(object).Unwrap(); +            dst_cmdbuf[current_offset++] = handle_table.Create(object).Unwrap();          }      } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 8c19e86d3..615d7901a 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -2,38 +2,291 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <array> +#include <atomic> +#include <memory> +#include <mutex> +#include <utility> + +#include "common/assert.h" +#include "common/logging/log.h" + +#include "core/core.h" +#include "core/core_timing.h"  #include "core/hle/kernel/handle_table.h"  #include "core/hle/kernel/kernel.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/resource_limit.h"  #include "core/hle/kernel/thread.h"  #include "core/hle/kernel/timer.h" +#include "core/hle/lock.h" +#include "core/hle/result.h"  namespace Kernel { -std::atomic<u32> Object::next_object_id{0}; +/** + * Callback that will wake up the thread it was scheduled for + * @param thread_handle The handle 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, [[maybe_unused]] int cycles_late) { +    const auto proper_handle = static_cast<Handle>(thread_handle); +    auto& system = Core::System::GetInstance(); + +    // Lock the global kernel mutex when we enter the kernel HLE. +    std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); + +    SharedPtr<Thread> thread = +        system.Kernel().RetrieveThreadFromWakeupCallbackHandleTable(proper_handle); +    if (thread == nullptr) { +        LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); +        return; +    } + +    bool resume = true; + +    if (thread->status == ThreadStatus::WaitSynchAny || +        thread->status == ThreadStatus::WaitSynchAll || +        thread->status == ThreadStatus::WaitHLEEvent) { +        // Remove the thread from each of its waiting objects' waitlists +        for (auto& object : thread->wait_objects) { +            object->RemoveWaitingThread(thread.get()); +        } +        thread->wait_objects.clear(); + +        // Invoke the wakeup callback before clearing the wait objects +        if (thread->wakeup_callback) { +            resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0); +        } +    } + +    if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 || +        thread->wait_handle) { +        ASSERT(thread->status == ThreadStatus::WaitMutex); +        thread->mutex_wait_address = 0; +        thread->condvar_wait_address = 0; +        thread->wait_handle = 0; + +        auto lock_owner = thread->lock_owner; +        // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance +        // and don't have a lock owner unless SignalProcessWideKey was called first and the thread +        // wasn't awakened due to the mutex already being acquired. +        if (lock_owner) { +            lock_owner->RemoveMutexWaiter(thread); +        } +    } + +    if (thread->arb_wait_address != 0) { +        ASSERT(thread->status == ThreadStatus::WaitArb); +        thread->arb_wait_address = 0; +    } + +    if (resume) { +        thread->ResumeFromWait(); +    } +} + +/// The timer callback event, called when a timer is fired +static void TimerCallback(u64 timer_handle, int cycles_late) { +    const auto proper_handle = static_cast<Handle>(timer_handle); +    auto& system = Core::System::GetInstance(); +    SharedPtr<Timer> timer = system.Kernel().RetrieveTimerFromCallbackHandleTable(proper_handle); + +    if (timer == nullptr) { +        LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016X}", timer_handle); +        return; +    } + +    timer->Signal(cycles_late); +} -/// Initialize the kernel -void Init() { -    Kernel::ResourceLimitsInit(); -    Kernel::ThreadingInit(); -    Kernel::TimersInit(); +struct KernelCore::Impl { +    void Initialize(KernelCore& kernel) { +        Shutdown(); -    Object::next_object_id = 0; +        InitializeResourceLimits(kernel); +        InitializeThreads(); +        InitializeTimers(); +    } + +    void Shutdown() { +        next_object_id = 0; +        next_process_id = 10; +        next_thread_id = 1; + +        process_list.clear(); + +        handle_table.Clear(); +        resource_limits.fill(nullptr); + +        thread_wakeup_callback_handle_table.Clear(); +        thread_wakeup_event_type = nullptr; + +        timer_callback_handle_table.Clear(); +        timer_callback_event_type = nullptr; +    } + +    void InitializeResourceLimits(KernelCore& kernel) { +        // Create the four resource limits that the system uses +        // Create the APPLICATION resource limit +        SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create(kernel, "Applications"); +        resource_limit->max_priority = 0x18; +        resource_limit->max_commit = 0x4000000; +        resource_limit->max_threads = 0x20; +        resource_limit->max_events = 0x20; +        resource_limit->max_mutexes = 0x20; +        resource_limit->max_semaphores = 0x8; +        resource_limit->max_timers = 0x8; +        resource_limit->max_shared_mems = 0x10; +        resource_limit->max_address_arbiters = 0x2; +        resource_limit->max_cpu_time = 0x1E; +        resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit; + +        // Create the SYS_APPLET resource limit +        resource_limit = ResourceLimit::Create(kernel, "System Applets"); +        resource_limit->max_priority = 0x4; +        resource_limit->max_commit = 0x5E00000; +        resource_limit->max_threads = 0x1D; +        resource_limit->max_events = 0xB; +        resource_limit->max_mutexes = 0x8; +        resource_limit->max_semaphores = 0x4; +        resource_limit->max_timers = 0x4; +        resource_limit->max_shared_mems = 0x8; +        resource_limit->max_address_arbiters = 0x3; +        resource_limit->max_cpu_time = 0x2710; +        resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit; + +        // Create the LIB_APPLET resource limit +        resource_limit = ResourceLimit::Create(kernel, "Library Applets"); +        resource_limit->max_priority = 0x4; +        resource_limit->max_commit = 0x600000; +        resource_limit->max_threads = 0xE; +        resource_limit->max_events = 0x8; +        resource_limit->max_mutexes = 0x8; +        resource_limit->max_semaphores = 0x4; +        resource_limit->max_timers = 0x4; +        resource_limit->max_shared_mems = 0x8; +        resource_limit->max_address_arbiters = 0x1; +        resource_limit->max_cpu_time = 0x2710; +        resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit; + +        // Create the OTHER resource limit +        resource_limit = ResourceLimit::Create(kernel, "Others"); +        resource_limit->max_priority = 0x4; +        resource_limit->max_commit = 0x2180000; +        resource_limit->max_threads = 0xE1; +        resource_limit->max_events = 0x108; +        resource_limit->max_mutexes = 0x25; +        resource_limit->max_semaphores = 0x43; +        resource_limit->max_timers = 0x2C; +        resource_limit->max_shared_mems = 0x1F; +        resource_limit->max_address_arbiters = 0x2D; +        resource_limit->max_cpu_time = 0x3E8; +        resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit; +    } + +    void InitializeThreads() { +        thread_wakeup_event_type = +            CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); +    } + +    void InitializeTimers() { +        timer_callback_handle_table.Clear(); +        timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback); +    } + +    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 -    Process::next_process_id = 10; +    std::atomic<u32> next_process_id{10}; +    std::atomic<u32> next_thread_id{1}; + +    // Lists all processes that exist in the current session. +    std::vector<SharedPtr<Process>> process_list; + +    Kernel::HandleTable handle_table; +    std::array<SharedPtr<ResourceLimit>, 4> resource_limits; + +    /// The event type of the generic timer callback event +    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. +    Kernel::HandleTable timer_callback_handle_table; + +    CoreTiming::EventType* thread_wakeup_event_type = nullptr; +    // 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. +    Kernel::HandleTable thread_wakeup_callback_handle_table; +}; + +KernelCore::KernelCore() : impl{std::make_unique<Impl>()} {} +KernelCore::~KernelCore() { +    Shutdown(); +} + +void KernelCore::Initialize() { +    impl->Initialize(*this); +} + +void KernelCore::Shutdown() { +    impl->Shutdown(); +} + +Kernel::HandleTable& KernelCore::HandleTable() { +    return impl->handle_table; +} + +const Kernel::HandleTable& KernelCore::HandleTable() const { +    return impl->handle_table; +} + +SharedPtr<ResourceLimit> KernelCore::ResourceLimitForCategory( +    ResourceLimitCategory category) const { +    return impl->resource_limits.at(static_cast<std::size_t>(category)); +} + +SharedPtr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const { +    return impl->thread_wakeup_callback_handle_table.Get<Thread>(handle); +} + +SharedPtr<Timer> KernelCore::RetrieveTimerFromCallbackHandleTable(Handle handle) const { +    return impl->timer_callback_handle_table.Get<Timer>(handle); +} + +void KernelCore::AppendNewProcess(SharedPtr<Process> process) { +    impl->process_list.push_back(std::move(process)); +} + +u32 KernelCore::CreateNewObjectID() { +    return impl->next_object_id++; +} + +u32 KernelCore::CreateNewThreadID() { +    return impl->next_thread_id++;  } -/// Shutdown the kernel -void Shutdown() { -    // Free all kernel objects -    g_handle_table.Clear(); +u32 KernelCore::CreateNewProcessID() { +    return impl->next_process_id++; +} -    Kernel::ThreadingShutdown(); +ResultVal<Handle> KernelCore::CreateTimerCallbackHandle(const SharedPtr<Timer>& timer) { +    return impl->timer_callback_handle_table.Create(timer); +} + +CoreTiming::EventType* KernelCore::ThreadWakeupCallbackEventType() const { +    return impl->thread_wakeup_event_type; +} + +CoreTiming::EventType* KernelCore::TimerCallbackEventType() const { +    return impl->timer_callback_event_type; +} + +Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() { +    return impl->thread_wakeup_callback_handle_table; +} -    Kernel::TimersShutdown(); -    Kernel::ResourceLimitsShutdown(); +const Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() const { +    return impl->thread_wakeup_callback_handle_table;  }  } // namespace Kernel diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 131311472..089e959ac 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -4,14 +4,93 @@  #pragma once -#include "common/common_types.h" +#include "core/hle/kernel/object.h" + +template <typename T> +class ResultVal; + +namespace CoreTiming { +struct EventType; +}  namespace Kernel { -/// Initialize the kernel with the specified system mode. -void Init(); +class HandleTable; +class Process; +class ResourceLimit; +class Thread; +class Timer; + +enum class ResourceLimitCategory : u8; + +/// Represents a single instance of the kernel. +class KernelCore { +public: +    KernelCore(); +    ~KernelCore(); + +    KernelCore(const KernelCore&) = delete; +    KernelCore& operator=(const KernelCore&) = delete; + +    KernelCore(KernelCore&&) = delete; +    KernelCore& operator=(KernelCore&&) = delete; + +    /// Resets the kernel to a clean slate for use. +    void Initialize(); + +    /// Clears all resources in use by the kernel instance. +    void Shutdown(); + +    /// Provides a reference to the handle table. +    Kernel::HandleTable& HandleTable(); + +    /// Provides a const reference to the handle table. +    const Kernel::HandleTable& HandleTable() const; + +    /// Retrieves a shared pointer to a ResourceLimit identified by the given category. +    SharedPtr<ResourceLimit> ResourceLimitForCategory(ResourceLimitCategory category) const; + +    /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. +    SharedPtr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const; + +    /// Retrieves a shared pointer to a Timer instance within the timer callback handle table. +    SharedPtr<Timer> RetrieveTimerFromCallbackHandleTable(Handle handle) const; + +    /// Adds the given shared pointer to an internal list of active processes. +    void AppendNewProcess(SharedPtr<Process> process); + +private: +    friend class Object; +    friend class Process; +    friend class Thread; +    friend class Timer; + +    /// Creates a new object ID, incrementing the internal object ID counter. +    u32 CreateNewObjectID(); + +    /// Creates a new process ID, incrementing the internal process ID counter; +    u32 CreateNewProcessID(); + +    /// Creates a new thread ID, incrementing the internal thread ID counter. +    u32 CreateNewThreadID(); + +    /// Creates a timer callback handle for the given timer. +    ResultVal<Handle> CreateTimerCallbackHandle(const SharedPtr<Timer>& timer); + +    /// Retrieves the event type used for thread wakeup callbacks. +    CoreTiming::EventType* ThreadWakeupCallbackEventType() const; + +    /// Retrieves the event type used for timer callbacks. +    CoreTiming::EventType* TimerCallbackEventType() const; + +    /// Provides a reference to the thread wakeup callback handle table. +    Kernel::HandleTable& ThreadWakeupCallbackHandleTable(); + +    /// Provides a const reference to the thread wakeup callback handle table. +    const Kernel::HandleTable& ThreadWakeupCallbackHandleTable() const; -/// Shutdown the kernel -void Shutdown(); +    struct Impl; +    std::unique_ptr<Impl> impl; +};  } // namespace Kernel diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index cb7f58b35..36bf0b677 100644 --- a/src/core/hle/kernel/mutex.cpp +++ b/src/core/hle/kernel/mutex.cpp @@ -58,15 +58,15 @@ static void TransferMutexOwnership(VAddr mutex_addr, SharedPtr<Thread> current_t      }  } -ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle, +ResultCode Mutex::TryAcquire(HandleTable& handle_table, VAddr address, Handle holding_thread_handle,                               Handle requesting_thread_handle) {      // The mutex address must be 4-byte aligned      if ((address % sizeof(u32)) != 0) {          return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress);      } -    SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle); -    SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle); +    SharedPtr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle); +    SharedPtr<Thread> requesting_thread = handle_table.Get<Thread>(requesting_thread_handle);      // TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another      // thread. diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h index 45268bbe9..81e62d497 100644 --- a/src/core/hle/kernel/mutex.h +++ b/src/core/hle/kernel/mutex.h @@ -11,6 +11,7 @@ union ResultCode;  namespace Kernel { +class HandleTable;  class Thread;  class Mutex final { @@ -21,8 +22,8 @@ public:      static constexpr u32 MutexOwnerMask = 0xBFFFFFFF;      /// Attempts to acquire a mutex at the specified address. -    static ResultCode TryAcquire(VAddr address, Handle holding_thread_handle, -                                 Handle requesting_thread_handle); +    static ResultCode TryAcquire(HandleTable& handle_table, VAddr address, +                                 Handle holding_thread_handle, Handle requesting_thread_handle);      /// Releases the mutex at the specified address.      static ResultCode Release(VAddr address); diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp index cdba272f5..d51562d92 100644 --- a/src/core/hle/kernel/object.cpp +++ b/src/core/hle/kernel/object.cpp @@ -3,10 +3,12 @@  // Refer to the license.txt file included.  #include "common/assert.h" +#include "core/hle/kernel/kernel.h"  #include "core/hle/kernel/object.h"  namespace Kernel { +Object::Object(KernelCore& kernel) : kernel{kernel}, object_id{kernel.CreateNewObjectID()} {}  Object::~Object() = default;  bool Object::IsWaitable() const { diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h index 526ac9cc3..b054cbf7d 100644 --- a/src/core/hle/kernel/object.h +++ b/src/core/hle/kernel/object.h @@ -14,6 +14,8 @@  namespace Kernel { +class KernelCore; +  using Handle = u32;  enum class HandleType : u32 { @@ -40,6 +42,7 @@ enum class ResetType {  class Object : NonCopyable {  public: +    explicit Object(KernelCore& kernel);      virtual ~Object();      /// Returns a unique identifier for the object. For debugging purposes only. @@ -61,15 +64,16 @@ public:       */      bool IsWaitable() const; -public: -    static std::atomic<u32> next_object_id; +protected: +    /// The kernel instance this object was created under. +    KernelCore& kernel;  private:      friend void intrusive_ptr_add_ref(Object*);      friend void intrusive_ptr_release(Object*);      std::atomic<u32> ref_count{0}; -    std::atomic<u32> object_id{next_object_id++}; +    std::atomic<u32> object_id{0};  };  // Special functions used by boost::instrusive_ptr to do automatic ref-counting diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index edf34c5a3..b025e323f 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -8,6 +8,7 @@  #include "common/common_funcs.h"  #include "common/logging/log.h"  #include "core/hle/kernel/errors.h" +#include "core/hle/kernel/kernel.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/resource_limit.h"  #include "core/hle/kernel/thread.h" @@ -16,30 +17,26 @@  namespace Kernel { -// Lists all processes that exist in the current session. -static std::vector<SharedPtr<Process>> process_list; - -SharedPtr<CodeSet> CodeSet::Create(std::string name) { -    SharedPtr<CodeSet> codeset(new CodeSet); +SharedPtr<CodeSet> CodeSet::Create(KernelCore& kernel, std::string name) { +    SharedPtr<CodeSet> codeset(new CodeSet(kernel));      codeset->name = std::move(name);      return codeset;  } -CodeSet::CodeSet() {} -CodeSet::~CodeSet() {} - -u32 Process::next_process_id; +CodeSet::CodeSet(KernelCore& kernel) : Object{kernel} {} +CodeSet::~CodeSet() = default; -SharedPtr<Process> Process::Create(std::string&& name) { -    SharedPtr<Process> process(new Process); +SharedPtr<Process> Process::Create(KernelCore& kernel, std::string&& name) { +    SharedPtr<Process> process(new Process(kernel));      process->name = std::move(name);      process->flags.raw = 0;      process->flags.memory_region.Assign(MemoryRegion::APPLICATION);      process->status = ProcessStatus::Created;      process->program_id = 0; +    process->process_id = kernel.CreateNewProcessID(); -    process_list.push_back(process); +    kernel.AppendNewProcess(process);      return process;  } @@ -128,7 +125,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {      vm_manager.LogLayout();      status = ProcessStatus::Running; -    Kernel::SetupMainThread(entry_point, main_thread_priority, this); +    Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, this);  }  void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { @@ -231,22 +228,7 @@ ResultCode Process::UnmapMemory(VAddr dst_addr, VAddr /*src_addr*/, u64 size) {      return vm_manager.UnmapRange(dst_addr, size);  } -Kernel::Process::Process() {} +Kernel::Process::Process(KernelCore& kernel) : Object{kernel} {}  Kernel::Process::~Process() {} -void ClearProcessList() { -    process_list.clear(); -} - -SharedPtr<Process> GetProcessById(u32 process_id) { -    auto itr = std::find_if( -        process_list.begin(), process_list.end(), -        [&](const SharedPtr<Process>& process) { return process->process_id == process_id; }); - -    if (itr == process_list.end()) -        return nullptr; - -    return *itr; -} -  } // namespace Kernel diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 992689186..1587d40c1 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h @@ -19,6 +19,8 @@  namespace Kernel { +class KernelCore; +  struct AddressMapping {      // Address and size must be page-aligned      VAddr address; @@ -62,7 +64,7 @@ struct CodeSet final : public Object {          u32 size = 0;      }; -    static SharedPtr<CodeSet> Create(std::string name); +    static SharedPtr<CodeSet> Create(KernelCore& kernel, std::string name);      std::string GetTypeName() const override {          return "CodeSet"; @@ -109,13 +111,13 @@ struct CodeSet final : public Object {      std::string name;  private: -    CodeSet(); +    explicit CodeSet(KernelCore& kernel);      ~CodeSet() override;  };  class Process final : public Object {  public: -    static SharedPtr<Process> Create(std::string&& name); +    static SharedPtr<Process> Create(KernelCore& kernel, std::string&& name);      std::string GetTypeName() const override {          return "Process"; @@ -129,8 +131,6 @@ public:          return HANDLE_TYPE;      } -    static u32 next_process_id; -      /// Title ID corresponding to the process      u64 program_id; @@ -157,8 +157,8 @@ public:      /// Current status of the process      ProcessStatus status; -    /// The id of this process -    u32 process_id = next_process_id++; +    /// The ID of this process +    u32 process_id = 0;      /**       * Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them @@ -206,13 +206,8 @@ public:      ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size);  private: -    Process(); +    explicit Process(KernelCore& kernel);      ~Process() override;  }; -void ClearProcessList(); - -/// Retrieves a process from the current list of processes. -SharedPtr<Process> GetProcessById(u32 process_id); -  } // namespace Kernel diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp index 17a3e8a74..b253a680f 100644 --- a/src/core/hle/kernel/resource_limit.cpp +++ b/src/core/hle/kernel/resource_limit.cpp @@ -9,31 +9,16 @@  namespace Kernel { -static SharedPtr<ResourceLimit> resource_limits[4]; +ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {} +ResourceLimit::~ResourceLimit() = default; -ResourceLimit::ResourceLimit() {} -ResourceLimit::~ResourceLimit() {} - -SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) { -    SharedPtr<ResourceLimit> resource_limit(new ResourceLimit); +SharedPtr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel, std::string name) { +    SharedPtr<ResourceLimit> resource_limit(new ResourceLimit(kernel));      resource_limit->name = std::move(name);      return resource_limit;  } -SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) { -    switch (category) { -    case ResourceLimitCategory::APPLICATION: -    case ResourceLimitCategory::SYS_APPLET: -    case ResourceLimitCategory::LIB_APPLET: -    case ResourceLimitCategory::OTHER: -        return resource_limits[static_cast<u8>(category)]; -    default: -        LOG_CRITICAL(Kernel, "Unknown resource limit category"); -        UNREACHABLE(); -    } -} -  s32 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {      switch (resource) {      case ResourceType::Commit: @@ -89,66 +74,4 @@ u32 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {          return 0;      }  } - -void ResourceLimitsInit() { -    // Create the four resource limits that the system uses -    // Create the APPLICATION resource limit -    SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create("Applications"); -    resource_limit->max_priority = 0x18; -    resource_limit->max_commit = 0x4000000; -    resource_limit->max_threads = 0x20; -    resource_limit->max_events = 0x20; -    resource_limit->max_mutexes = 0x20; -    resource_limit->max_semaphores = 0x8; -    resource_limit->max_timers = 0x8; -    resource_limit->max_shared_mems = 0x10; -    resource_limit->max_address_arbiters = 0x2; -    resource_limit->max_cpu_time = 0x1E; -    resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit; - -    // Create the SYS_APPLET resource limit -    resource_limit = ResourceLimit::Create("System Applets"); -    resource_limit->max_priority = 0x4; -    resource_limit->max_commit = 0x5E00000; -    resource_limit->max_threads = 0x1D; -    resource_limit->max_events = 0xB; -    resource_limit->max_mutexes = 0x8; -    resource_limit->max_semaphores = 0x4; -    resource_limit->max_timers = 0x4; -    resource_limit->max_shared_mems = 0x8; -    resource_limit->max_address_arbiters = 0x3; -    resource_limit->max_cpu_time = 0x2710; -    resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit; - -    // Create the LIB_APPLET resource limit -    resource_limit = ResourceLimit::Create("Library Applets"); -    resource_limit->max_priority = 0x4; -    resource_limit->max_commit = 0x600000; -    resource_limit->max_threads = 0xE; -    resource_limit->max_events = 0x8; -    resource_limit->max_mutexes = 0x8; -    resource_limit->max_semaphores = 0x4; -    resource_limit->max_timers = 0x4; -    resource_limit->max_shared_mems = 0x8; -    resource_limit->max_address_arbiters = 0x1; -    resource_limit->max_cpu_time = 0x2710; -    resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit; - -    // Create the OTHER resource limit -    resource_limit = ResourceLimit::Create("Others"); -    resource_limit->max_priority = 0x4; -    resource_limit->max_commit = 0x2180000; -    resource_limit->max_threads = 0xE1; -    resource_limit->max_events = 0x108; -    resource_limit->max_mutexes = 0x25; -    resource_limit->max_semaphores = 0x43; -    resource_limit->max_timers = 0x2C; -    resource_limit->max_shared_mems = 0x1F; -    resource_limit->max_address_arbiters = 0x2D; -    resource_limit->max_cpu_time = 0x3E8; -    resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit; -} - -void ResourceLimitsShutdown() {} -  } // namespace Kernel diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h index 0fa141db3..219e49562 100644 --- a/src/core/hle/kernel/resource_limit.h +++ b/src/core/hle/kernel/resource_limit.h @@ -9,6 +9,8 @@  namespace Kernel { +class KernelCore; +  enum class ResourceLimitCategory : u8 {      APPLICATION = 0,      SYS_APPLET = 1, @@ -34,14 +36,7 @@ public:      /**       * Creates a resource limit object.       */ -    static SharedPtr<ResourceLimit> Create(std::string name = "Unknown"); - -    /** -     * Retrieves the resource limit associated with the specified resource limit category. -     * @param category The resource limit category -     * @returns The resource limit associated with the category -     */ -    static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category); +    static SharedPtr<ResourceLimit> Create(KernelCore& kernel, std::string name = "Unknown");      std::string GetTypeName() const override {          return "ResourceLimit"; @@ -113,14 +108,8 @@ public:      s32 current_cpu_time = 0;  private: -    ResourceLimit(); +    explicit ResourceLimit(KernelCore& kernel);      ~ResourceLimit() override;  }; -/// Initializes the resource limits -void ResourceLimitsInit(); - -// Destroys the resource limits -void ResourceLimitsShutdown(); -  } // namespace Kernel diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp index 7b6211fd8..3792e3e18 100644 --- a/src/core/hle/kernel/server_port.cpp +++ b/src/core/hle/kernel/server_port.cpp @@ -13,8 +13,8 @@  namespace Kernel { -ServerPort::ServerPort() {} -ServerPort::~ServerPort() {} +ServerPort::ServerPort(KernelCore& kernel) : WaitObject{kernel} {} +ServerPort::~ServerPort() = default;  ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() {      if (pending_sessions.empty()) { @@ -36,10 +36,10 @@ void ServerPort::Acquire(Thread* thread) {  }  std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair( -    u32 max_sessions, std::string name) { +    KernelCore& kernel, u32 max_sessions, std::string name) { -    SharedPtr<ServerPort> server_port(new ServerPort); -    SharedPtr<ClientPort> client_port(new ClientPort); +    SharedPtr<ServerPort> server_port(new ServerPort(kernel)); +    SharedPtr<ClientPort> client_port(new ClientPort(kernel));      server_port->name = name + "_Server";      client_port->name = name + "_Client"; diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h index 7f6d6b3eb..62fb51349 100644 --- a/src/core/hle/kernel/server_port.h +++ b/src/core/hle/kernel/server_port.h @@ -15,6 +15,7 @@  namespace Kernel {  class ClientPort; +class KernelCore;  class ServerSession;  class SessionRequestHandler; @@ -23,12 +24,13 @@ public:      /**       * Creates a pair of ServerPort and an associated ClientPort.       * +     * @param kernel The kernel instance to create the port pair under.       * @param max_sessions Maximum number of sessions to the port       * @param name Optional name of the ports       * @return The created port tuple       */      static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair( -        u32 max_sessions, std::string name = "UnknownPort"); +        KernelCore& kernel, u32 max_sessions, std::string name = "UnknownPort");      std::string GetTypeName() const override {          return "ServerPort"; @@ -69,7 +71,7 @@ public:      void Acquire(Thread* thread) override;  private: -    ServerPort(); +    explicit ServerPort(KernelCore& kernel);      ~ServerPort() override;  }; diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp index 51a1ec160..90c9a5aff 100644 --- a/src/core/hle/kernel/server_session.cpp +++ b/src/core/hle/kernel/server_session.cpp @@ -20,7 +20,7 @@  namespace Kernel { -ServerSession::ServerSession() = default; +ServerSession::ServerSession(KernelCore& kernel) : WaitObject{kernel} {}  ServerSession::~ServerSession() {      // This destructor will be called automatically when the last ServerSession handle is closed by      // the emulated application. @@ -35,8 +35,8 @@ ServerSession::~ServerSession() {      parent->server = nullptr;  } -ResultVal<SharedPtr<ServerSession>> ServerSession::Create(std::string name) { -    SharedPtr<ServerSession> server_session(new ServerSession); +ResultVal<SharedPtr<ServerSession>> ServerSession::Create(KernelCore& kernel, std::string name) { +    SharedPtr<ServerSession> server_session(new ServerSession(kernel));      server_session->name = std::move(name);      server_session->parent = nullptr; @@ -105,10 +105,10 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {      // from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or      // similar. +    auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();      Kernel::HLERequestContext context(this);      u32* cmd_buf = (u32*)Memory::GetPointer(thread->GetTLSAddress()); -    context.PopulateFromIncomingCommandBuffer(cmd_buf, *Core::CurrentProcess(), -                                              Kernel::g_handle_table); +    context.PopulateFromIncomingCommandBuffer(cmd_buf, *Core::CurrentProcess(), handle_table);      ResultCode result = RESULT_SUCCESS;      // If the session has been converted to a domain, handle the domain request @@ -160,10 +160,11 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {      return result;  } -ServerSession::SessionPair ServerSession::CreateSessionPair(const std::string& name, +ServerSession::SessionPair ServerSession::CreateSessionPair(KernelCore& kernel, +                                                            const std::string& name,                                                              SharedPtr<ClientPort> port) { -    auto server_session = ServerSession::Create(name + "_Server").Unwrap(); -    SharedPtr<ClientSession> client_session(new ClientSession); +    auto server_session = ServerSession::Create(kernel, name + "_Server").Unwrap(); +    SharedPtr<ClientSession> client_session(new ClientSession(kernel));      client_session->name = name + "_Client";      std::shared_ptr<Session> parent(new Session); diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 1a88e66b9..e068db2bf 100644 --- a/src/core/hle/kernel/server_session.h +++ b/src/core/hle/kernel/server_session.h @@ -15,13 +15,14 @@  namespace Kernel { -class ClientSession;  class ClientPort; +class ClientSession; +class HLERequestContext; +class KernelCore;  class ServerSession;  class Session;  class SessionRequestHandler;  class Thread; -class HLERequestContext;  /**   * Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS @@ -50,11 +51,12 @@ public:      /**       * Creates a pair of ServerSession and an associated ClientSession. +     * @param kernel      The kernal instance to create the session pair under.       * @param name        Optional name of the ports.       * @param client_port Optional The ClientPort that spawned this session.       * @return The created session tuple       */ -    static SessionPair CreateSessionPair(const std::string& name = "Unknown", +    static SessionPair CreateSessionPair(KernelCore& kernel, const std::string& name = "Unknown",                                           SharedPtr<ClientPort> client_port = nullptr);      /** @@ -111,16 +113,18 @@ public:      }  private: -    ServerSession(); +    explicit ServerSession(KernelCore& kernel);      ~ServerSession() override;      /**       * Creates a server session. The server session can have an optional HLE handler,       * which will be invoked to handle the IPC requests that this session receives. +     * @param kernel The kernel instance to create this server session under.       * @param name Optional name of the server session.       * @return The created server session       */ -    static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown"); +    static ResultVal<SharedPtr<ServerSession>> Create(KernelCore& kernel, +                                                      std::string name = "Unknown");      /// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an      /// object handle. diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index fc168d2b5..abb1d09cd 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -13,14 +13,14 @@  namespace Kernel { -SharedMemory::SharedMemory() {} -SharedMemory::~SharedMemory() {} +SharedMemory::SharedMemory(KernelCore& kernel) : Object{kernel} {} +SharedMemory::~SharedMemory() = default; -SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u64 size, -                                             MemoryPermission permissions, +SharedPtr<SharedMemory> SharedMemory::Create(KernelCore& kernel, SharedPtr<Process> owner_process, +                                             u64 size, MemoryPermission permissions,                                               MemoryPermission other_permissions, VAddr address,                                               MemoryRegion region, std::string name) { -    SharedPtr<SharedMemory> shared_memory(new SharedMemory); +    SharedPtr<SharedMemory> shared_memory(new SharedMemory(kernel));      shared_memory->owner_process = std::move(owner_process);      shared_memory->name = std::move(name); @@ -59,12 +59,10 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u      return shared_memory;  } -SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, -                                                      u32 offset, u32 size, -                                                      MemoryPermission permissions, -                                                      MemoryPermission other_permissions, -                                                      std::string name) { -    SharedPtr<SharedMemory> shared_memory(new SharedMemory); +SharedPtr<SharedMemory> SharedMemory::CreateForApplet( +    KernelCore& kernel, std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size, +    MemoryPermission permissions, MemoryPermission other_permissions, std::string name) { +    SharedPtr<SharedMemory> shared_memory(new SharedMemory(kernel));      shared_memory->owner_process = nullptr;      shared_memory->name = std::move(name); diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h index c50fee615..2c729afe3 100644 --- a/src/core/hle/kernel/shared_memory.h +++ b/src/core/hle/kernel/shared_memory.h @@ -15,6 +15,8 @@  namespace Kernel { +class KernelCore; +  /// Permissions for mapped shared memory blocks  enum class MemoryPermission : u32 {      None = 0, @@ -32,6 +34,7 @@ class SharedMemory final : public Object {  public:      /**       * Creates a shared memory object. +     * @param kernel The kernel instance to create a shared memory instance under.       * @param owner_process Process that created this shared memory object.       * @param size Size of the memory block. Must be page-aligned.       * @param permissions Permission restrictions applied to the process which created the block. @@ -42,14 +45,15 @@ public:       * linear heap.       * @param name Optional object name, used for debugging purposes.       */ -    static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u64 size, -                                          MemoryPermission permissions, +    static SharedPtr<SharedMemory> Create(KernelCore& kernel, SharedPtr<Process> owner_process, +                                          u64 size, MemoryPermission permissions,                                            MemoryPermission other_permissions, VAddr address = 0,                                            MemoryRegion region = MemoryRegion::BASE,                                            std::string name = "Unknown");      /**       * Creates a shared memory object from a block of memory managed by an HLE applet. +     * @param kernel The kernel instance to create a shared memory instance under.       * @param heap_block Heap block of the HLE applet.       * @param offset The offset into the heap block that the SharedMemory will map.       * @param size Size of the memory block. Must be page-aligned. @@ -58,7 +62,8 @@ public:       * block.       * @param name Optional object name, used for debugging purposes.       */ -    static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block, +    static SharedPtr<SharedMemory> CreateForApplet(KernelCore& kernel, +                                                   std::shared_ptr<std::vector<u8>> heap_block,                                                     u32 offset, u32 size,                                                     MemoryPermission permissions,                                                     MemoryPermission other_permissions, @@ -125,7 +130,7 @@ public:      std::string name;  private: -    SharedMemory(); +    explicit SharedMemory(KernelCore& kernel);      ~SharedMemory() override;  }; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index cb6253398..099d1053f 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -87,13 +87,15 @@ static ResultCode ConnectToNamedPort(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)); +    auto& kernel = Core::System::GetInstance().Kernel(); +    CASCADE_RESULT(*out_handle, kernel.HandleTable().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); +    auto& kernel = Core::System::GetInstance().Kernel(); +    SharedPtr<ClientSession> session = kernel.HandleTable().Get<ClientSession>(handle);      if (!session) {          LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);          return ERR_INVALID_HANDLE; @@ -112,7 +114,8 @@ static ResultCode SendSyncRequest(Handle handle) {  static ResultCode GetThreadId(u32* thread_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); +    auto& kernel = Core::System::GetInstance().Kernel(); +    const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);      if (!thread) {          return ERR_INVALID_HANDLE;      } @@ -125,7 +128,8 @@ static ResultCode GetThreadId(u32* thread_id, Handle thread_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); +    auto& kernel = Core::System::GetInstance().Kernel(); +    const SharedPtr<Process> process = kernel.HandleTable().Get<Process>(process_handle);      if (!process) {          return ERR_INVALID_HANDLE;      } @@ -168,10 +172,11 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64      using ObjectPtr = SharedPtr<WaitObject>;      std::vector<ObjectPtr> objects(handle_count); +    auto& kernel = Core::System::GetInstance().Kernel();      for (u64 i = 0; i < handle_count; ++i) {          const Handle handle = Memory::Read32(handles_address + i * sizeof(Handle)); -        const auto object = g_handle_table.Get<WaitObject>(handle); +        const auto object = kernel.HandleTable().Get<WaitObject>(handle);          if (object == nullptr) {              return ERR_INVALID_HANDLE; @@ -219,7 +224,8 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64  static ResultCode CancelSynchronization(Handle thread_handle) {      LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); -    const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); +    auto& kernel = Core::System::GetInstance().Kernel(); +    const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);      if (!thread) {          return ERR_INVALID_HANDLE;      } @@ -239,7 +245,9 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,                "requesting_current_thread_handle=0x{:08X}",                holding_thread_handle, mutex_addr, requesting_thread_handle); -    return Mutex::TryAcquire(mutex_addr, holding_thread_handle, requesting_thread_handle); +    auto& handle_table = Core::System::GetInstance().Kernel().HandleTable(); +    return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle, +                             requesting_thread_handle);  }  /// Unlock a mutex @@ -352,7 +360,8 @@ static ResultCode GetThreadContext(Handle handle, VAddr addr) {  /// Gets the priority for the specified thread  static ResultCode GetThreadPriority(u32* priority, Handle handle) { -    const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle); +    auto& kernel = Core::System::GetInstance().Kernel(); +    const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);      if (!thread)          return ERR_INVALID_HANDLE; @@ -366,7 +375,8 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {          return ERR_OUT_OF_RANGE;      } -    SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle); +    auto& kernel = Core::System::GetInstance().Kernel(); +    SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);      if (!thread)          return ERR_INVALID_HANDLE; @@ -395,7 +405,8 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s                "called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",                shared_memory_handle, addr, size, permissions); -    SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle); +    auto& kernel = Core::System::GetInstance().Kernel(); +    auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);      if (!shared_memory) {          return ERR_INVALID_HANDLE;      } @@ -423,7 +434,8 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64      LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}",                  shared_memory_handle, addr, size); -    SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle); +    auto& kernel = Core::System::GetInstance().Kernel(); +    auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);      return shared_memory->Unmap(Core::CurrentProcess().get(), addr);  } @@ -431,7 +443,9 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64  /// Query process memory  static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_info*/,                                       Handle process_handle, u64 addr) { -    SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle); + +    auto& kernel = Core::System::GetInstance().Kernel(); +    SharedPtr<Process> process = kernel.HandleTable().Get<Process>(process_handle);      if (!process) {          return ERR_INVALID_HANDLE;      } @@ -528,10 +542,11 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V          break;      } +    auto& kernel = Core::System::GetInstance().Kernel();      CASCADE_RESULT(SharedPtr<Thread> thread, -                   Thread::Create(name, entry_point, priority, arg, processor_id, stack_top, +                   Thread::Create(kernel, name, entry_point, priority, arg, processor_id, stack_top,                                    Core::CurrentProcess())); -    CASCADE_RESULT(thread->guest_handle, g_handle_table.Create(thread)); +    CASCADE_RESULT(thread->guest_handle, kernel.HandleTable().Create(thread));      *out_handle = thread->guest_handle;      Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule(); @@ -548,7 +563,8 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V  static ResultCode StartThread(Handle thread_handle) {      LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); -    const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); +    auto& kernel = Core::System::GetInstance().Kernel(); +    const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);      if (!thread) {          return ERR_INVALID_HANDLE;      } @@ -595,7 +611,8 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var          "called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}",          mutex_addr, condition_variable_addr, thread_handle, nano_seconds); -    SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); +    auto& kernel = Core::System::GetInstance().Kernel(); +    SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);      ASSERT(thread);      CASCADE_CODE(Mutex::Release(mutex_addr)); @@ -704,8 +721,9 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target                                                 mutex_val | Mutex::MutexHasWaitersFlag));              // The mutex is already owned by some other thread, make this thread wait on it. +            auto& kernel = Core::System::GetInstance().Kernel();              Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask); -            auto owner = g_handle_table.Get<Thread>(owner_handle); +            auto owner = kernel.HandleTable().Get<Thread>(owner_handle);              ASSERT(owner);              ASSERT(thread->status == ThreadStatus::WaitMutex);              thread->wakeup_callback = nullptr; @@ -783,14 +801,20 @@ static u64 GetSystemTick() {  /// Close a handle  static ResultCode CloseHandle(Handle handle) {      LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); -    return g_handle_table.Close(handle); + +    auto& kernel = Core::System::GetInstance().Kernel(); +    return kernel.HandleTable().Close(handle);  }  /// Reset an event  static ResultCode ResetSignal(Handle handle) {      LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x{:08X}", handle); -    auto event = g_handle_table.Get<Event>(handle); + +    auto& kernel = Core::System::GetInstance().Kernel(); +    auto event = kernel.HandleTable().Get<Event>(handle); +      ASSERT(event != nullptr); +      event->Clear();      return RESULT_SUCCESS;  } @@ -806,7 +830,8 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32  static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) {      LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); -    const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); +    auto& kernel = Core::System::GetInstance().Kernel(); +    const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);      if (!thread) {          return ERR_INVALID_HANDLE;      } @@ -821,7 +846,8 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {      LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:16X}, core=0x{:X}", thread_handle,                mask, core); -    const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle); +    auto& kernel = Core::System::GetInstance().Kernel(); +    const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);      if (!thread) {          return ERR_INVALID_HANDLE;      } @@ -861,19 +887,23 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss                                       u32 remote_permissions) {      LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size,                local_permissions, remote_permissions); -    auto sharedMemHandle = -        SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size, + +    auto& kernel = Core::System::GetInstance().Kernel(); +    auto& handle_table = kernel.HandleTable(); +    auto shared_mem_handle = +        SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size,                               static_cast<MemoryPermission>(local_permissions),                               static_cast<MemoryPermission>(remote_permissions)); -    CASCADE_RESULT(*handle, g_handle_table.Create(sharedMemHandle)); +    CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle));      return RESULT_SUCCESS;  }  static ResultCode ClearEvent(Handle handle) {      LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle); -    SharedPtr<Event> evt = g_handle_table.Get<Event>(handle); +    auto& kernel = Core::System::GetInstance().Kernel(); +    SharedPtr<Event> evt = kernel.HandleTable().Get<Event>(handle);      if (evt == nullptr)          return ERR_INVALID_HANDLE;      evt->Clear(); diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 4ffd8d5cc..520ea0853 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -20,6 +20,7 @@  #include "core/core_timing_util.h"  #include "core/hle/kernel/errors.h"  #include "core/hle/kernel/handle_table.h" +#include "core/hle/kernel/kernel.h"  #include "core/hle/kernel/object.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/thread.h" @@ -29,9 +30,6 @@  namespace Kernel { -/// Event type for the thread wake up event -static CoreTiming::EventType* ThreadWakeupEventType = nullptr; -  bool Thread::ShouldWait(Thread* thread) const {      return status != ThreadStatus::Dead;  } @@ -40,32 +38,17 @@ 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; - -// The first available thread id at startup -static u32 next_thread_id; - -/** - * Creates a new thread ID - * @return The new thread ID - */ -inline static u32 const NewThreadId() { -    return next_thread_id++; -} - -Thread::Thread() {} -Thread::~Thread() {} +Thread::Thread(KernelCore& kernel) : WaitObject{kernel} {} +Thread::~Thread() = default;  void Thread::Stop() {      // Cancel any outstanding wakeup events for this thread -    CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle); -    wakeup_callback_handle_table.Close(callback_handle); +    CoreTiming::UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), callback_handle); +    kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle);      callback_handle = 0;      // Clean up thread from ready queue -    // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) +    // This is only needed when the thread is terminated forcefully (SVC TerminateProcess)      if (status == ThreadStatus::Ready) {          scheduler->UnscheduleThread(this, current_priority);      } @@ -98,63 +81,6 @@ void ExitCurrentThread() {      Core::System::GetInstance().CurrentScheduler().RemoveThread(thread);  } -/** - * Callback that will wake up the thread it was scheduled for - * @param thread_handle The handle 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, int cycles_late) { -    const auto proper_handle = static_cast<Handle>(thread_handle); - -    // Lock the global kernel mutex when we enter the kernel HLE. -    std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock); - -    SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>(proper_handle); -    if (thread == nullptr) { -        LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle); -        return; -    } - -    bool resume = true; - -    if (thread->status == ThreadStatus::WaitSynchAny || -        thread->status == ThreadStatus::WaitSynchAll || -        thread->status == ThreadStatus::WaitHLEEvent) { -        // Remove the thread from each of its waiting objects' waitlists -        for (auto& object : thread->wait_objects) -            object->RemoveWaitingThread(thread.get()); -        thread->wait_objects.clear(); - -        // Invoke the wakeup callback before clearing the wait objects -        if (thread->wakeup_callback) -            resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0); -    } - -    if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 || -        thread->wait_handle) { -        ASSERT(thread->status == ThreadStatus::WaitMutex); -        thread->mutex_wait_address = 0; -        thread->condvar_wait_address = 0; -        thread->wait_handle = 0; - -        auto lock_owner = thread->lock_owner; -        // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance -        // and don't have a lock owner unless SignalProcessWideKey was called first and the thread -        // wasn't awakened due to the mutex already being acquired. -        if (lock_owner) { -            lock_owner->RemoveMutexWaiter(thread); -        } -    } - -    if (thread->arb_wait_address != 0) { -        ASSERT(thread->status == ThreadStatus::WaitArb); -        thread->arb_wait_address = 0; -    } - -    if (resume) -        thread->ResumeFromWait(); -} -  void Thread::WakeAfterDelay(s64 nanoseconds) {      // Don't schedule a wakeup if the thread wants to wait forever      if (nanoseconds == -1) @@ -162,12 +88,12 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {      // This function might be called from any thread so we have to be cautious and use the      // thread-safe version of ScheduleEvent. -    CoreTiming::ScheduleEventThreadsafe(CoreTiming::nsToCycles(nanoseconds), ThreadWakeupEventType, -                                        callback_handle); +    CoreTiming::ScheduleEventThreadsafe(CoreTiming::nsToCycles(nanoseconds), +                                        kernel.ThreadWakeupCallbackEventType(), callback_handle);  }  void Thread::CancelWakeupTimer() { -    CoreTiming::UnscheduleEventThreadsafe(ThreadWakeupEventType, callback_handle); +    CoreTiming::UnscheduleEventThreadsafe(kernel.ThreadWakeupCallbackEventType(), callback_handle);  }  static boost::optional<s32> GetNextProcessorId(u64 mask) { @@ -294,9 +220,9 @@ static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAdd      context.fpscr = 0;  } -ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, u32 priority, -                                            u64 arg, s32 processor_id, VAddr stack_top, -                                            SharedPtr<Process> owner_process) { +ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name, VAddr entry_point, +                                            u32 priority, u64 arg, s32 processor_id, +                                            VAddr stack_top, SharedPtr<Process> owner_process) {      // Check if priority is in ranged. Lowest priority -> highest priority id.      if (priority > THREADPRIO_LOWEST) {          LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority); @@ -316,9 +242,9 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,          return ResultCode(-1);      } -    SharedPtr<Thread> thread(new Thread); +    SharedPtr<Thread> thread(new Thread(kernel)); -    thread->thread_id = NewThreadId(); +    thread->thread_id = kernel.CreateNewThreadID();      thread->status = ThreadStatus::Dormant;      thread->entry_point = entry_point;      thread->stack_top = stack_top; @@ -333,7 +259,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,      thread->condvar_wait_address = 0;      thread->wait_handle = 0;      thread->name = std::move(name); -    thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); +    thread->callback_handle = kernel.ThreadWakeupCallbackHandleTable().Create(thread).Unwrap();      thread->owner_process = owner_process;      thread->scheduler = Core::System::GetInstance().Scheduler(processor_id);      thread->scheduler->AddThread(thread, priority); @@ -383,19 +309,19 @@ void Thread::BoostPriority(u32 priority) {      current_priority = priority;  } -SharedPtr<Thread> SetupMainThread(VAddr entry_point, u32 priority, +SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority,                                    SharedPtr<Process> owner_process) {      // Setup page table so we can write to memory      SetCurrentPageTable(&Core::CurrentProcess()->vm_manager.page_table);      // Initialize new "main" thread -    auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0, +    auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, THREADPROCESSORID_0,                                       Memory::STACK_AREA_VADDR_END, std::move(owner_process));      SharedPtr<Thread> thread = std::move(thread_res).Unwrap();      // Register 1 must be a handle to the main thread -    thread->guest_handle = Kernel::g_handle_table.Create(thread).Unwrap(); +    thread->guest_handle = kernel.HandleTable().Create(thread).Unwrap();      thread->context.cpu_registers[1] = thread->guest_handle; @@ -528,13 +454,4 @@ Thread* GetCurrentThread() {      return Core::System::GetInstance().CurrentScheduler().GetCurrentThread();  } -void ThreadingInit() { -    ThreadWakeupEventType = CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); -    next_thread_id = 1; -} - -void ThreadingShutdown() { -    Kernel::ClearProcessList(); -} -  } // namespace Kernel diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 06edc296d..20f50458b 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -56,6 +56,7 @@ enum class ThreadWakeupReason {  namespace Kernel { +class KernelCore;  class Process;  class Scheduler; @@ -63,6 +64,7 @@ class Thread final : public WaitObject {  public:      /**       * Creates and returns a new thread. The new thread is immediately scheduled +     * @param kernel The kernel instance this thread will be created under.       * @param name The friendly name desired for the thread       * @param entry_point The address at which the thread should start execution       * @param priority The thread's priority @@ -72,8 +74,9 @@ public:       * @param owner_process The parent process for the thread       * @return A shared pointer to the newly created thread       */ -    static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, u32 priority, -                                               u64 arg, s32 processor_id, VAddr stack_top, +    static ResultVal<SharedPtr<Thread>> Create(KernelCore& kernel, std::string name, +                                               VAddr entry_point, u32 priority, u64 arg, +                                               s32 processor_id, VAddr stack_top,                                                 SharedPtr<Process> owner_process);      std::string GetName() const override { @@ -263,7 +266,7 @@ public:      u64 affinity_mask{0x1};  private: -    Thread(); +    explicit Thread(KernelCore& kernel);      ~Thread() override;      std::shared_ptr<std::vector<u8>> tls_memory = std::make_shared<std::vector<u8>>(); @@ -271,12 +274,13 @@ private:  /**   * Sets up the primary application thread + * @param kernel The kernel instance to create the main thread under.   * @param entry_point The address at which the thread should start execution   * @param priority The priority to give the main thread   * @param owner_process The parent process for the main thread   * @return A shared pointer to the main thread   */ -SharedPtr<Thread> SetupMainThread(VAddr entry_point, u32 priority, +SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority,                                    SharedPtr<Process> owner_process);  /** @@ -294,14 +298,4 @@ void WaitCurrentThread_Sleep();   */  void ExitCurrentThread(); -/** - * Initialize threading - */ -void ThreadingInit(); - -/** - * Shutdown threading - */ -void ThreadingShutdown(); -  } // namespace Kernel diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp index 282360745..6957b16e0 100644 --- a/src/core/hle/kernel/timer.cpp +++ b/src/core/hle/kernel/timer.cpp @@ -2,36 +2,31 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. -#include <cinttypes>  #include "common/assert.h"  #include "common/logging/log.h" +#include "core/core.h"  #include "core/core_timing.h"  #include "core/core_timing_util.h"  #include "core/hle/kernel/handle_table.h" +#include "core/hle/kernel/kernel.h"  #include "core/hle/kernel/object.h"  #include "core/hle/kernel/thread.h"  #include "core/hle/kernel/timer.h"  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; +Timer::Timer(KernelCore& kernel) : WaitObject{kernel} {} +Timer::~Timer() = default; -Timer::Timer() {} -Timer::~Timer() {} - -SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) { -    SharedPtr<Timer> timer(new Timer); +SharedPtr<Timer> Timer::Create(KernelCore& kernel, ResetType reset_type, std::string name) { +    SharedPtr<Timer> timer(new Timer(kernel));      timer->reset_type = reset_type;      timer->signaled = false;      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_handle = kernel.CreateTimerCallbackHandle(timer).Unwrap();      return timer;  } @@ -58,13 +53,13 @@ void Timer::Set(s64 initial, s64 interval) {          // Immediately invoke the callback          Signal(0);      } else { -        CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(initial), timer_callback_event_type, +        CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(initial), kernel.TimerCallbackEventType(),                                    callback_handle);      }  }  void Timer::Cancel() { -    CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle); +    CoreTiming::UnscheduleEvent(kernel.TimerCallbackEventType(), callback_handle);  }  void Timer::Clear() { @@ -89,28 +84,8 @@ void Timer::Signal(int cycles_late) {      if (interval_delay != 0) {          // Reschedule the timer with the interval delay          CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(interval_delay) - cycles_late, -                                  timer_callback_event_type, callback_handle); +                                  kernel.TimerCallbackEventType(), callback_handle);      }  } -/// The timer callback event, called when a timer is fired -static void TimerCallback(u64 timer_handle, int cycles_late) { -    SharedPtr<Timer> timer = -        timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle)); - -    if (timer == nullptr) { -        LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016X}", timer_handle); -        return; -    } - -    timer->Signal(cycles_late); -} - -void TimersInit() { -    timer_callback_handle_table.Clear(); -    timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback); -} - -void TimersShutdown() {} -  } // namespace Kernel diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h index 4dddc67e0..12915c1b1 100644 --- a/src/core/hle/kernel/timer.h +++ b/src/core/hle/kernel/timer.h @@ -10,15 +10,19 @@  namespace Kernel { +class KernelCore; +  class Timer final : public WaitObject {  public:      /**       * Creates a timer +     * @param kernel The kernel instance to create the timer callback handle for.       * @param reset_type ResetType describing how to create the timer       * @param name Optional name of timer       * @return The created Timer       */ -    static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown"); +    static SharedPtr<Timer> Create(KernelCore& kernel, ResetType reset_type, +                                   std::string name = "Unknown");      std::string GetTypeName() const override {          return "Timer"; @@ -68,7 +72,7 @@ public:      void Signal(int cycles_late);  private: -    Timer(); +    explicit Timer(KernelCore& kernel);      ~Timer() override;      ResetType reset_type; ///< The ResetType of this timer @@ -83,9 +87,4 @@ private:      Handle callback_handle;  }; -/// Initializes the required variables for timers -void TimersInit(); -/// Tears down the timer variables -void TimersShutdown(); -  } // namespace Kernel diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index 7681cdee7..eef00b729 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -12,6 +12,9 @@  namespace Kernel { +WaitObject::WaitObject(KernelCore& kernel) : Object{kernel} {} +WaitObject::~WaitObject() = default; +  void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {      auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);      if (itr == waiting_threads.end()) diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h index b5fbc647b..0bd97133c 100644 --- a/src/core/hle/kernel/wait_object.h +++ b/src/core/hle/kernel/wait_object.h @@ -11,11 +11,15 @@  namespace Kernel { +class KernelCore;  class Thread;  /// Class that represents a Kernel object that a thread can be waiting on  class WaitObject : public Object {  public: +    explicit WaitObject(KernelCore& kernel); +    ~WaitObject() override; +      /**       * Check if the specified thread should wait until the object is available       * @param thread The thread about which we're deciding. diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 7e3cf6d58..818c03e0f 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -160,8 +160,9 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger      };      RegisterHandlers(functions); +    auto& kernel = Core::System::GetInstance().Kernel();      launchable_event = -        Kernel::Event::Create(Kernel::ResetType::Sticky, "ISelfController:LaunchableEvent"); +        Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "ISelfController:LaunchableEvent");  }  void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { @@ -332,7 +333,8 @@ ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter"      };      RegisterHandlers(functions); -    event = Kernel::Event::Create(Kernel::ResetType::OneShot, "ICommonStateGetter:Event"); +    auto& kernel = Core::System::GetInstance().Kernel(); +    event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ICommonStateGetter:Event");  }  void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) { @@ -505,7 +507,8 @@ public:          };          RegisterHandlers(functions); -        state_changed_event = Kernel::Event::Create(Kernel::ResetType::OneShot, +        auto& kernel = Core::System::GetInstance().Kernel(); +        state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,                                                      "ILibraryAppletAccessor:StateChangedEvent");      } diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp index ce709ccf4..5f370bbdf 100644 --- a/src/core/hle/service/audio/audout_u.cpp +++ b/src/core/hle/service/audio/audout_u.cpp @@ -47,7 +47,9 @@ public:          RegisterHandlers(functions);          // This is the event handle used to check if the audio buffer was released -        buffer_event = Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioOutBufferReleased"); +        auto& kernel = Core::System::GetInstance().Kernel(); +        buffer_event = +            Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioOutBufferReleased");          stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count,                                         "IAudioOut", [=]() { buffer_event->Signal(); }); diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp index 9e75eb3a6..016db7c82 100644 --- a/src/core/hle/service/audio/audren_u.cpp +++ b/src/core/hle/service/audio/audren_u.cpp @@ -35,8 +35,9 @@ public:          };          RegisterHandlers(functions); +        auto& kernel = Core::System::GetInstance().Kernel();          system_event = -            Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent"); +            Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent");          renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event);      } @@ -121,8 +122,9 @@ public:          };          RegisterHandlers(functions); -        buffer_event = -            Kernel::Event::Create(Kernel::ResetType::OneShot, "IAudioOutBufferReleasedEvent"); +        auto& kernel = Core::System::GetInstance().Kernel(); +        buffer_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, +                                             "IAudioOutBufferReleasedEvent");      }  private: diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index c0ba330dc..0d31abe8b 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -4,6 +4,7 @@  #include <atomic>  #include "common/logging/log.h" +#include "core/core.h"  #include "core/core_timing.h"  #include "core/core_timing_util.h"  #include "core/frontend/emu_window.h" @@ -35,9 +36,10 @@ public:          };          RegisterHandlers(functions); +        auto& kernel = Core::System::GetInstance().Kernel();          shared_mem = Kernel::SharedMemory::Create( -            nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read, -            0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); +            kernel, nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, +            Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");          // Register update callbacks          pad_update_event = CoreTiming::RegisterEvent( @@ -402,7 +404,8 @@ public:          RegisterHandlers(functions); -        event = Kernel::Event::Create(Kernel::ResetType::OneShot, "hid:EventHandle"); +        auto& kernel = Core::System::GetInstance().Kernel(); +        event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "hid:EventHandle");      }      ~Hid() = default; diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp index 56b05e9e8..4f7543af5 100644 --- a/src/core/hle/service/nfp/nfp.cpp +++ b/src/core/hle/service/nfp/nfp.cpp @@ -46,11 +46,13 @@ public:          };          RegisterHandlers(functions); -        activate_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:ActivateEvent"); +        auto& kernel = Core::System::GetInstance().Kernel(); +        activate_event = +            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:ActivateEvent");          deactivate_event = -            Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:DeactivateEvent"); -        availability_change_event = -            Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:AvailabilityChangeEvent"); +            Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent"); +        availability_change_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, +                                                          "IUser:AvailabilityChangeEvent");      }  private: diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index cfe8d9178..ed4f5f539 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -2,6 +2,7 @@  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include "core/core.h"  #include "core/hle/ipc_helpers.h"  #include "core/hle/kernel/event.h"  #include "core/hle/service/nifm/nifm.h" @@ -54,8 +55,9 @@ public:          };          RegisterHandlers(functions); -        event1 = Kernel::Event::Create(Kernel::ResetType::OneShot, "IRequest:Event1"); -        event2 = Kernel::Event::Create(Kernel::ResetType::OneShot, "IRequest:Event2"); +        auto& kernel = Core::System::GetInstance().Kernel(); +        event1 = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IRequest:Event1"); +        event2 = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IRequest:Event2");      }  private: diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp index 923a52cc5..51638793d 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/pl_u.cpp @@ -266,8 +266,9 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {          SHARED_FONT_MEM_VADDR, shared_font, 0, SHARED_FONT_MEM_SIZE, Kernel::MemoryState::Shared);      // Create shared font memory object +    auto& kernel = Core::System::GetInstance().Kernel();      shared_font_mem = Kernel::SharedMemory::Create( -        Core::CurrentProcess(), SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite, +        kernel, Core::CurrentProcess(), SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite,          Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,          "PL_U:shared_font_mem"); diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp index 1b497b814..634ab9196 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -4,6 +4,7 @@  #include <cinttypes>  #include "common/logging/log.h" +#include "core/core.h"  #include "core/hle/ipc_helpers.h"  #include "core/hle/kernel/event.h"  #include "core/hle/service/nvdrv/interface.h" @@ -107,7 +108,8 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)      };      RegisterHandlers(functions); -    query_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "NVDRV::query_event"); +    auto& kernel = Core::System::GetInstance().Kernel(); +    query_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "NVDRV::query_event");  }  } // namespace Service::Nvidia diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index ef5713a71..8d8962276 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -6,14 +6,16 @@  #include "common/assert.h"  #include "common/logging/log.h" +#include "core/core.h"  #include "core/hle/service/nvflinger/buffer_queue.h"  namespace Service {  namespace NVFlinger {  BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { +    auto& kernel = Core::System::GetInstance().Kernel();      buffer_wait_event = -        Kernel::Event::Create(Kernel::ResetType::Sticky, "BufferQueue NativeHandle"); +        Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "BufferQueue NativeHandle");  }  void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) { diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index a26a5f812..3996c24fe 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -161,7 +161,8 @@ void NVFlinger::Compose() {  Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {}  Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) { -    vsync_event = Kernel::Event::Create(Kernel::ResetType::Pulse, "Display VSync Event"); +    auto& kernel = Core::System::GetInstance().Kernel(); +    vsync_event = Kernel::Event::Create(kernel, Kernel::ResetType::Pulse, "Display VSync Event");  }  } // namespace Service::NVFlinger diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 11951adaf..8fb907072 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -107,19 +107,24 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager)  void ServiceFrameworkBase::InstallAsNamedPort() {      ASSERT(port == nullptr); + +    auto& kernel = Core::System::GetInstance().Kernel();      SharedPtr<ServerPort> server_port;      SharedPtr<ClientPort> client_port; -    std::tie(server_port, client_port) = ServerPort::CreatePortPair(max_sessions, service_name); +    std::tie(server_port, client_port) = +        ServerPort::CreatePortPair(kernel, max_sessions, service_name);      server_port->SetHleHandler(shared_from_this());      AddNamedPort(service_name, std::move(client_port));  }  Kernel::SharedPtr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort() {      ASSERT(port == nullptr); + +    auto& kernel = Core::System::GetInstance().Kernel();      Kernel::SharedPtr<Kernel::ServerPort> server_port;      Kernel::SharedPtr<Kernel::ClientPort> client_port;      std::tie(server_port, client_port) = -        Kernel::ServerPort::CreatePortPair(max_sessions, service_name); +        Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);      port = MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port)).Unwrap();      port->SetHleHandler(shared_from_this());      return client_port; diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index f22a2a79f..b240d7eed 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -4,6 +4,7 @@  #include <tuple>  #include "common/assert.h" +#include "core/core.h"  #include "core/hle/ipc_helpers.h"  #include "core/hle/kernel/client_port.h"  #include "core/hle/kernel/client_session.h" @@ -47,9 +48,11 @@ ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService      if (registered_services.find(name) != registered_services.end())          return ERR_ALREADY_REGISTERED; +    auto& kernel = Core::System::GetInstance().Kernel();      Kernel::SharedPtr<Kernel::ServerPort> server_port;      Kernel::SharedPtr<Kernel::ClientPort> client_port; -    std::tie(server_port, client_port) = Kernel::ServerPort::CreatePortPair(max_sessions, name); +    std::tie(server_port, client_port) = +        Kernel::ServerPort::CreatePortPair(kernel, max_sessions, name);      registered_services.emplace(std::move(name), std::move(client_port));      return MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port)); diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 4c79d7902..a53fa6e00 100644 --- a/src/core/loader/deconstructed_rom_directory.cpp +++ b/src/core/loader/deconstructed_rom_directory.cpp @@ -6,6 +6,7 @@  #include "common/common_funcs.h"  #include "common/file_util.h"  #include "common/logging/log.h" +#include "core/core.h"  #include "core/file_sys/content_archive.h"  #include "core/file_sys/control_metadata.h"  #include "core/file_sys/romfs_factory.h" @@ -117,10 +118,11 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(          }      } +    auto& kernel = Core::System::GetInstance().Kernel();      process->program_id = metadata.GetTitleID();      process->svc_access_mask.set();      process->resource_limit = -        Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); +        kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);      process->Run(Memory::PROCESS_IMAGE_VADDR, metadata.GetMainThreadPriority(),                   metadata.GetMainThreadStackSize()); diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp index 6420a7f11..3702a8478 100644 --- a/src/core/loader/elf.cpp +++ b/src/core/loader/elf.cpp @@ -9,6 +9,7 @@  #include "common/common_types.h"  #include "common/file_util.h"  #include "common/logging/log.h" +#include "core/core.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/resource_limit.h"  #include "core/loader/elf.h" @@ -300,7 +301,8 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {      std::vector<u8> program_image(total_image_size);      size_t current_image_position = 0; -    SharedPtr<CodeSet> codeset = CodeSet::Create(""); +    auto& kernel = Core::System::GetInstance().Kernel(); +    SharedPtr<CodeSet> codeset = CodeSet::Create(kernel, "");      for (unsigned int i = 0; i < header->e_phnum; ++i) {          Elf32_Phdr* p = &segments[i]; @@ -400,8 +402,9 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {      process->svc_access_mask.set();      // Attach the default resource limit (APPLICATION) to the process +    auto& kernel = Core::System::GetInstance().Kernel();      process->resource_limit = -        Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); +        kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);      process->Run(codeset->entrypoint, 48, Memory::DEFAULT_STACK_SIZE); diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 2179cf2ea..00205d1d2 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp @@ -136,7 +136,8 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) {      }      // Build program image -    Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create(""); +    auto& kernel = Core::System::GetInstance().Kernel(); +    Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create(kernel, "");      std::vector<u8> program_image = file->ReadBytes(PageAlignSize(nro_header.file_size));      if (program_image.size() != PageAlignSize(nro_header.file_size)) {          return {}; @@ -185,9 +186,10 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {          return ResultStatus::ErrorLoadingNRO;      } +    auto& kernel = Core::System::GetInstance().Kernel();      process->svc_access_mask.set();      process->resource_limit = -        Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); +        kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);      process->Run(base_addr, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);      is_loaded = true; diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index a94558ac5..0c992d662 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -100,7 +100,8 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base) {          return {};      // Build program image -    Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create(""); +    auto& kernel = Core::System::GetInstance().Kernel(); +    Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create(kernel, "");      std::vector<u8> program_image;      for (std::size_t i = 0; i < nso_header.segments.size(); ++i) {          const std::vector<u8> compressed_data = @@ -151,9 +152,10 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) {      LoadModule(file, Memory::PROCESS_IMAGE_VADDR);      LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), Memory::PROCESS_IMAGE_VADDR); +    auto& kernel = Core::System::GetInstance().Kernel();      process->svc_access_mask.set();      process->resource_limit = -        Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION); +        kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);      process->Run(Memory::PROCESS_IMAGE_VADDR, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);      is_loaded = true; diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index 539746246..038d57b3a 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp @@ -13,7 +13,7 @@ namespace ArmTests {  TestEnvironment::TestEnvironment(bool mutable_memory_)      : mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) { -    Core::CurrentProcess() = Kernel::Process::Create(""); +    Core::CurrentProcess() = Kernel::Process::Create(kernel, "");      page_table = &Core::CurrentProcess()->vm_manager.page_table;      page_table->pointers.fill(nullptr); diff --git a/src/tests/core/arm/arm_test_common.h b/src/tests/core/arm/arm_test_common.h index 7fdbda494..e4b6df194 100644 --- a/src/tests/core/arm/arm_test_common.h +++ b/src/tests/core/arm/arm_test_common.h @@ -9,6 +9,7 @@  #include <vector>  #include "common/common_types.h" +#include "core/hle/kernel/kernel.h"  #include "core/memory_hook.h"  namespace Memory { @@ -86,6 +87,7 @@ private:      std::shared_ptr<TestMemory> test_memory;      std::vector<WriteRecord> write_records;      Memory::PageTable* page_table = nullptr; +    Kernel::KernelCore kernel;  };  } // namespace ArmTests diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp index d0926d723..eac0c05f2 100644 --- a/src/yuzu/debugger/wait_tree.cpp +++ b/src/yuzu/debugger/wait_tree.cpp @@ -77,9 +77,11 @@ QString WaitTreeText::GetText() const {  }  WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address) : mutex_address(mutex_address) { +    auto& handle_table = Core::System::GetInstance().Kernel().HandleTable(); +      mutex_value = Memory::Read32(mutex_address);      owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Mutex::MutexOwnerMask); -    owner = Kernel::g_handle_table.Get<Kernel::Thread>(owner_handle); +    owner = handle_table.Get<Kernel::Thread>(owner_handle);  }  QString WaitTreeMutexInfo::GetText() const { | 
