diff --git a/src/core/core.cpp b/src/core/core.cpp index 07da4c4937..2293669e5b 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -171,6 +171,14 @@ const std::shared_ptr& 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(); - current_process = Kernel::Process::Create("main"); + current_process = Kernel::Process::Create(kernel, "main"); cpu_barrier = std::make_shared(); 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(); service_manager = std::make_shared(); - 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 321104585b..2c18f7193f 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 d3a7348319..0f3ffdb600 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -12,6 +12,7 @@ #include #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>(sessions); auto client = std::get>(sessions); iface->ClientConnected(server); diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp index 134e41ebc6..873d6c5163 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> ClientPort::Connect() { @@ -27,7 +27,7 @@ ResultVal> 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>(sessions)); diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h index b1269ea5c6..f3dfebbb18 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 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 fdffc648d9..c114eaf994 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 dabd93ed7c..439fbdb35e 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 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 5623c4b6a7..8967e602ea 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::Create(ResetType reset_type, std::string name) { - SharedPtr evt(new Event); +SharedPtr Event::Create(KernelCore& kernel, ResetType reset_type, std::string name) { + SharedPtr 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 3c20c05e84..27d6126b0a 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 Create(ResetType reset_type, std::string name = "Unknown"); + static SharedPtr 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 6d9f7a02bb..3a079b9a97 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 aee3583e8a..cac928adb8 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 82a3fb5a8e..db7aef7669 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 HLERequestContext::SleepClientThread(SharedPtr 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())); + copy_objects.push_back(handle_table.GetGeneric(rp.Pop())); } for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) { - move_objects.push_back(Kernel::g_handle_table.GetGeneric(rp.Pop())); + move_objects.push_back(handle_table.GetGeneric(rp.Pop())); } } 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 8c19e86d3b..615d7901a8 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 +#include +#include +#include +#include + +#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 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(thread_handle); + auto& system = Core::System::GetInstance(); -/// Initialize the kernel -void Init() { - Kernel::ResourceLimitsInit(); - Kernel::ThreadingInit(); - Kernel::TimersInit(); + // Lock the global kernel mutex when we enter the kernel HLE. + std::lock_guard lock(HLE::g_hle_lock); - Object::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; + SharedPtr 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(); + } } -/// Shutdown the kernel -void Shutdown() { - // Free all kernel objects - g_handle_table.Clear(); +/// 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(timer_handle); + auto& system = Core::System::GetInstance(); + SharedPtr timer = system.Kernel().RetrieveTimerFromCallbackHandleTable(proper_handle); - Kernel::ThreadingShutdown(); + if (timer == nullptr) { + LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016X}", timer_handle); + return; + } - Kernel::TimersShutdown(); - Kernel::ResourceLimitsShutdown(); + timer->Signal(cycles_late); +} + +struct KernelCore::Impl { + void Initialize(KernelCore& kernel) { + Shutdown(); + + 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 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(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(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(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(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 next_object_id{0}; + // TODO(Subv): Start the process ids from 10 for now, as lower PIDs are + // reserved for low-level services + std::atomic next_process_id{10}; + std::atomic next_thread_id{1}; + + // Lists all processes that exist in the current session. + std::vector> process_list; + + Kernel::HandleTable handle_table; + std::array, 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()} {} +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 KernelCore::ResourceLimitForCategory( + ResourceLimitCategory category) const { + return impl->resource_limits.at(static_cast(category)); +} + +SharedPtr KernelCore::RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const { + return impl->thread_wakeup_callback_handle_table.Get(handle); +} + +SharedPtr KernelCore::RetrieveTimerFromCallbackHandleTable(Handle handle) const { + return impl->timer_callback_handle_table.Get(handle); +} + +void KernelCore::AppendNewProcess(SharedPtr 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++; +} + +u32 KernelCore::CreateNewProcessID() { + return impl->next_process_id++; +} + +ResultVal KernelCore::CreateTimerCallbackHandle(const SharedPtr& 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; +} + +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 1313114720..089e959ac1 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 +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; -/// Shutdown the kernel -void Shutdown(); +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 ResourceLimitForCategory(ResourceLimitCategory category) const; + + /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. + SharedPtr RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const; + + /// Retrieves a shared pointer to a Timer instance within the timer callback handle table. + SharedPtr RetrieveTimerFromCallbackHandleTable(Handle handle) const; + + /// Adds the given shared pointer to an internal list of active processes. + void AppendNewProcess(SharedPtr 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 CreateTimerCallbackHandle(const SharedPtr& 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; + + struct Impl; + std::unique_ptr impl; +}; } // namespace Kernel diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp index cb7f58b358..36bf0b677a 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 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 holding_thread = g_handle_table.Get(holding_thread_handle); - SharedPtr requesting_thread = g_handle_table.Get(requesting_thread_handle); + SharedPtr holding_thread = handle_table.Get(holding_thread_handle); + SharedPtr requesting_thread = handle_table.Get(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 45268bbe9b..81e62d4970 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 cdba272f57..d51562d92c 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 526ac9cc3c..b054cbf7d8 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 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 ref_count{0}; - std::atomic object_id{next_object_id++}; + std::atomic 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 edf34c5a3b..b025e323ff 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> process_list; - -SharedPtr CodeSet::Create(std::string name) { - SharedPtr codeset(new CodeSet); +SharedPtr CodeSet::Create(KernelCore& kernel, std::string name) { + SharedPtr codeset(new CodeSet(kernel)); codeset->name = std::move(name); return codeset; } -CodeSet::CodeSet() {} -CodeSet::~CodeSet() {} +CodeSet::CodeSet(KernelCore& kernel) : Object{kernel} {} +CodeSet::~CodeSet() = default; -u32 Process::next_process_id; - -SharedPtr Process::Create(std::string&& name) { - SharedPtr process(new Process); +SharedPtr Process::Create(KernelCore& kernel, std::string&& name) { + SharedPtr 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 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 GetProcessById(u32 process_id) { - auto itr = std::find_if( - process_list.begin(), process_list.end(), - [&](const SharedPtr& 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 9926891864..1587d40c1e 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 Create(std::string name); + static SharedPtr 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 Create(std::string&& name); + static SharedPtr 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 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 17a3e8a747..b253a680f7 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 resource_limits[4]; +ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {} +ResourceLimit::~ResourceLimit() = default; -ResourceLimit::ResourceLimit() {} -ResourceLimit::~ResourceLimit() {} - -SharedPtr ResourceLimit::Create(std::string name) { - SharedPtr resource_limit(new ResourceLimit); +SharedPtr ResourceLimit::Create(KernelCore& kernel, std::string name) { + SharedPtr resource_limit(new ResourceLimit(kernel)); resource_limit->name = std::move(name); return resource_limit; } -SharedPtr 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(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 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(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(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(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(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 0fa141db3a..219e495624 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 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 GetForCategory(ResourceLimitCategory category); + static SharedPtr 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 7b6211fd8e..3792e3e186 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> ServerPort::Accept() { if (pending_sessions.empty()) { @@ -36,10 +36,10 @@ void ServerPort::Acquire(Thread* thread) { } std::tuple, SharedPtr> ServerPort::CreatePortPair( - u32 max_sessions, std::string name) { + KernelCore& kernel, u32 max_sessions, std::string name) { - SharedPtr server_port(new ServerPort); - SharedPtr client_port(new ClientPort); + SharedPtr server_port(new ServerPort(kernel)); + SharedPtr 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 7f6d6b3eb1..62fb513490 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> 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 51a1ec1605..90c9a5afff 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> ServerSession::Create(std::string name) { - SharedPtr server_session(new ServerSession); +ResultVal> ServerSession::Create(KernelCore& kernel, std::string name) { + SharedPtr server_session(new ServerSession(kernel)); server_session->name = std::move(name); server_session->parent = nullptr; @@ -105,10 +105,10 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr 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) { return result; } -ServerSession::SessionPair ServerSession::CreateSessionPair(const std::string& name, +ServerSession::SessionPair ServerSession::CreateSessionPair(KernelCore& kernel, + const std::string& name, SharedPtr port) { - auto server_session = ServerSession::Create(name + "_Server").Unwrap(); - SharedPtr client_session(new ClientSession); + auto server_session = ServerSession::Create(kernel, name + "_Server").Unwrap(); + SharedPtr client_session(new ClientSession(kernel)); client_session->name = name + "_Client"; std::shared_ptr parent(new Session); diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h index 1a88e66b9e..e068db2bf6 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 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> Create(std::string name = "Unknown"); + static ResultVal> 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 fc168d2b53..abb1d09cd3 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::Create(SharedPtr owner_process, u64 size, - MemoryPermission permissions, +SharedPtr SharedMemory::Create(KernelCore& kernel, SharedPtr owner_process, + u64 size, MemoryPermission permissions, MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) { - SharedPtr shared_memory(new SharedMemory); + SharedPtr 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::Create(SharedPtr owner_process, u return shared_memory; } -SharedPtr SharedMemory::CreateForApplet(std::shared_ptr> heap_block, - u32 offset, u32 size, - MemoryPermission permissions, - MemoryPermission other_permissions, - std::string name) { - SharedPtr shared_memory(new SharedMemory); +SharedPtr SharedMemory::CreateForApplet( + KernelCore& kernel, std::shared_ptr> heap_block, u32 offset, u32 size, + MemoryPermission permissions, MemoryPermission other_permissions, std::string name) { + SharedPtr 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 c50fee615f..2c729afe3f 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 Create(SharedPtr owner_process, u64 size, - MemoryPermission permissions, + static SharedPtr Create(KernelCore& kernel, SharedPtr 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 CreateForApplet(std::shared_ptr> heap_block, + static SharedPtr CreateForApplet(KernelCore& kernel, + std::shared_ptr> 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 cb6253398c..099d1053f9 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 session = g_handle_table.Get(handle); + auto& kernel = Core::System::GetInstance().Kernel(); + SharedPtr session = kernel.HandleTable().Get(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 = g_handle_table.Get(thread_handle); + auto& kernel = Core::System::GetInstance().Kernel(); + const SharedPtr thread = kernel.HandleTable().Get(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 = g_handle_table.Get(process_handle); + auto& kernel = Core::System::GetInstance().Kernel(); + const SharedPtr process = kernel.HandleTable().Get(process_handle); if (!process) { return ERR_INVALID_HANDLE; } @@ -168,10 +172,11 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64 using ObjectPtr = SharedPtr; std::vector 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(handle); + const auto object = kernel.HandleTable().Get(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 = g_handle_table.Get(thread_handle); + auto& kernel = Core::System::GetInstance().Kernel(); + const SharedPtr thread = kernel.HandleTable().Get(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 = g_handle_table.Get(handle); + auto& kernel = Core::System::GetInstance().Kernel(); + const SharedPtr thread = kernel.HandleTable().Get(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 = g_handle_table.Get(handle); + auto& kernel = Core::System::GetInstance().Kernel(); + SharedPtr thread = kernel.HandleTable().Get(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 shared_memory = g_handle_table.Get(shared_memory_handle); + auto& kernel = Core::System::GetInstance().Kernel(); + auto shared_memory = kernel.HandleTable().Get(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 shared_memory = g_handle_table.Get(shared_memory_handle); + auto& kernel = Core::System::GetInstance().Kernel(); + auto shared_memory = kernel.HandleTable().Get(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 = g_handle_table.Get(process_handle); + + auto& kernel = Core::System::GetInstance().Kernel(); + SharedPtr process = kernel.HandleTable().Get(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::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 = g_handle_table.Get(thread_handle); + auto& kernel = Core::System::GetInstance().Kernel(); + const SharedPtr thread = kernel.HandleTable().Get(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 = g_handle_table.Get(thread_handle); + auto& kernel = Core::System::GetInstance().Kernel(); + SharedPtr thread = kernel.HandleTable().Get(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(mutex_val & Mutex::MutexOwnerMask); - auto owner = g_handle_table.Get(owner_handle); + auto owner = kernel.HandleTable().Get(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(handle); + + auto& kernel = Core::System::GetInstance().Kernel(); + auto event = kernel.HandleTable().Get(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 = g_handle_table.Get(thread_handle); + auto& kernel = Core::System::GetInstance().Kernel(); + const SharedPtr thread = kernel.HandleTable().Get(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 = g_handle_table.Get(thread_handle); + auto& kernel = Core::System::GetInstance().Kernel(); + const SharedPtr thread = kernel.HandleTable().Get(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(KernelHandle::CurrentProcess), size, + + auto& kernel = Core::System::GetInstance().Kernel(); + auto& handle_table = kernel.HandleTable(); + auto shared_mem_handle = + SharedMemory::Create(kernel, handle_table.Get(KernelHandle::CurrentProcess), size, static_cast(local_permissions), static_cast(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 evt = g_handle_table.Get(handle); + auto& kernel = Core::System::GetInstance().Kernel(); + SharedPtr evt = kernel.HandleTable().Get(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 4ffd8d5cc6..520ea0853f 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(thread_handle); - - // Lock the global kernel mutex when we enter the kernel HLE. - std::lock_guard lock(HLE::g_hle_lock); - - SharedPtr thread = wakeup_callback_handle_table.Get(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 GetNextProcessorId(u64 mask) { @@ -294,9 +220,9 @@ static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAdd context.fpscr = 0; } -ResultVal> Thread::Create(std::string name, VAddr entry_point, u32 priority, - u64 arg, s32 processor_id, VAddr stack_top, - SharedPtr owner_process) { +ResultVal> Thread::Create(KernelCore& kernel, std::string name, VAddr entry_point, + u32 priority, u64 arg, s32 processor_id, + VAddr stack_top, SharedPtr 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> Thread::Create(std::string name, VAddr entry_point, return ResultCode(-1); } - SharedPtr thread(new Thread); + SharedPtr 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> 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 SetupMainThread(VAddr entry_point, u32 priority, +SharedPtr SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority, SharedPtr 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 = 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 06edc296d5..20f50458b7 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> Create(std::string name, VAddr entry_point, u32 priority, - u64 arg, s32 processor_id, VAddr stack_top, + static ResultVal> Create(KernelCore& kernel, std::string name, + VAddr entry_point, u32 priority, u64 arg, + s32 processor_id, VAddr stack_top, SharedPtr 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> tls_memory = std::make_shared>(); @@ -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 SetupMainThread(VAddr entry_point, u32 priority, +SharedPtr SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority, SharedPtr 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 282360745c..6957b16e03 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 #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::Create(ResetType reset_type, std::string name) { - SharedPtr timer(new Timer); +SharedPtr Timer::Create(KernelCore& kernel, ResetType reset_type, std::string name) { + SharedPtr 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_callback_handle_table.Get(static_cast(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 4dddc67e09..12915c1b11 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 Create(ResetType reset_type, std::string name = "Unknown"); + static SharedPtr 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 7681cdee7d..eef00b729a 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) { 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 b5fbc647b3..0bd97133c7 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 7e3cf6d583..818c03e0f3 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 }; 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 ce709ccf49..5f370bbdfb 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 9e75eb3a6c..016db7c82c 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(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 c0ba330dcd..0d31abe8b5 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -4,6 +4,7 @@ #include #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 56b05e9e80..4f7543af5e 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 cfe8d91786..ed4f5f5393 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 923a52cc53..51638793da 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 1b497b8145..634ab9196d 100644 --- a/src/core/hle/service/nvdrv/interface.cpp +++ b/src/core/hle/service/nvdrv/interface.cpp @@ -4,6 +4,7 @@ #include #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 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 ef5713a71f..8d89622769 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 a26a5f8125..3996c24fea 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 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 11951adaf4..8fb9070725 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 server_port; SharedPtr 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 ServiceFrameworkBase::CreatePort() { ASSERT(port == nullptr); + + auto& kernel = Core::System::GetInstance().Kernel(); Kernel::SharedPtr server_port; Kernel::SharedPtr 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>(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 f22a2a79f6..b240d7eed5 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp @@ -4,6 +4,7 @@ #include #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> ServiceManager::RegisterService if (registered_services.find(name) != registered_services.end()) return ERR_ALREADY_REGISTERED; + auto& kernel = Core::System::GetInstance().Kernel(); Kernel::SharedPtr server_port; Kernel::SharedPtr 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>(std::move(server_port)); diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp index 4c79d7902c..a53fa6e00c 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 6420a7f110..3702a84781 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 ElfReader::LoadInto(u32 vaddr) { std::vector program_image(total_image_size); size_t current_image_position = 0; - SharedPtr codeset = CodeSet::Create(""); + auto& kernel = Core::System::GetInstance().Kernel(); + SharedPtr 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& 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 2179cf2ea0..00205d1d21 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 codeset = Kernel::CodeSet::Create(""); + auto& kernel = Core::System::GetInstance().Kernel(); + Kernel::SharedPtr codeset = Kernel::CodeSet::Create(kernel, ""); std::vector 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& 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 a94558ac5f..0c992d662b 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 codeset = Kernel::CodeSet::Create(""); + auto& kernel = Core::System::GetInstance().Kernel(); + Kernel::SharedPtr codeset = Kernel::CodeSet::Create(kernel, ""); std::vector program_image; for (std::size_t i = 0; i < nso_header.segments.size(); ++i) { const std::vector compressed_data = @@ -151,9 +152,10 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr& 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 539746246b..038d57b3a6 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(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 7fdbda494c..e4b6df194e 100644 --- a/src/tests/core/arm/arm_test_common.h +++ b/src/tests/core/arm/arm_test_common.h @@ -9,6 +9,7 @@ #include #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 test_memory; std::vector 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 d0926d723d..eac0c05f27 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(mutex_value & Kernel::Mutex::MutexOwnerMask); - owner = Kernel::g_handle_table.Get(owner_handle); + owner = handle_table.Get(owner_handle); } QString WaitTreeMutexInfo::GetText() const {