summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/client_port.cpp4
-rw-r--r--src/core/hle/kernel/client_port.h5
-rw-r--r--src/core/hle/kernel/client_session.cpp2
-rw-r--r--src/core/hle/kernel/client_session.h5
-rw-r--r--src/core/hle/kernel/event.cpp8
-rw-r--r--src/core/hle/kernel/event.h8
-rw-r--r--src/core/hle/kernel/handle_table.cpp2
-rw-r--r--src/core/hle/kernel/handle_table.h2
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp17
-rw-r--r--src/core/hle/kernel/kernel.cpp283
-rw-r--r--src/core/hle/kernel/kernel.h89
-rw-r--r--src/core/hle/kernel/mutex.cpp6
-rw-r--r--src/core/hle/kernel/mutex.h5
-rw-r--r--src/core/hle/kernel/object.cpp2
-rw-r--r--src/core/hle/kernel/object.h10
-rw-r--r--src/core/hle/kernel/process.cpp40
-rw-r--r--src/core/hle/kernel/process.h21
-rw-r--r--src/core/hle/kernel/resource_limit.cpp85
-rw-r--r--src/core/hle/kernel/resource_limit.h19
-rw-r--r--src/core/hle/kernel/server_port.cpp10
-rw-r--r--src/core/hle/kernel/server_port.h6
-rw-r--r--src/core/hle/kernel/server_session.cpp17
-rw-r--r--src/core/hle/kernel/server_session.h14
-rw-r--r--src/core/hle/kernel/shared_memory.cpp20
-rw-r--r--src/core/hle/kernel/shared_memory.h13
-rw-r--r--src/core/hle/kernel/svc.cpp80
-rw-r--r--src/core/hle/kernel/thread.cpp119
-rw-r--r--src/core/hle/kernel/thread.h22
-rw-r--r--src/core/hle/kernel/timer.cpp45
-rw-r--r--src/core/hle/kernel/timer.h13
-rw-r--r--src/core/hle/kernel/wait_object.cpp3
-rw-r--r--src/core/hle/kernel/wait_object.h4
32 files changed, 574 insertions, 405 deletions
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 134e41ebc..873d6c516 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -14,7 +14,7 @@
namespace Kernel {
-ClientPort::ClientPort() = default;
+ClientPort::ClientPort(KernelCore& kernel) : Object{kernel} {}
ClientPort::~ClientPort() = default;
ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
@@ -27,7 +27,7 @@ ResultVal<SharedPtr<ClientSession>> ClientPort::Connect() {
active_sessions++;
// Create a new session pair, let the created sessions inherit the parent port's HLE handler.
- auto sessions = ServerSession::CreateSessionPair(server_port->GetName(), this);
+ auto sessions = ServerSession::CreateSessionPair(kernel, server_port->GetName(), this);
if (server_port->hle_handler)
server_port->hle_handler->ClientConnected(std::get<SharedPtr<ServerSession>>(sessions));
diff --git a/src/core/hle/kernel/client_port.h b/src/core/hle/kernel/client_port.h
index b1269ea5c..f3dfebbb1 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -11,8 +11,9 @@
namespace Kernel {
-class ServerPort;
class ClientSession;
+class KernelCore;
+class ServerPort;
class ClientPort final : public Object {
public:
@@ -44,7 +45,7 @@ public:
void ConnectionClosed();
private:
- ClientPort();
+ explicit ClientPort(KernelCore& kernel);
~ClientPort() override;
SharedPtr<ServerPort> server_port; ///< ServerPort associated with this client port.
diff --git a/src/core/hle/kernel/client_session.cpp b/src/core/hle/kernel/client_session.cpp
index fdffc648d..c114eaf99 100644
--- a/src/core/hle/kernel/client_session.cpp
+++ b/src/core/hle/kernel/client_session.cpp
@@ -11,7 +11,7 @@
namespace Kernel {
-ClientSession::ClientSession() = default;
+ClientSession::ClientSession(KernelCore& kernel) : Object{kernel} {}
ClientSession::~ClientSession() {
// This destructor will be called automatically when the last ClientSession handle is closed by
// the emulated application.
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h
index dabd93ed7..439fbdb35 100644
--- a/src/core/hle/kernel/client_session.h
+++ b/src/core/hle/kernel/client_session.h
@@ -12,8 +12,9 @@
namespace Kernel {
-class ServerSession;
+class KernelCore;
class Session;
+class ServerSession;
class Thread;
class ClientSession final : public Object {
@@ -41,7 +42,7 @@ public:
std::shared_ptr<Session> parent;
private:
- ClientSession();
+ explicit ClientSession(KernelCore& kernel);
~ClientSession() override;
};
diff --git a/src/core/hle/kernel/event.cpp b/src/core/hle/kernel/event.cpp
index 5623c4b6a..8967e602e 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -10,11 +10,11 @@
namespace Kernel {
-Event::Event() {}
-Event::~Event() {}
+Event::Event(KernelCore& kernel) : WaitObject{kernel} {}
+Event::~Event() = default;
-SharedPtr<Event> Event::Create(ResetType reset_type, std::string name) {
- SharedPtr<Event> evt(new Event);
+SharedPtr<Event> Event::Create(KernelCore& kernel, ResetType reset_type, std::string name) {
+ SharedPtr<Event> evt(new Event(kernel));
evt->signaled = false;
evt->reset_type = reset_type;
diff --git a/src/core/hle/kernel/event.h b/src/core/hle/kernel/event.h
index 3c20c05e8..27d6126b0 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -10,14 +10,18 @@
namespace Kernel {
+class KernelCore;
+
class Event final : public WaitObject {
public:
/**
* Creates an event
+ * @param kernel The kernel instance to create this event under.
* @param reset_type ResetType describing how to create event
* @param name Optional name of event
*/
- static SharedPtr<Event> Create(ResetType reset_type, std::string name = "Unknown");
+ static SharedPtr<Event> Create(KernelCore& kernel, ResetType reset_type,
+ std::string name = "Unknown");
std::string GetTypeName() const override {
return "Event";
@@ -44,7 +48,7 @@ public:
void Clear();
private:
- Event();
+ explicit Event(KernelCore& kernel);
~Event() override;
ResetType reset_type; ///< Current ResetType
diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp
index 6d9f7a02b..3a079b9a9 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -13,8 +13,6 @@
namespace Kernel {
-HandleTable g_handle_table;
-
HandleTable::HandleTable() {
next_generation = 1;
Clear();
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
index aee3583e8..cac928adb 100644
--- a/src/core/hle/kernel/handle_table.h
+++ b/src/core/hle/kernel/handle_table.h
@@ -121,6 +121,4 @@ private:
u16 next_free_slot;
};
-extern HandleTable g_handle_table;
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 82a3fb5a8..db7aef766 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -13,6 +13,7 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h"
@@ -51,7 +52,9 @@ SharedPtr<Event> HLERequestContext::SleepClientThread(SharedPtr<Thread> thread,
if (!event) {
// Create event if not provided
- event = Kernel::Event::Create(Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ event =
+ Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "HLE Pause Event: " + reason);
}
event->Clear();
@@ -90,12 +93,14 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
rp.Skip(2, false);
}
if (incoming) {
+ auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
+
// Populate the object lists with the data in the IPC request.
for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) {
- copy_objects.push_back(Kernel::g_handle_table.GetGeneric(rp.Pop<Handle>()));
+ copy_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));
}
for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) {
- move_objects.push_back(Kernel::g_handle_table.GetGeneric(rp.Pop<Handle>()));
+ move_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));
}
} else {
// For responses we just ignore the handles, they're empty and will be populated when
@@ -230,17 +235,19 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(const Thread& thread)
ASSERT(copy_objects.size() == handle_descriptor_header->num_handles_to_copy);
ASSERT(move_objects.size() == handle_descriptor_header->num_handles_to_move);
+ auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
+
// We don't make a distinction between copy and move handles when translating since HLE
// services don't deal with handles directly. However, the guest applications might check
// for specific values in each of these descriptors.
for (auto& object : copy_objects) {
ASSERT(object != nullptr);
- dst_cmdbuf[current_offset++] = Kernel::g_handle_table.Create(object).Unwrap();
+ dst_cmdbuf[current_offset++] = handle_table.Create(object).Unwrap();
}
for (auto& object : move_objects) {
ASSERT(object != nullptr);
- dst_cmdbuf[current_offset++] = Kernel::g_handle_table.Create(object).Unwrap();
+ dst_cmdbuf[current_offset++] = handle_table.Create(object).Unwrap();
}
}
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8c19e86d3..615d7901a 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -2,38 +2,291 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <array>
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <utility>
+
+#include "common/assert.h"
+#include "common/logging/log.h"
+
+#include "core/core.h"
+#include "core/core_timing.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
+#include "core/hle/lock.h"
+#include "core/hle/result.h"
namespace Kernel {
-std::atomic<u32> Object::next_object_id{0};
+/**
+ * Callback that will wake up the thread it was scheduled for
+ * @param thread_handle The handle of the thread that's been awoken
+ * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
+ */
+static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] int cycles_late) {
+ const auto proper_handle = static_cast<Handle>(thread_handle);
+ auto& system = Core::System::GetInstance();
+
+ // Lock the global kernel mutex when we enter the kernel HLE.
+ std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
+
+ SharedPtr<Thread> thread =
+ system.Kernel().RetrieveThreadFromWakeupCallbackHandleTable(proper_handle);
+ if (thread == nullptr) {
+ LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
+ return;
+ }
+
+ bool resume = true;
+
+ if (thread->status == ThreadStatus::WaitSynchAny ||
+ thread->status == ThreadStatus::WaitSynchAll ||
+ thread->status == ThreadStatus::WaitHLEEvent) {
+ // Remove the thread from each of its waiting objects' waitlists
+ for (auto& object : thread->wait_objects) {
+ object->RemoveWaitingThread(thread.get());
+ }
+ thread->wait_objects.clear();
+
+ // Invoke the wakeup callback before clearing the wait objects
+ if (thread->wakeup_callback) {
+ resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
+ }
+ }
+
+ if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 ||
+ thread->wait_handle) {
+ ASSERT(thread->status == ThreadStatus::WaitMutex);
+ thread->mutex_wait_address = 0;
+ thread->condvar_wait_address = 0;
+ thread->wait_handle = 0;
+
+ auto lock_owner = thread->lock_owner;
+ // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance
+ // and don't have a lock owner unless SignalProcessWideKey was called first and the thread
+ // wasn't awakened due to the mutex already being acquired.
+ if (lock_owner) {
+ lock_owner->RemoveMutexWaiter(thread);
+ }
+ }
+
+ if (thread->arb_wait_address != 0) {
+ ASSERT(thread->status == ThreadStatus::WaitArb);
+ thread->arb_wait_address = 0;
+ }
+
+ if (resume) {
+ thread->ResumeFromWait();
+ }
+}
+
+/// The timer callback event, called when a timer is fired
+static void TimerCallback(u64 timer_handle, int cycles_late) {
+ const auto proper_handle = static_cast<Handle>(timer_handle);
+ auto& system = Core::System::GetInstance();
+ SharedPtr<Timer> timer = system.Kernel().RetrieveTimerFromCallbackHandleTable(proper_handle);
+
+ if (timer == nullptr) {
+ LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016X}", timer_handle);
+ return;
+ }
+
+ timer->Signal(cycles_late);
+}
-/// Initialize the kernel
-void Init() {
- Kernel::ResourceLimitsInit();
- Kernel::ThreadingInit();
- Kernel::TimersInit();
+struct KernelCore::Impl {
+ void Initialize(KernelCore& kernel) {
+ Shutdown();
- Object::next_object_id = 0;
+ InitializeResourceLimits(kernel);
+ InitializeThreads();
+ InitializeTimers();
+ }
+
+ void Shutdown() {
+ next_object_id = 0;
+ next_process_id = 10;
+ next_thread_id = 1;
+
+ process_list.clear();
+
+ handle_table.Clear();
+ resource_limits.fill(nullptr);
+
+ thread_wakeup_callback_handle_table.Clear();
+ thread_wakeup_event_type = nullptr;
+
+ timer_callback_handle_table.Clear();
+ timer_callback_event_type = nullptr;
+ }
+
+ void InitializeResourceLimits(KernelCore& kernel) {
+ // Create the four resource limits that the system uses
+ // Create the APPLICATION resource limit
+ SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create(kernel, "Applications");
+ resource_limit->max_priority = 0x18;
+ resource_limit->max_commit = 0x4000000;
+ resource_limit->max_threads = 0x20;
+ resource_limit->max_events = 0x20;
+ resource_limit->max_mutexes = 0x20;
+ resource_limit->max_semaphores = 0x8;
+ resource_limit->max_timers = 0x8;
+ resource_limit->max_shared_mems = 0x10;
+ resource_limit->max_address_arbiters = 0x2;
+ resource_limit->max_cpu_time = 0x1E;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit;
+
+ // Create the SYS_APPLET resource limit
+ resource_limit = ResourceLimit::Create(kernel, "System Applets");
+ resource_limit->max_priority = 0x4;
+ resource_limit->max_commit = 0x5E00000;
+ resource_limit->max_threads = 0x1D;
+ resource_limit->max_events = 0xB;
+ resource_limit->max_mutexes = 0x8;
+ resource_limit->max_semaphores = 0x4;
+ resource_limit->max_timers = 0x4;
+ resource_limit->max_shared_mems = 0x8;
+ resource_limit->max_address_arbiters = 0x3;
+ resource_limit->max_cpu_time = 0x2710;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit;
+
+ // Create the LIB_APPLET resource limit
+ resource_limit = ResourceLimit::Create(kernel, "Library Applets");
+ resource_limit->max_priority = 0x4;
+ resource_limit->max_commit = 0x600000;
+ resource_limit->max_threads = 0xE;
+ resource_limit->max_events = 0x8;
+ resource_limit->max_mutexes = 0x8;
+ resource_limit->max_semaphores = 0x4;
+ resource_limit->max_timers = 0x4;
+ resource_limit->max_shared_mems = 0x8;
+ resource_limit->max_address_arbiters = 0x1;
+ resource_limit->max_cpu_time = 0x2710;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit;
+
+ // Create the OTHER resource limit
+ resource_limit = ResourceLimit::Create(kernel, "Others");
+ resource_limit->max_priority = 0x4;
+ resource_limit->max_commit = 0x2180000;
+ resource_limit->max_threads = 0xE1;
+ resource_limit->max_events = 0x108;
+ resource_limit->max_mutexes = 0x25;
+ resource_limit->max_semaphores = 0x43;
+ resource_limit->max_timers = 0x2C;
+ resource_limit->max_shared_mems = 0x1F;
+ resource_limit->max_address_arbiters = 0x2D;
+ resource_limit->max_cpu_time = 0x3E8;
+ resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit;
+ }
+
+ void InitializeThreads() {
+ thread_wakeup_event_type =
+ CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
+ }
+
+ void InitializeTimers() {
+ timer_callback_handle_table.Clear();
+ timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
+ }
+
+ std::atomic<u32> next_object_id{0};
// TODO(Subv): Start the process ids from 10 for now, as lower PIDs are
// reserved for low-level services
- Process::next_process_id = 10;
+ std::atomic<u32> next_process_id{10};
+ std::atomic<u32> next_thread_id{1};
+
+ // Lists all processes that exist in the current session.
+ std::vector<SharedPtr<Process>> process_list;
+
+ Kernel::HandleTable handle_table;
+ std::array<SharedPtr<ResourceLimit>, 4> resource_limits;
+
+ /// The event type of the generic timer callback event
+ CoreTiming::EventType* timer_callback_event_type = nullptr;
+ // TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future,
+ // allowing us to simply use a pool index or similar.
+ Kernel::HandleTable timer_callback_handle_table;
+
+ CoreTiming::EventType* thread_wakeup_event_type = nullptr;
+ // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future,
+ // allowing us to simply use a pool index or similar.
+ Kernel::HandleTable thread_wakeup_callback_handle_table;
+};
+
+KernelCore::KernelCore() : impl{std::make_unique<Impl>()} {}
+KernelCore::~KernelCore() {
+ Shutdown();
+}
+
+void KernelCore::Initialize() {
+ impl->Initialize(*this);
+}
+
+void KernelCore::Shutdown() {
+ impl->Shutdown();
+}
+
+Kernel::HandleTable& KernelCore::HandleTable() {
+ return impl->handle_table;
+}
+
+const Kernel::HandleTable& KernelCore::HandleTable() const {
+ return impl->handle_table;
+}
+
+SharedPtr<ResourceLimit> KernelCore::ResourceLimitForCategory(
+ ResourceLimitCategory category) const {
+ return impl->resource_limits.at(static_cast<std::size_t>(category));
+}
+
+SharedPtr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const {
+ return impl->thread_wakeup_callback_handle_table.Get<Thread>(handle);
+}
+
+SharedPtr<Timer> KernelCore::RetrieveTimerFromCallbackHandleTable(Handle handle) const {
+ return impl->timer_callback_handle_table.Get<Timer>(handle);
+}
+
+void KernelCore::AppendNewProcess(SharedPtr<Process> process) {
+ impl->process_list.push_back(std::move(process));
+}
+
+u32 KernelCore::CreateNewObjectID() {
+ return impl->next_object_id++;
+}
+
+u32 KernelCore::CreateNewThreadID() {
+ return impl->next_thread_id++;
}
-/// Shutdown the kernel
-void Shutdown() {
- // Free all kernel objects
- g_handle_table.Clear();
+u32 KernelCore::CreateNewProcessID() {
+ return impl->next_process_id++;
+}
- Kernel::ThreadingShutdown();
+ResultVal<Handle> KernelCore::CreateTimerCallbackHandle(const SharedPtr<Timer>& timer) {
+ return impl->timer_callback_handle_table.Create(timer);
+}
+
+CoreTiming::EventType* KernelCore::ThreadWakeupCallbackEventType() const {
+ return impl->thread_wakeup_event_type;
+}
+
+CoreTiming::EventType* KernelCore::TimerCallbackEventType() const {
+ return impl->timer_callback_event_type;
+}
+
+Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() {
+ return impl->thread_wakeup_callback_handle_table;
+}
- Kernel::TimersShutdown();
- Kernel::ResourceLimitsShutdown();
+const Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() const {
+ return impl->thread_wakeup_callback_handle_table;
}
} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 131311472..089e959ac 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -4,14 +4,93 @@
#pragma once
-#include "common/common_types.h"
+#include "core/hle/kernel/object.h"
+
+template <typename T>
+class ResultVal;
+
+namespace CoreTiming {
+struct EventType;
+}
namespace Kernel {
-/// Initialize the kernel with the specified system mode.
-void Init();
+class HandleTable;
+class Process;
+class ResourceLimit;
+class Thread;
+class Timer;
+
+enum class ResourceLimitCategory : u8;
+
+/// Represents a single instance of the kernel.
+class KernelCore {
+public:
+ KernelCore();
+ ~KernelCore();
+
+ KernelCore(const KernelCore&) = delete;
+ KernelCore& operator=(const KernelCore&) = delete;
+
+ KernelCore(KernelCore&&) = delete;
+ KernelCore& operator=(KernelCore&&) = delete;
+
+ /// Resets the kernel to a clean slate for use.
+ void Initialize();
+
+ /// Clears all resources in use by the kernel instance.
+ void Shutdown();
+
+ /// Provides a reference to the handle table.
+ Kernel::HandleTable& HandleTable();
+
+ /// Provides a const reference to the handle table.
+ const Kernel::HandleTable& HandleTable() const;
+
+ /// Retrieves a shared pointer to a ResourceLimit identified by the given category.
+ SharedPtr<ResourceLimit> ResourceLimitForCategory(ResourceLimitCategory category) const;
+
+ /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
+ SharedPtr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const;
+
+ /// Retrieves a shared pointer to a Timer instance within the timer callback handle table.
+ SharedPtr<Timer> RetrieveTimerFromCallbackHandleTable(Handle handle) const;
+
+ /// Adds the given shared pointer to an internal list of active processes.
+ void AppendNewProcess(SharedPtr<Process> process);
+
+private:
+ friend class Object;
+ friend class Process;
+ friend class Thread;
+ friend class Timer;
+
+ /// Creates a new object ID, incrementing the internal object ID counter.
+ u32 CreateNewObjectID();
+
+ /// Creates a new process ID, incrementing the internal process ID counter;
+ u32 CreateNewProcessID();
+
+ /// Creates a new thread ID, incrementing the internal thread ID counter.
+ u32 CreateNewThreadID();
+
+ /// Creates a timer callback handle for the given timer.
+ ResultVal<Handle> CreateTimerCallbackHandle(const SharedPtr<Timer>& timer);
+
+ /// Retrieves the event type used for thread wakeup callbacks.
+ CoreTiming::EventType* ThreadWakeupCallbackEventType() const;
+
+ /// Retrieves the event type used for timer callbacks.
+ CoreTiming::EventType* TimerCallbackEventType() const;
+
+ /// Provides a reference to the thread wakeup callback handle table.
+ Kernel::HandleTable& ThreadWakeupCallbackHandleTable();
+
+ /// Provides a const reference to the thread wakeup callback handle table.
+ const Kernel::HandleTable& ThreadWakeupCallbackHandleTable() const;
-/// Shutdown the kernel
-void Shutdown();
+ struct Impl;
+ std::unique_ptr<Impl> impl;
+};
} // namespace Kernel
diff --git a/src/core/hle/kernel/mutex.cpp b/src/core/hle/kernel/mutex.cpp
index cb7f58b35..36bf0b677 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -58,15 +58,15 @@ static void TransferMutexOwnership(VAddr mutex_addr, SharedPtr<Thread> current_t
}
}
-ResultCode Mutex::TryAcquire(VAddr address, Handle holding_thread_handle,
+ResultCode Mutex::TryAcquire(HandleTable& handle_table, VAddr address, Handle holding_thread_handle,
Handle requesting_thread_handle) {
// The mutex address must be 4-byte aligned
if ((address % sizeof(u32)) != 0) {
return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidAddress);
}
- SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle);
- SharedPtr<Thread> requesting_thread = g_handle_table.Get<Thread>(requesting_thread_handle);
+ SharedPtr<Thread> holding_thread = handle_table.Get<Thread>(holding_thread_handle);
+ SharedPtr<Thread> requesting_thread = handle_table.Get<Thread>(requesting_thread_handle);
// TODO(Subv): It is currently unknown if it is possible to lock a mutex in behalf of another
// thread.
diff --git a/src/core/hle/kernel/mutex.h b/src/core/hle/kernel/mutex.h
index 45268bbe9..81e62d497 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -11,6 +11,7 @@ union ResultCode;
namespace Kernel {
+class HandleTable;
class Thread;
class Mutex final {
@@ -21,8 +22,8 @@ public:
static constexpr u32 MutexOwnerMask = 0xBFFFFFFF;
/// Attempts to acquire a mutex at the specified address.
- static ResultCode TryAcquire(VAddr address, Handle holding_thread_handle,
- Handle requesting_thread_handle);
+ static ResultCode TryAcquire(HandleTable& handle_table, VAddr address,
+ Handle holding_thread_handle, Handle requesting_thread_handle);
/// Releases the mutex at the specified address.
static ResultCode Release(VAddr address);
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index cdba272f5..d51562d92 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -3,10 +3,12 @@
// Refer to the license.txt file included.
#include "common/assert.h"
+#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
namespace Kernel {
+Object::Object(KernelCore& kernel) : kernel{kernel}, object_id{kernel.CreateNewObjectID()} {}
Object::~Object() = default;
bool Object::IsWaitable() const {
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 526ac9cc3..b054cbf7d 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -14,6 +14,8 @@
namespace Kernel {
+class KernelCore;
+
using Handle = u32;
enum class HandleType : u32 {
@@ -40,6 +42,7 @@ enum class ResetType {
class Object : NonCopyable {
public:
+ explicit Object(KernelCore& kernel);
virtual ~Object();
/// Returns a unique identifier for the object. For debugging purposes only.
@@ -61,15 +64,16 @@ public:
*/
bool IsWaitable() const;
-public:
- static std::atomic<u32> next_object_id;
+protected:
+ /// The kernel instance this object was created under.
+ KernelCore& kernel;
private:
friend void intrusive_ptr_add_ref(Object*);
friend void intrusive_ptr_release(Object*);
std::atomic<u32> ref_count{0};
- std::atomic<u32> object_id{next_object_id++};
+ std::atomic<u32> object_id{0};
};
// Special functions used by boost::instrusive_ptr to do automatic ref-counting
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index edf34c5a3..b025e323f 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -8,6 +8,7 @@
#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "core/hle/kernel/errors.h"
+#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/thread.h"
@@ -16,30 +17,26 @@
namespace Kernel {
-// Lists all processes that exist in the current session.
-static std::vector<SharedPtr<Process>> process_list;
-
-SharedPtr<CodeSet> CodeSet::Create(std::string name) {
- SharedPtr<CodeSet> codeset(new CodeSet);
+SharedPtr<CodeSet> CodeSet::Create(KernelCore& kernel, std::string name) {
+ SharedPtr<CodeSet> codeset(new CodeSet(kernel));
codeset->name = std::move(name);
return codeset;
}
-CodeSet::CodeSet() {}
-CodeSet::~CodeSet() {}
-
-u32 Process::next_process_id;
+CodeSet::CodeSet(KernelCore& kernel) : Object{kernel} {}
+CodeSet::~CodeSet() = default;
-SharedPtr<Process> Process::Create(std::string&& name) {
- SharedPtr<Process> process(new Process);
+SharedPtr<Process> Process::Create(KernelCore& kernel, std::string&& name) {
+ SharedPtr<Process> process(new Process(kernel));
process->name = std::move(name);
process->flags.raw = 0;
process->flags.memory_region.Assign(MemoryRegion::APPLICATION);
process->status = ProcessStatus::Created;
process->program_id = 0;
+ process->process_id = kernel.CreateNewProcessID();
- process_list.push_back(process);
+ kernel.AppendNewProcess(process);
return process;
}
@@ -128,7 +125,7 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
vm_manager.LogLayout();
status = ProcessStatus::Running;
- Kernel::SetupMainThread(entry_point, main_thread_priority, this);
+ Kernel::SetupMainThread(kernel, entry_point, main_thread_priority, this);
}
void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) {
@@ -231,22 +228,7 @@ ResultCode Process::UnmapMemory(VAddr dst_addr, VAddr /*src_addr*/, u64 size) {
return vm_manager.UnmapRange(dst_addr, size);
}
-Kernel::Process::Process() {}
+Kernel::Process::Process(KernelCore& kernel) : Object{kernel} {}
Kernel::Process::~Process() {}
-void ClearProcessList() {
- process_list.clear();
-}
-
-SharedPtr<Process> GetProcessById(u32 process_id) {
- auto itr = std::find_if(
- process_list.begin(), process_list.end(),
- [&](const SharedPtr<Process>& process) { return process->process_id == process_id; });
-
- if (itr == process_list.end())
- return nullptr;
-
- return *itr;
-}
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 992689186..1587d40c1 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -19,6 +19,8 @@
namespace Kernel {
+class KernelCore;
+
struct AddressMapping {
// Address and size must be page-aligned
VAddr address;
@@ -62,7 +64,7 @@ struct CodeSet final : public Object {
u32 size = 0;
};
- static SharedPtr<CodeSet> Create(std::string name);
+ static SharedPtr<CodeSet> Create(KernelCore& kernel, std::string name);
std::string GetTypeName() const override {
return "CodeSet";
@@ -109,13 +111,13 @@ struct CodeSet final : public Object {
std::string name;
private:
- CodeSet();
+ explicit CodeSet(KernelCore& kernel);
~CodeSet() override;
};
class Process final : public Object {
public:
- static SharedPtr<Process> Create(std::string&& name);
+ static SharedPtr<Process> Create(KernelCore& kernel, std::string&& name);
std::string GetTypeName() const override {
return "Process";
@@ -129,8 +131,6 @@ public:
return HANDLE_TYPE;
}
- static u32 next_process_id;
-
/// Title ID corresponding to the process
u64 program_id;
@@ -157,8 +157,8 @@ public:
/// Current status of the process
ProcessStatus status;
- /// The id of this process
- u32 process_id = next_process_id++;
+ /// The ID of this process
+ u32 process_id = 0;
/**
* Parses a list of kernel capability descriptors (as found in the ExHeader) and applies them
@@ -206,13 +206,8 @@ public:
ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size);
private:
- Process();
+ explicit Process(KernelCore& kernel);
~Process() override;
};
-void ClearProcessList();
-
-/// Retrieves a process from the current list of processes.
-SharedPtr<Process> GetProcessById(u32 process_id);
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/resource_limit.cpp b/src/core/hle/kernel/resource_limit.cpp
index 17a3e8a74..b253a680f 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -9,31 +9,16 @@
namespace Kernel {
-static SharedPtr<ResourceLimit> resource_limits[4];
+ResourceLimit::ResourceLimit(KernelCore& kernel) : Object{kernel} {}
+ResourceLimit::~ResourceLimit() = default;
-ResourceLimit::ResourceLimit() {}
-ResourceLimit::~ResourceLimit() {}
-
-SharedPtr<ResourceLimit> ResourceLimit::Create(std::string name) {
- SharedPtr<ResourceLimit> resource_limit(new ResourceLimit);
+SharedPtr<ResourceLimit> ResourceLimit::Create(KernelCore& kernel, std::string name) {
+ SharedPtr<ResourceLimit> resource_limit(new ResourceLimit(kernel));
resource_limit->name = std::move(name);
return resource_limit;
}
-SharedPtr<ResourceLimit> ResourceLimit::GetForCategory(ResourceLimitCategory category) {
- switch (category) {
- case ResourceLimitCategory::APPLICATION:
- case ResourceLimitCategory::SYS_APPLET:
- case ResourceLimitCategory::LIB_APPLET:
- case ResourceLimitCategory::OTHER:
- return resource_limits[static_cast<u8>(category)];
- default:
- LOG_CRITICAL(Kernel, "Unknown resource limit category");
- UNREACHABLE();
- }
-}
-
s32 ResourceLimit::GetCurrentResourceValue(ResourceType resource) const {
switch (resource) {
case ResourceType::Commit:
@@ -89,66 +74,4 @@ u32 ResourceLimit::GetMaxResourceValue(ResourceType resource) const {
return 0;
}
}
-
-void ResourceLimitsInit() {
- // Create the four resource limits that the system uses
- // Create the APPLICATION resource limit
- SharedPtr<ResourceLimit> resource_limit = ResourceLimit::Create("Applications");
- resource_limit->max_priority = 0x18;
- resource_limit->max_commit = 0x4000000;
- resource_limit->max_threads = 0x20;
- resource_limit->max_events = 0x20;
- resource_limit->max_mutexes = 0x20;
- resource_limit->max_semaphores = 0x8;
- resource_limit->max_timers = 0x8;
- resource_limit->max_shared_mems = 0x10;
- resource_limit->max_address_arbiters = 0x2;
- resource_limit->max_cpu_time = 0x1E;
- resource_limits[static_cast<u8>(ResourceLimitCategory::APPLICATION)] = resource_limit;
-
- // Create the SYS_APPLET resource limit
- resource_limit = ResourceLimit::Create("System Applets");
- resource_limit->max_priority = 0x4;
- resource_limit->max_commit = 0x5E00000;
- resource_limit->max_threads = 0x1D;
- resource_limit->max_events = 0xB;
- resource_limit->max_mutexes = 0x8;
- resource_limit->max_semaphores = 0x4;
- resource_limit->max_timers = 0x4;
- resource_limit->max_shared_mems = 0x8;
- resource_limit->max_address_arbiters = 0x3;
- resource_limit->max_cpu_time = 0x2710;
- resource_limits[static_cast<u8>(ResourceLimitCategory::SYS_APPLET)] = resource_limit;
-
- // Create the LIB_APPLET resource limit
- resource_limit = ResourceLimit::Create("Library Applets");
- resource_limit->max_priority = 0x4;
- resource_limit->max_commit = 0x600000;
- resource_limit->max_threads = 0xE;
- resource_limit->max_events = 0x8;
- resource_limit->max_mutexes = 0x8;
- resource_limit->max_semaphores = 0x4;
- resource_limit->max_timers = 0x4;
- resource_limit->max_shared_mems = 0x8;
- resource_limit->max_address_arbiters = 0x1;
- resource_limit->max_cpu_time = 0x2710;
- resource_limits[static_cast<u8>(ResourceLimitCategory::LIB_APPLET)] = resource_limit;
-
- // Create the OTHER resource limit
- resource_limit = ResourceLimit::Create("Others");
- resource_limit->max_priority = 0x4;
- resource_limit->max_commit = 0x2180000;
- resource_limit->max_threads = 0xE1;
- resource_limit->max_events = 0x108;
- resource_limit->max_mutexes = 0x25;
- resource_limit->max_semaphores = 0x43;
- resource_limit->max_timers = 0x2C;
- resource_limit->max_shared_mems = 0x1F;
- resource_limit->max_address_arbiters = 0x2D;
- resource_limit->max_cpu_time = 0x3E8;
- resource_limits[static_cast<u8>(ResourceLimitCategory::OTHER)] = resource_limit;
-}
-
-void ResourceLimitsShutdown() {}
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/resource_limit.h b/src/core/hle/kernel/resource_limit.h
index 0fa141db3..219e49562 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -9,6 +9,8 @@
namespace Kernel {
+class KernelCore;
+
enum class ResourceLimitCategory : u8 {
APPLICATION = 0,
SYS_APPLET = 1,
@@ -34,14 +36,7 @@ public:
/**
* Creates a resource limit object.
*/
- static SharedPtr<ResourceLimit> Create(std::string name = "Unknown");
-
- /**
- * Retrieves the resource limit associated with the specified resource limit category.
- * @param category The resource limit category
- * @returns The resource limit associated with the category
- */
- static SharedPtr<ResourceLimit> GetForCategory(ResourceLimitCategory category);
+ static SharedPtr<ResourceLimit> Create(KernelCore& kernel, std::string name = "Unknown");
std::string GetTypeName() const override {
return "ResourceLimit";
@@ -113,14 +108,8 @@ public:
s32 current_cpu_time = 0;
private:
- ResourceLimit();
+ explicit ResourceLimit(KernelCore& kernel);
~ResourceLimit() override;
};
-/// Initializes the resource limits
-void ResourceLimitsInit();
-
-// Destroys the resource limits
-void ResourceLimitsShutdown();
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/server_port.cpp b/src/core/hle/kernel/server_port.cpp
index 7b6211fd8..3792e3e18 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -13,8 +13,8 @@
namespace Kernel {
-ServerPort::ServerPort() {}
-ServerPort::~ServerPort() {}
+ServerPort::ServerPort(KernelCore& kernel) : WaitObject{kernel} {}
+ServerPort::~ServerPort() = default;
ResultVal<SharedPtr<ServerSession>> ServerPort::Accept() {
if (pending_sessions.empty()) {
@@ -36,10 +36,10 @@ void ServerPort::Acquire(Thread* thread) {
}
std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> ServerPort::CreatePortPair(
- u32 max_sessions, std::string name) {
+ KernelCore& kernel, u32 max_sessions, std::string name) {
- SharedPtr<ServerPort> server_port(new ServerPort);
- SharedPtr<ClientPort> client_port(new ClientPort);
+ SharedPtr<ServerPort> server_port(new ServerPort(kernel));
+ SharedPtr<ClientPort> client_port(new ClientPort(kernel));
server_port->name = name + "_Server";
client_port->name = name + "_Client";
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index 7f6d6b3eb..62fb51349 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -15,6 +15,7 @@
namespace Kernel {
class ClientPort;
+class KernelCore;
class ServerSession;
class SessionRequestHandler;
@@ -23,12 +24,13 @@ public:
/**
* Creates a pair of ServerPort and an associated ClientPort.
*
+ * @param kernel The kernel instance to create the port pair under.
* @param max_sessions Maximum number of sessions to the port
* @param name Optional name of the ports
* @return The created port tuple
*/
static std::tuple<SharedPtr<ServerPort>, SharedPtr<ClientPort>> CreatePortPair(
- u32 max_sessions, std::string name = "UnknownPort");
+ KernelCore& kernel, u32 max_sessions, std::string name = "UnknownPort");
std::string GetTypeName() const override {
return "ServerPort";
@@ -69,7 +71,7 @@ public:
void Acquire(Thread* thread) override;
private:
- ServerPort();
+ explicit ServerPort(KernelCore& kernel);
~ServerPort() override;
};
diff --git a/src/core/hle/kernel/server_session.cpp b/src/core/hle/kernel/server_session.cpp
index 51a1ec160..90c9a5aff 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -20,7 +20,7 @@
namespace Kernel {
-ServerSession::ServerSession() = default;
+ServerSession::ServerSession(KernelCore& kernel) : WaitObject{kernel} {}
ServerSession::~ServerSession() {
// This destructor will be called automatically when the last ServerSession handle is closed by
// the emulated application.
@@ -35,8 +35,8 @@ ServerSession::~ServerSession() {
parent->server = nullptr;
}
-ResultVal<SharedPtr<ServerSession>> ServerSession::Create(std::string name) {
- SharedPtr<ServerSession> server_session(new ServerSession);
+ResultVal<SharedPtr<ServerSession>> ServerSession::Create(KernelCore& kernel, std::string name) {
+ SharedPtr<ServerSession> server_session(new ServerSession(kernel));
server_session->name = std::move(name);
server_session->parent = nullptr;
@@ -105,10 +105,10 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
// from its ClientSession, so wake up any threads that may be waiting on a svcReplyAndReceive or
// similar.
+ auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
Kernel::HLERequestContext context(this);
u32* cmd_buf = (u32*)Memory::GetPointer(thread->GetTLSAddress());
- context.PopulateFromIncomingCommandBuffer(cmd_buf, *Core::CurrentProcess(),
- Kernel::g_handle_table);
+ context.PopulateFromIncomingCommandBuffer(cmd_buf, *Core::CurrentProcess(), handle_table);
ResultCode result = RESULT_SUCCESS;
// If the session has been converted to a domain, handle the domain request
@@ -160,10 +160,11 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
return result;
}
-ServerSession::SessionPair ServerSession::CreateSessionPair(const std::string& name,
+ServerSession::SessionPair ServerSession::CreateSessionPair(KernelCore& kernel,
+ const std::string& name,
SharedPtr<ClientPort> port) {
- auto server_session = ServerSession::Create(name + "_Server").Unwrap();
- SharedPtr<ClientSession> client_session(new ClientSession);
+ auto server_session = ServerSession::Create(kernel, name + "_Server").Unwrap();
+ SharedPtr<ClientSession> client_session(new ClientSession(kernel));
client_session->name = name + "_Client";
std::shared_ptr<Session> parent(new Session);
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index 1a88e66b9..e068db2bf 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -15,13 +15,14 @@
namespace Kernel {
-class ClientSession;
class ClientPort;
+class ClientSession;
+class HLERequestContext;
+class KernelCore;
class ServerSession;
class Session;
class SessionRequestHandler;
class Thread;
-class HLERequestContext;
/**
* Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS
@@ -50,11 +51,12 @@ public:
/**
* Creates a pair of ServerSession and an associated ClientSession.
+ * @param kernel The kernal instance to create the session pair under.
* @param name Optional name of the ports.
* @param client_port Optional The ClientPort that spawned this session.
* @return The created session tuple
*/
- static SessionPair CreateSessionPair(const std::string& name = "Unknown",
+ static SessionPair CreateSessionPair(KernelCore& kernel, const std::string& name = "Unknown",
SharedPtr<ClientPort> client_port = nullptr);
/**
@@ -111,16 +113,18 @@ public:
}
private:
- ServerSession();
+ explicit ServerSession(KernelCore& kernel);
~ServerSession() override;
/**
* Creates a server session. The server session can have an optional HLE handler,
* which will be invoked to handle the IPC requests that this session receives.
+ * @param kernel The kernel instance to create this server session under.
* @param name Optional name of the server session.
* @return The created server session
*/
- static ResultVal<SharedPtr<ServerSession>> Create(std::string name = "Unknown");
+ static ResultVal<SharedPtr<ServerSession>> Create(KernelCore& kernel,
+ std::string name = "Unknown");
/// Handles a SyncRequest to a domain, forwarding the request to the proper object or closing an
/// object handle.
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index fc168d2b5..abb1d09cd 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -13,14 +13,14 @@
namespace Kernel {
-SharedMemory::SharedMemory() {}
-SharedMemory::~SharedMemory() {}
+SharedMemory::SharedMemory(KernelCore& kernel) : Object{kernel} {}
+SharedMemory::~SharedMemory() = default;
-SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u64 size,
- MemoryPermission permissions,
+SharedPtr<SharedMemory> SharedMemory::Create(KernelCore& kernel, SharedPtr<Process> owner_process,
+ u64 size, MemoryPermission permissions,
MemoryPermission other_permissions, VAddr address,
MemoryRegion region, std::string name) {
- SharedPtr<SharedMemory> shared_memory(new SharedMemory);
+ SharedPtr<SharedMemory> shared_memory(new SharedMemory(kernel));
shared_memory->owner_process = std::move(owner_process);
shared_memory->name = std::move(name);
@@ -59,12 +59,10 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
return shared_memory;
}
-SharedPtr<SharedMemory> SharedMemory::CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
- u32 offset, u32 size,
- MemoryPermission permissions,
- MemoryPermission other_permissions,
- std::string name) {
- SharedPtr<SharedMemory> shared_memory(new SharedMemory);
+SharedPtr<SharedMemory> SharedMemory::CreateForApplet(
+ KernelCore& kernel, std::shared_ptr<std::vector<u8>> heap_block, u32 offset, u32 size,
+ MemoryPermission permissions, MemoryPermission other_permissions, std::string name) {
+ SharedPtr<SharedMemory> shared_memory(new SharedMemory(kernel));
shared_memory->owner_process = nullptr;
shared_memory->name = std::move(name);
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index c50fee615..2c729afe3 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -15,6 +15,8 @@
namespace Kernel {
+class KernelCore;
+
/// Permissions for mapped shared memory blocks
enum class MemoryPermission : u32 {
None = 0,
@@ -32,6 +34,7 @@ class SharedMemory final : public Object {
public:
/**
* Creates a shared memory object.
+ * @param kernel The kernel instance to create a shared memory instance under.
* @param owner_process Process that created this shared memory object.
* @param size Size of the memory block. Must be page-aligned.
* @param permissions Permission restrictions applied to the process which created the block.
@@ -42,14 +45,15 @@ public:
* linear heap.
* @param name Optional object name, used for debugging purposes.
*/
- static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u64 size,
- MemoryPermission permissions,
+ static SharedPtr<SharedMemory> Create(KernelCore& kernel, SharedPtr<Process> owner_process,
+ u64 size, MemoryPermission permissions,
MemoryPermission other_permissions, VAddr address = 0,
MemoryRegion region = MemoryRegion::BASE,
std::string name = "Unknown");
/**
* Creates a shared memory object from a block of memory managed by an HLE applet.
+ * @param kernel The kernel instance to create a shared memory instance under.
* @param heap_block Heap block of the HLE applet.
* @param offset The offset into the heap block that the SharedMemory will map.
* @param size Size of the memory block. Must be page-aligned.
@@ -58,7 +62,8 @@ public:
* block.
* @param name Optional object name, used for debugging purposes.
*/
- static SharedPtr<SharedMemory> CreateForApplet(std::shared_ptr<std::vector<u8>> heap_block,
+ static SharedPtr<SharedMemory> CreateForApplet(KernelCore& kernel,
+ std::shared_ptr<std::vector<u8>> heap_block,
u32 offset, u32 size,
MemoryPermission permissions,
MemoryPermission other_permissions,
@@ -125,7 +130,7 @@ public:
std::string name;
private:
- SharedMemory();
+ explicit SharedMemory(KernelCore& kernel);
~SharedMemory() override;
};
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index cb6253398..099d1053f 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -87,13 +87,15 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
CASCADE_RESULT(client_session, client_port->Connect());
// Return the client session
- CASCADE_RESULT(*out_handle, g_handle_table.Create(client_session));
+ auto& kernel = Core::System::GetInstance().Kernel();
+ CASCADE_RESULT(*out_handle, kernel.HandleTable().Create(client_session));
return RESULT_SUCCESS;
}
/// Makes a blocking IPC call to an OS service.
static ResultCode SendSyncRequest(Handle handle) {
- SharedPtr<ClientSession> session = g_handle_table.Get<ClientSession>(handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ SharedPtr<ClientSession> session = kernel.HandleTable().Get<ClientSession>(handle);
if (!session) {
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);
return ERR_INVALID_HANDLE;
@@ -112,7 +114,8 @@ static ResultCode SendSyncRequest(Handle handle) {
static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
- const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
@@ -125,7 +128,8 @@ static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
- const SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ const SharedPtr<Process> process = kernel.HandleTable().Get<Process>(process_handle);
if (!process) {
return ERR_INVALID_HANDLE;
}
@@ -168,10 +172,11 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
using ObjectPtr = SharedPtr<WaitObject>;
std::vector<ObjectPtr> objects(handle_count);
+ auto& kernel = Core::System::GetInstance().Kernel();
for (u64 i = 0; i < handle_count; ++i) {
const Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
- const auto object = g_handle_table.Get<WaitObject>(handle);
+ const auto object = kernel.HandleTable().Get<WaitObject>(handle);
if (object == nullptr) {
return ERR_INVALID_HANDLE;
@@ -219,7 +224,8 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
static ResultCode CancelSynchronization(Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
- const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
@@ -239,7 +245,9 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
"requesting_current_thread_handle=0x{:08X}",
holding_thread_handle, mutex_addr, requesting_thread_handle);
- return Mutex::TryAcquire(mutex_addr, holding_thread_handle, requesting_thread_handle);
+ auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
+ return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle,
+ requesting_thread_handle);
}
/// Unlock a mutex
@@ -352,7 +360,8 @@ static ResultCode GetThreadContext(Handle handle, VAddr addr) {
/// Gets the priority for the specified thread
static ResultCode GetThreadPriority(u32* priority, Handle handle) {
- const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);
if (!thread)
return ERR_INVALID_HANDLE;
@@ -366,7 +375,8 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
return ERR_OUT_OF_RANGE;
}
- SharedPtr<Thread> thread = g_handle_table.Get<Thread>(handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);
if (!thread)
return ERR_INVALID_HANDLE;
@@ -395,7 +405,8 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
"called, shared_memory_handle=0x{:X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
shared_memory_handle, addr, size, permissions);
- SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
if (!shared_memory) {
return ERR_INVALID_HANDLE;
}
@@ -423,7 +434,8 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
LOG_WARNING(Kernel_SVC, "called, shared_memory_handle=0x{:08X}, addr=0x{:X}, size=0x{:X}",
shared_memory_handle, addr, size);
- SharedPtr<SharedMemory> shared_memory = g_handle_table.Get<SharedMemory>(shared_memory_handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
return shared_memory->Unmap(Core::CurrentProcess().get(), addr);
}
@@ -431,7 +443,9 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
/// Query process memory
static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_info*/,
Handle process_handle, u64 addr) {
- SharedPtr<Process> process = g_handle_table.Get<Process>(process_handle);
+
+ auto& kernel = Core::System::GetInstance().Kernel();
+ SharedPtr<Process> process = kernel.HandleTable().Get<Process>(process_handle);
if (!process) {
return ERR_INVALID_HANDLE;
}
@@ -528,10 +542,11 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
break;
}
+ auto& kernel = Core::System::GetInstance().Kernel();
CASCADE_RESULT(SharedPtr<Thread> thread,
- Thread::Create(name, entry_point, priority, arg, processor_id, stack_top,
+ Thread::Create(kernel, name, entry_point, priority, arg, processor_id, stack_top,
Core::CurrentProcess()));
- CASCADE_RESULT(thread->guest_handle, g_handle_table.Create(thread));
+ CASCADE_RESULT(thread->guest_handle, kernel.HandleTable().Create(thread));
*out_handle = thread->guest_handle;
Core::System::GetInstance().CpuCore(thread->processor_id).PrepareReschedule();
@@ -548,7 +563,8 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
static ResultCode StartThread(Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
- const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
@@ -595,7 +611,8 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
"called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}",
mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
- SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
ASSERT(thread);
CASCADE_CODE(Mutex::Release(mutex_addr));
@@ -704,8 +721,9 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
mutex_val | Mutex::MutexHasWaitersFlag));
// The mutex is already owned by some other thread, make this thread wait on it.
+ auto& kernel = Core::System::GetInstance().Kernel();
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
- auto owner = g_handle_table.Get<Thread>(owner_handle);
+ auto owner = kernel.HandleTable().Get<Thread>(owner_handle);
ASSERT(owner);
ASSERT(thread->status == ThreadStatus::WaitMutex);
thread->wakeup_callback = nullptr;
@@ -783,14 +801,20 @@ static u64 GetSystemTick() {
/// Close a handle
static ResultCode CloseHandle(Handle handle) {
LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
- return g_handle_table.Close(handle);
+
+ auto& kernel = Core::System::GetInstance().Kernel();
+ return kernel.HandleTable().Close(handle);
}
/// Reset an event
static ResultCode ResetSignal(Handle handle) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x{:08X}", handle);
- auto event = g_handle_table.Get<Event>(handle);
+
+ auto& kernel = Core::System::GetInstance().Kernel();
+ auto event = kernel.HandleTable().Get<Event>(handle);
+
ASSERT(event != nullptr);
+
event->Clear();
return RESULT_SUCCESS;
}
@@ -806,7 +830,8 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) {
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
- const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
@@ -821,7 +846,8 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:16X}, core=0x{:X}", thread_handle,
mask, core);
- const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
if (!thread) {
return ERR_INVALID_HANDLE;
}
@@ -861,19 +887,23 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
u32 remote_permissions) {
LOG_TRACE(Kernel_SVC, "called, size=0x{:X}, localPerms=0x{:08X}, remotePerms=0x{:08X}", size,
local_permissions, remote_permissions);
- auto sharedMemHandle =
- SharedMemory::Create(g_handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
+
+ auto& kernel = Core::System::GetInstance().Kernel();
+ auto& handle_table = kernel.HandleTable();
+ auto shared_mem_handle =
+ SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
static_cast<MemoryPermission>(local_permissions),
static_cast<MemoryPermission>(remote_permissions));
- CASCADE_RESULT(*handle, g_handle_table.Create(sharedMemHandle));
+ CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle));
return RESULT_SUCCESS;
}
static ResultCode ClearEvent(Handle handle) {
LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
- SharedPtr<Event> evt = g_handle_table.Get<Event>(handle);
+ auto& kernel = Core::System::GetInstance().Kernel();
+ SharedPtr<Event> evt = kernel.HandleTable().Get<Event>(handle);
if (evt == nullptr)
return ERR_INVALID_HANDLE;
evt->Clear();
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 4ffd8d5cc..520ea0853 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -20,6 +20,7 @@
#include "core/core_timing_util.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
+#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/thread.h"
@@ -29,9 +30,6 @@
namespace Kernel {
-/// Event type for the thread wake up event
-static CoreTiming::EventType* ThreadWakeupEventType = nullptr;
-
bool Thread::ShouldWait(Thread* thread) const {
return status != ThreadStatus::Dead;
}
@@ -40,32 +38,17 @@ void Thread::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
}
-// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
-// us to simply use a pool index or similar.
-static Kernel::HandleTable wakeup_callback_handle_table;
-
-// The first available thread id at startup
-static u32 next_thread_id;
-
-/**
- * Creates a new thread ID
- * @return The new thread ID
- */
-inline static u32 const NewThreadId() {
- return next_thread_id++;
-}
-
-Thread::Thread() {}
-Thread::~Thread() {}
+Thread::Thread(KernelCore& kernel) : WaitObject{kernel} {}
+Thread::~Thread() = default;
void Thread::Stop() {
// Cancel any outstanding wakeup events for this thread
- CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
- wakeup_callback_handle_table.Close(callback_handle);
+ CoreTiming::UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), callback_handle);
+ kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle);
callback_handle = 0;
// Clean up thread from ready queue
- // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
+ // This is only needed when the thread is terminated forcefully (SVC TerminateProcess)
if (status == ThreadStatus::Ready) {
scheduler->UnscheduleThread(this, current_priority);
}
@@ -98,63 +81,6 @@ void ExitCurrentThread() {
Core::System::GetInstance().CurrentScheduler().RemoveThread(thread);
}
-/**
- * Callback that will wake up the thread it was scheduled for
- * @param thread_handle The handle of the thread that's been awoken
- * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
- */
-static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
- const auto proper_handle = static_cast<Handle>(thread_handle);
-
- // Lock the global kernel mutex when we enter the kernel HLE.
- std::lock_guard<std::recursive_mutex> lock(HLE::g_hle_lock);
-
- SharedPtr<Thread> thread = wakeup_callback_handle_table.Get<Thread>(proper_handle);
- if (thread == nullptr) {
- LOG_CRITICAL(Kernel, "Callback fired for invalid thread {:08X}", proper_handle);
- return;
- }
-
- bool resume = true;
-
- if (thread->status == ThreadStatus::WaitSynchAny ||
- thread->status == ThreadStatus::WaitSynchAll ||
- thread->status == ThreadStatus::WaitHLEEvent) {
- // Remove the thread from each of its waiting objects' waitlists
- for (auto& object : thread->wait_objects)
- object->RemoveWaitingThread(thread.get());
- thread->wait_objects.clear();
-
- // Invoke the wakeup callback before clearing the wait objects
- if (thread->wakeup_callback)
- resume = thread->wakeup_callback(ThreadWakeupReason::Timeout, thread, nullptr, 0);
- }
-
- if (thread->mutex_wait_address != 0 || thread->condvar_wait_address != 0 ||
- thread->wait_handle) {
- ASSERT(thread->status == ThreadStatus::WaitMutex);
- thread->mutex_wait_address = 0;
- thread->condvar_wait_address = 0;
- thread->wait_handle = 0;
-
- auto lock_owner = thread->lock_owner;
- // Threads waking up by timeout from WaitProcessWideKey do not perform priority inheritance
- // and don't have a lock owner unless SignalProcessWideKey was called first and the thread
- // wasn't awakened due to the mutex already being acquired.
- if (lock_owner) {
- lock_owner->RemoveMutexWaiter(thread);
- }
- }
-
- if (thread->arb_wait_address != 0) {
- ASSERT(thread->status == ThreadStatus::WaitArb);
- thread->arb_wait_address = 0;
- }
-
- if (resume)
- thread->ResumeFromWait();
-}
-
void Thread::WakeAfterDelay(s64 nanoseconds) {
// Don't schedule a wakeup if the thread wants to wait forever
if (nanoseconds == -1)
@@ -162,12 +88,12 @@ void Thread::WakeAfterDelay(s64 nanoseconds) {
// This function might be called from any thread so we have to be cautious and use the
// thread-safe version of ScheduleEvent.
- CoreTiming::ScheduleEventThreadsafe(CoreTiming::nsToCycles(nanoseconds), ThreadWakeupEventType,
- callback_handle);
+ CoreTiming::ScheduleEventThreadsafe(CoreTiming::nsToCycles(nanoseconds),
+ kernel.ThreadWakeupCallbackEventType(), callback_handle);
}
void Thread::CancelWakeupTimer() {
- CoreTiming::UnscheduleEventThreadsafe(ThreadWakeupEventType, callback_handle);
+ CoreTiming::UnscheduleEventThreadsafe(kernel.ThreadWakeupCallbackEventType(), callback_handle);
}
static boost::optional<s32> GetNextProcessorId(u64 mask) {
@@ -294,9 +220,9 @@ static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAdd
context.fpscr = 0;
}
-ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, u32 priority,
- u64 arg, s32 processor_id, VAddr stack_top,
- SharedPtr<Process> owner_process) {
+ResultVal<SharedPtr<Thread>> Thread::Create(KernelCore& kernel, std::string name, VAddr entry_point,
+ u32 priority, u64 arg, s32 processor_id,
+ VAddr stack_top, SharedPtr<Process> owner_process) {
// Check if priority is in ranged. Lowest priority -> highest priority id.
if (priority > THREADPRIO_LOWEST) {
LOG_ERROR(Kernel_SVC, "Invalid thread priority: {}", priority);
@@ -316,9 +242,9 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
return ResultCode(-1);
}
- SharedPtr<Thread> thread(new Thread);
+ SharedPtr<Thread> thread(new Thread(kernel));
- thread->thread_id = NewThreadId();
+ thread->thread_id = kernel.CreateNewThreadID();
thread->status = ThreadStatus::Dormant;
thread->entry_point = entry_point;
thread->stack_top = stack_top;
@@ -333,7 +259,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
thread->condvar_wait_address = 0;
thread->wait_handle = 0;
thread->name = std::move(name);
- thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
+ thread->callback_handle = kernel.ThreadWakeupCallbackHandleTable().Create(thread).Unwrap();
thread->owner_process = owner_process;
thread->scheduler = Core::System::GetInstance().Scheduler(processor_id);
thread->scheduler->AddThread(thread, priority);
@@ -383,19 +309,19 @@ void Thread::BoostPriority(u32 priority) {
current_priority = priority;
}
-SharedPtr<Thread> SetupMainThread(VAddr entry_point, u32 priority,
+SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority,
SharedPtr<Process> owner_process) {
// Setup page table so we can write to memory
SetCurrentPageTable(&Core::CurrentProcess()->vm_manager.page_table);
// Initialize new "main" thread
- auto thread_res = Thread::Create("main", entry_point, priority, 0, THREADPROCESSORID_0,
+ auto thread_res = Thread::Create(kernel, "main", entry_point, priority, 0, THREADPROCESSORID_0,
Memory::STACK_AREA_VADDR_END, std::move(owner_process));
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
// Register 1 must be a handle to the main thread
- thread->guest_handle = Kernel::g_handle_table.Create(thread).Unwrap();
+ thread->guest_handle = kernel.HandleTable().Create(thread).Unwrap();
thread->context.cpu_registers[1] = thread->guest_handle;
@@ -528,13 +454,4 @@ Thread* GetCurrentThread() {
return Core::System::GetInstance().CurrentScheduler().GetCurrentThread();
}
-void ThreadingInit() {
- ThreadWakeupEventType = CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
- next_thread_id = 1;
-}
-
-void ThreadingShutdown() {
- Kernel::ClearProcessList();
-}
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 06edc296d..20f50458b 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -56,6 +56,7 @@ enum class ThreadWakeupReason {
namespace Kernel {
+class KernelCore;
class Process;
class Scheduler;
@@ -63,6 +64,7 @@ class Thread final : public WaitObject {
public:
/**
* Creates and returns a new thread. The new thread is immediately scheduled
+ * @param kernel The kernel instance this thread will be created under.
* @param name The friendly name desired for the thread
* @param entry_point The address at which the thread should start execution
* @param priority The thread's priority
@@ -72,8 +74,9 @@ public:
* @param owner_process The parent process for the thread
* @return A shared pointer to the newly created thread
*/
- static ResultVal<SharedPtr<Thread>> Create(std::string name, VAddr entry_point, u32 priority,
- u64 arg, s32 processor_id, VAddr stack_top,
+ static ResultVal<SharedPtr<Thread>> Create(KernelCore& kernel, std::string name,
+ VAddr entry_point, u32 priority, u64 arg,
+ s32 processor_id, VAddr stack_top,
SharedPtr<Process> owner_process);
std::string GetName() const override {
@@ -263,7 +266,7 @@ public:
u64 affinity_mask{0x1};
private:
- Thread();
+ explicit Thread(KernelCore& kernel);
~Thread() override;
std::shared_ptr<std::vector<u8>> tls_memory = std::make_shared<std::vector<u8>>();
@@ -271,12 +274,13 @@ private:
/**
* Sets up the primary application thread
+ * @param kernel The kernel instance to create the main thread under.
* @param entry_point The address at which the thread should start execution
* @param priority The priority to give the main thread
* @param owner_process The parent process for the main thread
* @return A shared pointer to the main thread
*/
-SharedPtr<Thread> SetupMainThread(VAddr entry_point, u32 priority,
+SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 priority,
SharedPtr<Process> owner_process);
/**
@@ -294,14 +298,4 @@ void WaitCurrentThread_Sleep();
*/
void ExitCurrentThread();
-/**
- * Initialize threading
- */
-void ThreadingInit();
-
-/**
- * Shutdown threading
- */
-void ThreadingShutdown();
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
index 282360745..6957b16e0 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -2,36 +2,31 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <cinttypes>
#include "common/assert.h"
#include "common/logging/log.h"
+#include "core/core.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/hle/kernel/handle_table.h"
+#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/kernel/timer.h"
namespace Kernel {
-/// The event type of the generic timer callback event
-static CoreTiming::EventType* timer_callback_event_type = nullptr;
-// TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future, allowing
-// us to simply use a pool index or similar.
-static Kernel::HandleTable timer_callback_handle_table;
+Timer::Timer(KernelCore& kernel) : WaitObject{kernel} {}
+Timer::~Timer() = default;
-Timer::Timer() {}
-Timer::~Timer() {}
-
-SharedPtr<Timer> Timer::Create(ResetType reset_type, std::string name) {
- SharedPtr<Timer> timer(new Timer);
+SharedPtr<Timer> Timer::Create(KernelCore& kernel, ResetType reset_type, std::string name) {
+ SharedPtr<Timer> timer(new Timer(kernel));
timer->reset_type = reset_type;
timer->signaled = false;
timer->name = std::move(name);
timer->initial_delay = 0;
timer->interval_delay = 0;
- timer->callback_handle = timer_callback_handle_table.Create(timer).Unwrap();
+ timer->callback_handle = kernel.CreateTimerCallbackHandle(timer).Unwrap();
return timer;
}
@@ -58,13 +53,13 @@ void Timer::Set(s64 initial, s64 interval) {
// Immediately invoke the callback
Signal(0);
} else {
- CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(initial), timer_callback_event_type,
+ CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(initial), kernel.TimerCallbackEventType(),
callback_handle);
}
}
void Timer::Cancel() {
- CoreTiming::UnscheduleEvent(timer_callback_event_type, callback_handle);
+ CoreTiming::UnscheduleEvent(kernel.TimerCallbackEventType(), callback_handle);
}
void Timer::Clear() {
@@ -89,28 +84,8 @@ void Timer::Signal(int cycles_late) {
if (interval_delay != 0) {
// Reschedule the timer with the interval delay
CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(interval_delay) - cycles_late,
- timer_callback_event_type, callback_handle);
+ kernel.TimerCallbackEventType(), callback_handle);
}
}
-/// The timer callback event, called when a timer is fired
-static void TimerCallback(u64 timer_handle, int cycles_late) {
- SharedPtr<Timer> timer =
- timer_callback_handle_table.Get<Timer>(static_cast<Handle>(timer_handle));
-
- if (timer == nullptr) {
- LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016X}", timer_handle);
- return;
- }
-
- timer->Signal(cycles_late);
-}
-
-void TimersInit() {
- timer_callback_handle_table.Clear();
- timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
-}
-
-void TimersShutdown() {}
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index 4dddc67e0..12915c1b1 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -10,15 +10,19 @@
namespace Kernel {
+class KernelCore;
+
class Timer final : public WaitObject {
public:
/**
* Creates a timer
+ * @param kernel The kernel instance to create the timer callback handle for.
* @param reset_type ResetType describing how to create the timer
* @param name Optional name of timer
* @return The created Timer
*/
- static SharedPtr<Timer> Create(ResetType reset_type, std::string name = "Unknown");
+ static SharedPtr<Timer> Create(KernelCore& kernel, ResetType reset_type,
+ std::string name = "Unknown");
std::string GetTypeName() const override {
return "Timer";
@@ -68,7 +72,7 @@ public:
void Signal(int cycles_late);
private:
- Timer();
+ explicit Timer(KernelCore& kernel);
~Timer() override;
ResetType reset_type; ///< The ResetType of this timer
@@ -83,9 +87,4 @@ private:
Handle callback_handle;
};
-/// Initializes the required variables for timers
-void TimersInit();
-/// Tears down the timer variables
-void TimersShutdown();
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
index 7681cdee7..eef00b729 100644
--- a/src/core/hle/kernel/wait_object.cpp
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -12,6 +12,9 @@
namespace Kernel {
+WaitObject::WaitObject(KernelCore& kernel) : Object{kernel} {}
+WaitObject::~WaitObject() = default;
+
void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
if (itr == waiting_threads.end())
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h
index b5fbc647b..0bd97133c 100644
--- a/src/core/hle/kernel/wait_object.h
+++ b/src/core/hle/kernel/wait_object.h
@@ -11,11 +11,15 @@
namespace Kernel {
+class KernelCore;
class Thread;
/// Class that represents a Kernel object that a thread can be waiting on
class WaitObject : public Object {
public:
+ explicit WaitObject(KernelCore& kernel);
+ ~WaitObject() override;
+
/**
* Check if the specified thread should wait until the object is available
* @param thread The thread about which we're deciding.