From 0cbcd6ec9aeeafc298fe2e6e4ac10d68bb7267c5 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Tue, 28 Aug 2018 12:30:33 -0400 Subject: kernel: Eliminate kernel global state As means to pave the way for getting rid of global state within core, This eliminates kernel global state by removing all globals. Instead this introduces a KernelCore class which acts as a kernel instance. This instance lives in the System class, which keeps its lifetime contained to the lifetime of the System class. This also forces the kernel types to actually interact with the main kernel instance itself instead of having transient kernel state placed all over several translation units, keeping everything together. It also has a nice consequence of making dependencies much more explicit. This also makes our initialization a tad bit more correct. Previously we were creating a kernel process before the actual kernel was initialized, which doesn't really make much sense. The KernelCore class itself follows the PImpl idiom, which allows keeping all the implementation details sealed away from everything else, which forces the use of the exposed API and allows us to avoid any unnecessary inclusions within the main kernel header. --- src/core/hle/ipc_helpers.h | 5 +- src/core/hle/kernel/client_port.cpp | 4 +- src/core/hle/kernel/client_port.h | 5 +- src/core/hle/kernel/client_session.cpp | 2 +- src/core/hle/kernel/client_session.h | 5 +- src/core/hle/kernel/event.cpp | 8 +- src/core/hle/kernel/event.h | 8 +- src/core/hle/kernel/handle_table.cpp | 2 - src/core/hle/kernel/handle_table.h | 2 - src/core/hle/kernel/hle_ipc.cpp | 17 +- src/core/hle/kernel/kernel.cpp | 283 ++++++++++++++++++++++-- src/core/hle/kernel/kernel.h | 89 +++++++- src/core/hle/kernel/mutex.cpp | 6 +- src/core/hle/kernel/mutex.h | 5 +- src/core/hle/kernel/object.cpp | 2 + src/core/hle/kernel/object.h | 10 +- src/core/hle/kernel/process.cpp | 40 +--- src/core/hle/kernel/process.h | 21 +- src/core/hle/kernel/resource_limit.cpp | 85 +------ src/core/hle/kernel/resource_limit.h | 19 +- src/core/hle/kernel/server_port.cpp | 10 +- src/core/hle/kernel/server_port.h | 6 +- src/core/hle/kernel/server_session.cpp | 17 +- src/core/hle/kernel/server_session.h | 14 +- src/core/hle/kernel/shared_memory.cpp | 20 +- src/core/hle/kernel/shared_memory.h | 13 +- src/core/hle/kernel/svc.cpp | 80 ++++--- src/core/hle/kernel/thread.cpp | 119 ++-------- src/core/hle/kernel/thread.h | 22 +- src/core/hle/kernel/timer.cpp | 45 +--- src/core/hle/kernel/timer.h | 13 +- src/core/hle/kernel/wait_object.cpp | 3 + src/core/hle/kernel/wait_object.h | 4 + src/core/hle/service/am/am.cpp | 9 +- src/core/hle/service/audio/audout_u.cpp | 4 +- src/core/hle/service/audio/audren_u.cpp | 8 +- src/core/hle/service/hid/hid.cpp | 9 +- src/core/hle/service/nfp/nfp.cpp | 10 +- src/core/hle/service/nifm/nifm.cpp | 6 +- src/core/hle/service/ns/pl_u.cpp | 3 +- src/core/hle/service/nvdrv/interface.cpp | 4 +- src/core/hle/service/nvflinger/buffer_queue.cpp | 4 +- src/core/hle/service/nvflinger/nvflinger.cpp | 3 +- src/core/hle/service/service.cpp | 9 +- src/core/hle/service/sm/sm.cpp | 5 +- 45 files changed, 629 insertions(+), 429 deletions(-) (limited to 'src/core/hle') 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 #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 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> 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 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 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 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::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 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 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 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 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 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 +#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(); + + // Lock the global kernel mutex when we enter the kernel HLE. + std::lock_guard lock(HLE::g_hle_lock); + + 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(); + } +} + +/// 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); + + 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 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 - Process::next_process_id = 10; + 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++; } -/// Shutdown the kernel -void Shutdown() { - // Free all kernel objects - g_handle_table.Clear(); +u32 KernelCore::CreateNewProcessID() { + return impl->next_process_id++; +} - Kernel::ThreadingShutdown(); +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; +} - 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 +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 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; -/// Shutdown the kernel -void Shutdown(); + 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 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 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 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 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 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> 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() {} - -u32 Process::next_process_id; +CodeSet::CodeSet(KernelCore& kernel) : Object{kernel} {} +CodeSet::~CodeSet() = default; -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 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 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 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 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 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 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 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> 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 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> 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> 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 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 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 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::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 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 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 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 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 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(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 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> 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 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 #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 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 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 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) { 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 }; 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(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 #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 #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 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 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 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 f22a2a79f..b240d7eed 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)); -- cgit v1.2.3