aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLioncash <mathew1800@gmail.com>2018-08-28 12:30:33 -0400
committerLioncash <mathew1800@gmail.com>2018-08-28 22:31:51 -0400
commit0cbcd6ec9aeeafc298fe2e6e4ac10d68bb7267c5 (patch)
tree2d7bb143d490c3984bff6deda426b818bf27d552 /src
parent4d7e1662c84ef65f7da5a27b0473125cc6759d5c (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/core/core.cpp16
-rw-r--r--src/core/core.h8
-rw-r--r--src/core/hle/ipc_helpers.h5
-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
-rw-r--r--src/core/hle/service/am/am.cpp9
-rw-r--r--src/core/hle/service/audio/audout_u.cpp4
-rw-r--r--src/core/hle/service/audio/audren_u.cpp8
-rw-r--r--src/core/hle/service/hid/hid.cpp9
-rw-r--r--src/core/hle/service/nfp/nfp.cpp10
-rw-r--r--src/core/hle/service/nifm/nifm.cpp6
-rw-r--r--src/core/hle/service/ns/pl_u.cpp3
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp4
-rw-r--r--src/core/hle/service/nvflinger/buffer_queue.cpp4
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp3
-rw-r--r--src/core/hle/service/service.cpp9
-rw-r--r--src/core/hle/service/sm/sm.cpp5
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp4
-rw-r--r--src/core/loader/elf.cpp7
-rw-r--r--src/core/loader/nro.cpp6
-rw-r--r--src/core/loader/nso.cpp6
-rw-r--r--src/tests/core/arm/arm_test_common.cpp2
-rw-r--r--src/tests/core/arm/arm_test_common.h2
-rw-r--r--src/yuzu/debugger/wait_tree.cpp4
54 files changed, 671 insertions, 442 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 07da4c4937..2293669e5b 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -171,6 +171,14 @@ const std::shared_ptr<Kernel::Scheduler>& System::Scheduler(size_t core_index) {
return cpu_cores[core_index]->Scheduler();
}
+Kernel::KernelCore& System::Kernel() {
+ return kernel;
+}
+
+const Kernel::KernelCore& System::Kernel() const {
+ return kernel;
+}
+
ARM_Interface& System::ArmInterface(size_t core_index) {
ASSERT(core_index < NUM_CPU_CORES);
return cpu_cores[core_index]->ArmInterface();
@@ -185,12 +193,13 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
LOG_DEBUG(HW_Memory, "initialized OK");
CoreTiming::Init();
+ kernel.Initialize();
// Create a default fs if one doesn't already exist.
if (virtual_filesystem == nullptr)
virtual_filesystem = std::make_shared<FileSys::RealVfsFilesystem>();
- current_process = Kernel::Process::Create("main");
+ current_process = Kernel::Process::Create(kernel, "main");
cpu_barrier = std::make_shared<CpuBarrier>();
cpu_exclusive_monitor = Cpu::MakeExclusiveMonitor(cpu_cores.size());
@@ -201,7 +210,6 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window) {
telemetry_session = std::make_unique<Core::TelemetrySession>();
service_manager = std::make_shared<Service::SM::ServiceManager>();
- Kernel::Init();
Service::Init(service_manager, virtual_filesystem);
GDBStub::Init();
@@ -246,7 +254,6 @@ void System::Shutdown() {
renderer.reset();
GDBStub::Shutdown();
Service::Shutdown();
- Kernel::Shutdown();
service_manager.reset();
telemetry_session.reset();
gpu_core.reset();
@@ -265,7 +272,8 @@ void System::Shutdown() {
}
cpu_barrier.reset();
- // Close core timing
+ // Shutdown kernel and core timing
+ kernel.Shutdown();
CoreTiming::Shutdown();
// Close app loader
diff --git a/src/core/core.h b/src/core/core.h
index 321104585b..2c18f7193f 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -12,6 +12,7 @@
#include "common/common_types.h"
#include "core/arm/exclusive_monitor.h"
#include "core/core_cpu.h"
+#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/scheduler.h"
#include "core/loader/loader.h"
@@ -188,6 +189,12 @@ public:
return current_process;
}
+ /// Provides a reference to the kernel instance.
+ Kernel::KernelCore& Kernel();
+
+ /// Provides a constant reference to the kernel instance.
+ const Kernel::KernelCore& Kernel() const;
+
/// Gets the name of the current game
Loader::ResultStatus GetGameName(std::string& out) const {
if (app_loader == nullptr)
@@ -246,6 +253,7 @@ private:
*/
ResultStatus Init(Frontend::EmuWindow& emu_window);
+ Kernel::KernelCore kernel;
/// RealVfsFilesystem instance
FileSys::VirtualFilesystem virtual_filesystem;
/// AppLoader used to load the current executing application
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index d3a7348319..0f3ffdb600 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -12,6 +12,7 @@
#include <utility>
#include "common/assert.h"
#include "common/common_types.h"
+#include "core/core.h"
#include "core/hle/ipc.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
@@ -135,7 +136,9 @@ public:
if (context->Session()->IsDomain()) {
context->AddDomainObject(std::move(iface));
} else {
- auto sessions = Kernel::ServerSession::CreateSessionPair(iface->GetServiceName());
+ auto& kernel = Core::System::GetInstance().Kernel();
+ auto sessions =
+ Kernel::ServerSession::CreateSessionPair(kernel, iface->GetServiceName());
auto server = std::get<Kernel::SharedPtr<Kernel::ServerSession>>(sessions);
auto client = std::get<Kernel::SharedPtr<Kernel::ClientSession>>(sessions);
iface->ClientConnected(server);
diff --git a/src/core/hle/kernel/client_port.cpp b/src/core/hle/kernel/client_port.cpp
index 134e41ebc6..873d6c5163 100644
--- a/src/core/hle/kernel/client_port.cpp
+++ b/src/core/hle/kernel/client_port.cpp
@@ -14,7 +14,7 @@
namespace Kernel {
-ClientPort::ClientPort() = default;
+ClientPort::ClientPort(KernelCore& kernel) : Object{kernel} {}
ClientPort::~ClientPort() = default;
ResultVal<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 b1269ea5c6..f3dfebbb18 100644
--- a/src/core/hle/kernel/client_port.h
+++ b/src/core/hle/kernel/client_port.h
@@ -11,8 +11,9 @@
namespace Kernel {
-class ServerPort;
class ClientSession;
+class KernelCore;
+class ServerPort;
class ClientPort final : public Object {
public:
@@ -44,7 +45,7 @@ public:
void ConnectionClosed();
private:
- ClientPort();
+ explicit ClientPort(KernelCore& kernel);
~ClientPort() override;
SharedPtr<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 fdffc648d9..c114eaf994 100644
--- a/src/core/hle/kernel/client_session.cpp
+++ b/src/core/hle/kernel/client_session.cpp
@@ -11,7 +11,7 @@
namespace Kernel {
-ClientSession::ClientSession() = default;
+ClientSession::ClientSession(KernelCore& kernel) : Object{kernel} {}
ClientSession::~ClientSession() {
// This destructor will be called automatically when the last ClientSession handle is closed by
// the emulated application.
diff --git a/src/core/hle/kernel/client_session.h b/src/core/hle/kernel/client_session.h
index dabd93ed7c..439fbdb35e 100644
--- a/src/core/hle/kernel/client_session.h
+++ b/src/core/hle/kernel/client_session.h
@@ -12,8 +12,9 @@
namespace Kernel {
-class ServerSession;
+class KernelCore;
class Session;
+class ServerSession;
class Thread;
class ClientSession final : public Object {
@@ -41,7 +42,7 @@ public:
std::shared_ptr<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 5623c4b6a7..8967e602ea 100644
--- a/src/core/hle/kernel/event.cpp
+++ b/src/core/hle/kernel/event.cpp
@@ -10,11 +10,11 @@
namespace Kernel {
-Event::Event() {}
-Event::~Event() {}
+Event::Event(KernelCore& kernel) : WaitObject{kernel} {}
+Event::~Event() = default;
-SharedPtr<Event> 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 3c20c05e84..27d6126b0a 100644
--- a/src/core/hle/kernel/event.h
+++ b/src/core/hle/kernel/event.h
@@ -10,14 +10,18 @@
namespace Kernel {
+class KernelCore;
+
class Event final : public WaitObject {
public:
/**
* Creates an event
+ * @param kernel The kernel instance to create this event under.
* @param reset_type ResetType describing how to create event
* @param name Optional name of event
*/
- static SharedPtr<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 6d9f7a02bb..3a079b9a97 100644
--- a/src/core/hle/kernel/handle_table.cpp
+++ b/src/core/hle/kernel/handle_table.cpp
@@ -13,8 +13,6 @@
namespace Kernel {
-HandleTable g_handle_table;
-
HandleTable::HandleTable() {
next_generation = 1;
Clear();
diff --git a/src/core/hle/kernel/handle_table.h b/src/core/hle/kernel/handle_table.h
index aee3583e8a..cac928adb8 100644
--- a/src/core/hle/kernel/handle_table.h
+++ b/src/core/hle/kernel/handle_table.h
@@ -121,6 +121,4 @@ private:
u16 next_free_slot;
};
-extern HandleTable g_handle_table;
-
} // namespace Kernel
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 82a3fb5a8e..db7aef7669 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -13,6 +13,7 @@
#include "common/common_funcs.h"
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/handle_table.h"
@@ -51,7 +52,9 @@ SharedPtr<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 8c19e86d3b..615d7901a8 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -2,38 +2,291 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <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 1313114720..089e959ac1 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -4,14 +4,93 @@
#pragma once
-#include "common/common_types.h"
+#include "core/hle/kernel/object.h"
+
+template <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 cb7f58b358..36bf0b677a 100644
--- a/src/core/hle/kernel/mutex.cpp
+++ b/src/core/hle/kernel/mutex.cpp
@@ -58,15 +58,15 @@ static void TransferMutexOwnership(VAddr mutex_addr, SharedPtr<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 45268bbe9b..81e62d4970 100644
--- a/src/core/hle/kernel/mutex.h
+++ b/src/core/hle/kernel/mutex.h
@@ -11,6 +11,7 @@ union ResultCode;
namespace Kernel {
+class HandleTable;
class Thread;
class Mutex final {
@@ -21,8 +22,8 @@ public:
static constexpr u32 MutexOwnerMask = 0xBFFFFFFF;
/// Attempts to acquire a mutex at the specified address.
- static ResultCode TryAcquire(VAddr address, Handle holding_thread_handle,
- Handle requesting_thread_handle);
+ static ResultCode TryAcquire(HandleTable& handle_table, VAddr address,
+ Handle holding_thread_handle, Handle requesting_thread_handle);
/// Releases the mutex at the specified address.
static ResultCode Release(VAddr address);
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index cdba272f57..d51562d92c 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -3,10 +3,12 @@
// Refer to the license.txt file included.
#include "common/assert.h"
+#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
namespace Kernel {
+Object::Object(KernelCore& kernel) : kernel{kernel}, object_id{kernel.CreateNewObjectID()} {}
Object::~Object() = default;
bool Object::IsWaitable() const {
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 526ac9cc3c..b054cbf7d8 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -14,6 +14,8 @@
namespace Kernel {
+class KernelCore;
+
using Handle = u32;
enum class HandleType : u32 {
@@ -40,6 +42,7 @@ enum class ResetType {
class Object : NonCopyable {
public:
+ explicit Object(KernelCore& kernel);
virtual ~Object();
/// Returns a unique identifier for the object. For debugging purposes only.
@@ -61,15 +64,16 @@ public:
*/
bool IsWaitable() const;
-public:
- static std::atomic<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 edf34c5a3b..b025e323ff 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -8,6 +8,7 @@
#include "common/common_funcs.h"
#include "common/logging/log.h"
#include "core/hle/kernel/errors.h"
+#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/thread.h"
@@ -16,30 +17,26 @@
namespace Kernel {
-// Lists all processes that exist in the current session.
-static std::vector<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 9926891864..1587d40c1e 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -19,6 +19,8 @@
namespace Kernel {
+class KernelCore;
+
struct AddressMapping {
// Address and size must be page-aligned
VAddr address;
@@ -62,7 +64,7 @@ struct CodeSet final : public Object {
u32 size = 0;
};
- static SharedPtr<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 17a3e8a747..b253a680f7 100644
--- a/src/core/hle/kernel/resource_limit.cpp
+++ b/src/core/hle/kernel/resource_limit.cpp
@@ -9,31 +9,16 @@
namespace Kernel {
-static SharedPtr<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 0fa141db3a..219e495624 100644
--- a/src/core/hle/kernel/resource_limit.h
+++ b/src/core/hle/kernel/resource_limit.h
@@ -9,6 +9,8 @@
namespace Kernel {
+class KernelCore;
+
enum class ResourceLimitCategory : u8 {
APPLICATION = 0,
SYS_APPLET = 1,
@@ -34,14 +36,7 @@ public:
/**
* Creates a resource limit object.
*/
- static SharedPtr<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 7b6211fd8e..3792e3e186 100644
--- a/src/core/hle/kernel/server_port.cpp
+++ b/src/core/hle/kernel/server_port.cpp
@@ -13,8 +13,8 @@
namespace Kernel {
-ServerPort::ServerPort() {}
-ServerPort::~ServerPort() {}
+ServerPort::ServerPort(KernelCore& kernel) : WaitObject{kernel} {}
+ServerPort::~ServerPort() = default;
ResultVal<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 7f6d6b3eb1..62fb513490 100644
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -15,6 +15,7 @@
namespace Kernel {
class ClientPort;
+class KernelCore;
class ServerSession;
class SessionRequestHandler;
@@ -23,12 +24,13 @@ public:
/**
* Creates a pair of ServerPort and an associated ClientPort.
*
+ * @param kernel The kernel instance to create the port pair under.
* @param max_sessions Maximum number of sessions to the port
* @param name Optional name of the ports
* @return The created port tuple
*/
static std::tuple<SharedPtr<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 51a1ec1605..90c9a5afff 100644
--- a/src/core/hle/kernel/server_session.cpp
+++ b/src/core/hle/kernel/server_session.cpp
@@ -20,7 +20,7 @@
namespace Kernel {
-ServerSession::ServerSession() = default;
+ServerSession::ServerSession(KernelCore& kernel) : WaitObject{kernel} {}
ServerSession::~ServerSession() {
// This destructor will be called automatically when the last ServerSession handle is closed by
// the emulated application.
@@ -35,8 +35,8 @@ ServerSession::~ServerSession() {
parent->server = nullptr;
}
-ResultVal<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 1a88e66b9e..e068db2bf6 100644
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -15,13 +15,14 @@
namespace Kernel {
-class ClientSession;
class ClientPort;
+class ClientSession;
+class HLERequestContext;
+class KernelCore;
class ServerSession;
class Session;
class SessionRequestHandler;
class Thread;
-class HLERequestContext;
/**
* Kernel object representing the server endpoint of an IPC session. Sessions are the basic CTR-OS
@@ -50,11 +51,12 @@ public:
/**
* Creates a pair of ServerSession and an associated ClientSession.
+ * @param kernel The kernal instance to create the session pair under.
* @param name Optional name of the ports.
* @param client_port Optional The ClientPort that spawned this session.
* @return The created session tuple
*/
- static SessionPair CreateSessionPair(const std::string& name = "Unknown",
+ static SessionPair CreateSessionPair(KernelCore& kernel, const std::string& name = "Unknown",
SharedPtr<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 fc168d2b53..abb1d09cd3 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -13,14 +13,14 @@
namespace Kernel {
-SharedMemory::SharedMemory() {}
-SharedMemory::~SharedMemory() {}
+SharedMemory::SharedMemory(KernelCore& kernel) : Object{kernel} {}
+SharedMemory::~SharedMemory() = default;
-SharedPtr<SharedMemory> 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 c50fee615f..2c729afe3f 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -15,6 +15,8 @@
namespace Kernel {
+class KernelCore;
+
/// Permissions for mapped shared memory blocks
enum class MemoryPermission : u32 {
None = 0,
@@ -32,6 +34,7 @@ class SharedMemory final : public Object {
public:
/**
* Creates a shared memory object.
+ * @param kernel The kernel instance to create a shared memory instance under.
* @param owner_process Process that created this shared memory object.
* @param size Size of the memory block. Must be page-aligned.
* @param permissions Permission restrictions applied to the process which created the block.
@@ -42,14 +45,15 @@ public:
* linear heap.
* @param name Optional object name, used for debugging purposes.
*/
- static SharedPtr<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 cb6253398c..099d1053f9 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -87,13 +87,15 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
CASCADE_RESULT(client_session, client_port->Connect());
// Return the client session
- CASCADE_RESULT(*out_handle, g_handle_table.Create(client_session));
+ auto& kernel = Core::System::GetInstance().Kernel();
+ CASCADE_RESULT(*out_handle, kernel.HandleTable().Create(client_session));
return RESULT_SUCCESS;
}
/// Makes a blocking IPC call to an OS service.
static ResultCode SendSyncRequest(Handle handle) {
- SharedPtr<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 4ffd8d5cc6..520ea0853f 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -20,6 +20,7 @@
#include "core/core_timing_util.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
+#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/object.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/thread.h"
@@ -29,9 +30,6 @@
namespace Kernel {
-/// Event type for the thread wake up event
-static CoreTiming::EventType* ThreadWakeupEventType = nullptr;
-
bool Thread::ShouldWait(Thread* thread) const {
return status != ThreadStatus::Dead;
}
@@ -40,32 +38,17 @@ void Thread::Acquire(Thread* thread) {
ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
}
-// TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, allowing
-// us to simply use a pool index or similar.
-static Kernel::HandleTable wakeup_callback_handle_table;
-
-// The first available thread id at startup
-static u32 next_thread_id;
-
-/**
- * Creates a new thread ID
- * @return The new thread ID
- */
-inline static u32 const NewThreadId() {
- return next_thread_id++;
-}
-
-Thread::Thread() {}
-Thread::~Thread() {}
+Thread::Thread(KernelCore& kernel) : WaitObject{kernel} {}
+Thread::~Thread() = default;
void Thread::Stop() {
// Cancel any outstanding wakeup events for this thread
- CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
- wakeup_callback_handle_table.Close(callback_handle);
+ CoreTiming::UnscheduleEvent(kernel.ThreadWakeupCallbackEventType(), callback_handle);
+ kernel.ThreadWakeupCallbackHandleTable().Close(callback_handle);
callback_handle = 0;
// Clean up thread from ready queue
- // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
+ // This is only needed when the thread is terminated forcefully (SVC TerminateProcess)
if (status == ThreadStatus::Ready) {
scheduler->UnscheduleThread(this, current_priority);
}
@@ -98,63 +81,6 @@ void ExitCurrentThread() {
Core::System::GetInstance().CurrentScheduler().RemoveThread(thread);
}
-/**
- * Callback that will wake up the thread it was scheduled for
- * @param thread_handle The handle of the thread that's been awoken
- * @param cycles_late The number of CPU cycles that have passed since the desired wakeup time
- */
-static void ThreadWakeupCallback(u64 thread_handle, int cycles_late) {
- const auto proper_handle = static_cast<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 06edc296d5..20f50458b7 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -56,6 +56,7 @@ enum class ThreadWakeupReason {
namespace Kernel {
+class KernelCore;
class Process;
class Scheduler;
@@ -63,6 +64,7 @@ class Thread final : public WaitObject {
public:
/**
* Creates and returns a new thread. The new thread is immediately scheduled
+ * @param kernel The kernel instance this thread will be created under.
* @param name The friendly name desired for the thread
* @param entry_point The address at which the thread should start execution
* @param priority The thread's priority
@@ -72,8 +74,9 @@ public:
* @param owner_process The parent process for the thread
* @return A shared pointer to the newly created thread
*/
- static ResultVal<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 282360745c..6957b16e03 100644
--- a/src/core/hle/kernel/timer.cpp
+++ b/src/core/hle/kernel/timer.cpp
@@ -2,36 +2,31 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-#include <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 4dddc67e09..12915c1b11 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -10,15 +10,19 @@
namespace Kernel {
+class KernelCore;
+
class Timer final : public WaitObject {
public:
/**
* Creates a timer
+ * @param kernel The kernel instance to create the timer callback handle for.
* @param reset_type ResetType describing how to create the timer
* @param name Optional name of timer
* @return The created Timer
*/
- static SharedPtr<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 7681cdee7d..eef00b729a 100644
--- a/src/core/hle/kernel/wait_object.cpp
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -12,6 +12,9 @@
namespace Kernel {
+WaitObject::WaitObject(KernelCore& kernel) : Object{kernel} {}
+WaitObject::~WaitObject() = default;
+
void WaitObject::AddWaitingThread(SharedPtr<Thread> thread) {
auto itr = std::find(waiting_threads.begin(), waiting_threads.end(), thread);
if (itr == waiting_threads.end())
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h
index b5fbc647b3..0bd97133c7 100644
--- a/src/core/hle/kernel/wait_object.h
+++ b/src/core/hle/kernel/wait_object.h
@@ -11,11 +11,15 @@
namespace Kernel {
+class KernelCore;
class Thread;
/// Class that represents a Kernel object that a thread can be waiting on
class WaitObject : public Object {
public:
+ explicit WaitObject(KernelCore& kernel);
+ ~WaitObject() override;
+
/**
* Check if the specified thread should wait until the object is available
* @param thread The thread about which we're deciding.
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 7e3cf6d583..818c03e0f3 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -160,8 +160,9 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger
};
RegisterHandlers(functions);
+ auto& kernel = Core::System::GetInstance().Kernel();
launchable_event =
- Kernel::Event::Create(Kernel::ResetType::Sticky, "ISelfController:LaunchableEvent");
+ Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "ISelfController:LaunchableEvent");
}
void ISelfController::SetFocusHandlingMode(Kernel::HLERequestContext& ctx) {
@@ -332,7 +333,8 @@ ICommonStateGetter::ICommonStateGetter() : ServiceFramework("ICommonStateGetter"
};
RegisterHandlers(functions);
- event = Kernel::Event::Create(Kernel::ResetType::OneShot, "ICommonStateGetter:Event");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "ICommonStateGetter:Event");
}
void ICommonStateGetter::GetBootMode(Kernel::HLERequestContext& ctx) {
@@ -505,7 +507,8 @@ public:
};
RegisterHandlers(functions);
- state_changed_event = Kernel::Event::Create(Kernel::ResetType::OneShot,
+ auto& kernel = Core::System::GetInstance().Kernel();
+ state_changed_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
"ILibraryAppletAccessor:StateChangedEvent");
}
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index ce709ccf49..5f370bbdfb 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -47,7 +47,9 @@ public:
RegisterHandlers(functions);
// This is the event handle used to check if the audio buffer was released
- buffer_event = Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioOutBufferReleased");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ buffer_event =
+ Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioOutBufferReleased");
stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count,
"IAudioOut", [=]() { buffer_event->Signal(); });
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 9e75eb3a6c..016db7c82c 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -35,8 +35,9 @@ public:
};
RegisterHandlers(functions);
+ auto& kernel = Core::System::GetInstance().Kernel();
system_event =
- Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent");
+ Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "IAudioRenderer:SystemEvent");
renderer = std::make_unique<AudioCore::AudioRenderer>(audren_params, system_event);
}
@@ -121,8 +122,9 @@ public:
};
RegisterHandlers(functions);
- buffer_event =
- Kernel::Event::Create(Kernel::ResetType::OneShot, "IAudioOutBufferReleasedEvent");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ buffer_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
+ "IAudioOutBufferReleasedEvent");
}
private:
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index c0ba330dcd..0d31abe8b5 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -4,6 +4,7 @@
#include <atomic>
#include "common/logging/log.h"
+#include "core/core.h"
#include "core/core_timing.h"
#include "core/core_timing_util.h"
#include "core/frontend/emu_window.h"
@@ -35,9 +36,10 @@ public:
};
RegisterHandlers(functions);
+ auto& kernel = Core::System::GetInstance().Kernel();
shared_mem = Kernel::SharedMemory::Create(
- nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read,
- 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");
+ kernel, nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite,
+ Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");
// Register update callbacks
pad_update_event = CoreTiming::RegisterEvent(
@@ -402,7 +404,8 @@ public:
RegisterHandlers(functions);
- event = Kernel::Event::Create(Kernel::ResetType::OneShot, "hid:EventHandle");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "hid:EventHandle");
}
~Hid() = default;
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 56b05e9e80..4f7543af5e 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -46,11 +46,13 @@ public:
};
RegisterHandlers(functions);
- activate_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:ActivateEvent");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ activate_event =
+ Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:ActivateEvent");
deactivate_event =
- Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:DeactivateEvent");
- availability_change_event =
- Kernel::Event::Create(Kernel::ResetType::OneShot, "IUser:AvailabilityChangeEvent");
+ Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IUser:DeactivateEvent");
+ availability_change_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot,
+ "IUser:AvailabilityChangeEvent");
}
private:
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp
index cfe8d91786..ed4f5f5393 100644
--- a/src/core/hle/service/nifm/nifm.cpp
+++ b/src/core/hle/service/nifm/nifm.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/service/nifm/nifm.h"
@@ -54,8 +55,9 @@ public:
};
RegisterHandlers(functions);
- event1 = Kernel::Event::Create(Kernel::ResetType::OneShot, "IRequest:Event1");
- event2 = Kernel::Event::Create(Kernel::ResetType::OneShot, "IRequest:Event2");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ event1 = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IRequest:Event1");
+ event2 = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "IRequest:Event2");
}
private:
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index 923a52cc53..51638793da 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -266,8 +266,9 @@ void PL_U::GetSharedMemoryNativeHandle(Kernel::HLERequestContext& ctx) {
SHARED_FONT_MEM_VADDR, shared_font, 0, SHARED_FONT_MEM_SIZE, Kernel::MemoryState::Shared);
// Create shared font memory object
+ auto& kernel = Core::System::GetInstance().Kernel();
shared_font_mem = Kernel::SharedMemory::Create(
- Core::CurrentProcess(), SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite,
+ kernel, Core::CurrentProcess(), SHARED_FONT_MEM_SIZE, Kernel::MemoryPermission::ReadWrite,
Kernel::MemoryPermission::Read, SHARED_FONT_MEM_VADDR, Kernel::MemoryRegion::BASE,
"PL_U:shared_font_mem");
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index 1b497b8145..634ab9196d 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -4,6 +4,7 @@
#include <cinttypes>
#include "common/logging/log.h"
+#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/service/nvdrv/interface.h"
@@ -107,7 +108,8 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
};
RegisterHandlers(functions);
- query_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "NVDRV::query_event");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ query_event = Kernel::Event::Create(kernel, Kernel::ResetType::OneShot, "NVDRV::query_event");
}
} // namespace Service::Nvidia
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index ef5713a71f..8d89622769 100644
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -6,14 +6,16 @@
#include "common/assert.h"
#include "common/logging/log.h"
+#include "core/core.h"
#include "core/hle/service/nvflinger/buffer_queue.h"
namespace Service {
namespace NVFlinger {
BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
+ auto& kernel = Core::System::GetInstance().Kernel();
buffer_wait_event =
- Kernel::Event::Create(Kernel::ResetType::Sticky, "BufferQueue NativeHandle");
+ Kernel::Event::Create(kernel, Kernel::ResetType::Sticky, "BufferQueue NativeHandle");
}
void BufferQueue::SetPreallocatedBuffer(u32 slot, const IGBPBuffer& igbp_buffer) {
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index a26a5f8125..3996c24fea 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -161,7 +161,8 @@ void NVFlinger::Compose() {
Layer::Layer(u64 id, std::shared_ptr<BufferQueue> queue) : id(id), buffer_queue(std::move(queue)) {}
Display::Display(u64 id, std::string name) : id(id), name(std::move(name)) {
- vsync_event = Kernel::Event::Create(Kernel::ResetType::Pulse, "Display VSync Event");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ vsync_event = Kernel::Event::Create(kernel, Kernel::ResetType::Pulse, "Display VSync Event");
}
} // namespace Service::NVFlinger
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 11951adaf4..8fb9070725 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -107,19 +107,24 @@ void ServiceFrameworkBase::InstallAsService(SM::ServiceManager& service_manager)
void ServiceFrameworkBase::InstallAsNamedPort() {
ASSERT(port == nullptr);
+
+ auto& kernel = Core::System::GetInstance().Kernel();
SharedPtr<ServerPort> server_port;
SharedPtr<ClientPort> client_port;
- std::tie(server_port, client_port) = ServerPort::CreatePortPair(max_sessions, service_name);
+ std::tie(server_port, client_port) =
+ ServerPort::CreatePortPair(kernel, max_sessions, service_name);
server_port->SetHleHandler(shared_from_this());
AddNamedPort(service_name, std::move(client_port));
}
Kernel::SharedPtr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort() {
ASSERT(port == nullptr);
+
+ auto& kernel = Core::System::GetInstance().Kernel();
Kernel::SharedPtr<Kernel::ServerPort> server_port;
Kernel::SharedPtr<Kernel::ClientPort> client_port;
std::tie(server_port, client_port) =
- Kernel::ServerPort::CreatePortPair(max_sessions, service_name);
+ Kernel::ServerPort::CreatePortPair(kernel, max_sessions, service_name);
port = MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port)).Unwrap();
port->SetHleHandler(shared_from_this());
return client_port;
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp
index f22a2a79f6..b240d7eed5 100644
--- a/src/core/hle/service/sm/sm.cpp
+++ b/src/core/hle/service/sm/sm.cpp
@@ -4,6 +4,7 @@
#include <tuple>
#include "common/assert.h"
+#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
@@ -47,9 +48,11 @@ ResultVal<Kernel::SharedPtr<Kernel::ServerPort>> ServiceManager::RegisterService
if (registered_services.find(name) != registered_services.end())
return ERR_ALREADY_REGISTERED;
+ auto& kernel = Core::System::GetInstance().Kernel();
Kernel::SharedPtr<Kernel::ServerPort> server_port;
Kernel::SharedPtr<Kernel::ClientPort> client_port;
- std::tie(server_port, client_port) = Kernel::ServerPort::CreatePortPair(max_sessions, name);
+ std::tie(server_port, client_port) =
+ Kernel::ServerPort::CreatePortPair(kernel, max_sessions, name);
registered_services.emplace(std::move(name), std::move(client_port));
return MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port));
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 4c79d7902c..a53fa6e00c 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -6,6 +6,7 @@
#include "common/common_funcs.h"
#include "common/file_util.h"
#include "common/logging/log.h"
+#include "core/core.h"
#include "core/file_sys/content_archive.h"
#include "core/file_sys/control_metadata.h"
#include "core/file_sys/romfs_factory.h"
@@ -117,10 +118,11 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
}
}
+ auto& kernel = Core::System::GetInstance().Kernel();
process->program_id = metadata.GetTitleID();
process->svc_access_mask.set();
process->resource_limit =
- Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
+ kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(Memory::PROCESS_IMAGE_VADDR, metadata.GetMainThreadPriority(),
metadata.GetMainThreadStackSize());
diff --git a/src/core/loader/elf.cpp b/src/core/loader/elf.cpp
index 6420a7f110..3702a84781 100644
--- a/src/core/loader/elf.cpp
+++ b/src/core/loader/elf.cpp
@@ -9,6 +9,7 @@
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
+#include "core/core.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
#include "core/loader/elf.h"
@@ -300,7 +301,8 @@ SharedPtr<CodeSet> ElfReader::LoadInto(u32 vaddr) {
std::vector<u8> program_image(total_image_size);
size_t current_image_position = 0;
- SharedPtr<CodeSet> codeset = CodeSet::Create("");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ SharedPtr<CodeSet> codeset = CodeSet::Create(kernel, "");
for (unsigned int i = 0; i < header->e_phnum; ++i) {
Elf32_Phdr* p = &segments[i];
@@ -400,8 +402,9 @@ ResultStatus AppLoader_ELF::Load(Kernel::SharedPtr<Kernel::Process>& process) {
process->svc_access_mask.set();
// Attach the default resource limit (APPLICATION) to the process
+ auto& kernel = Core::System::GetInstance().Kernel();
process->resource_limit =
- Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
+ kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(codeset->entrypoint, 48, Memory::DEFAULT_STACK_SIZE);
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index 2179cf2ea0..00205d1d21 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -136,7 +136,8 @@ bool AppLoader_NRO::LoadNro(FileSys::VirtualFile file, VAddr load_base) {
}
// Build program image
- Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create("");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create(kernel, "");
std::vector<u8> program_image = file->ReadBytes(PageAlignSize(nro_header.file_size));
if (program_image.size() != PageAlignSize(nro_header.file_size)) {
return {};
@@ -185,9 +186,10 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
return ResultStatus::ErrorLoadingNRO;
}
+ auto& kernel = Core::System::GetInstance().Kernel();
process->svc_access_mask.set();
process->resource_limit =
- Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
+ kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(base_addr, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
is_loaded = true;
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp
index a94558ac5f..0c992d662b 100644
--- a/src/core/loader/nso.cpp
+++ b/src/core/loader/nso.cpp
@@ -100,7 +100,8 @@ VAddr AppLoader_NSO::LoadModule(FileSys::VirtualFile file, VAddr load_base) {
return {};
// Build program image
- Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create("");
+ auto& kernel = Core::System::GetInstance().Kernel();
+ Kernel::SharedPtr<Kernel::CodeSet> codeset = Kernel::CodeSet::Create(kernel, "");
std::vector<u8> program_image;
for (std::size_t i = 0; i < nso_header.segments.size(); ++i) {
const std::vector<u8> compressed_data =
@@ -151,9 +152,10 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
LoadModule(file, Memory::PROCESS_IMAGE_VADDR);
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", file->GetName(), Memory::PROCESS_IMAGE_VADDR);
+ auto& kernel = Core::System::GetInstance().Kernel();
process->svc_access_mask.set();
process->resource_limit =
- Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
+ kernel.ResourceLimitForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(Memory::PROCESS_IMAGE_VADDR, THREADPRIO_DEFAULT, Memory::DEFAULT_STACK_SIZE);
is_loaded = true;
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp
index 539746246b..038d57b3a6 100644
--- a/src/tests/core/arm/arm_test_common.cpp
+++ b/src/tests/core/arm/arm_test_common.cpp
@@ -13,7 +13,7 @@ namespace ArmTests {
TestEnvironment::TestEnvironment(bool mutable_memory_)
: mutable_memory(mutable_memory_), test_memory(std::make_shared<TestMemory>(this)) {
- Core::CurrentProcess() = Kernel::Process::Create("");
+ Core::CurrentProcess() = Kernel::Process::Create(kernel, "");
page_table = &Core::CurrentProcess()->vm_manager.page_table;
page_table->pointers.fill(nullptr);
diff --git a/src/tests/core/arm/arm_test_common.h b/src/tests/core/arm/arm_test_common.h
index 7fdbda494c..e4b6df194e 100644
--- a/src/tests/core/arm/arm_test_common.h
+++ b/src/tests/core/arm/arm_test_common.h
@@ -9,6 +9,7 @@
#include <vector>
#include "common/common_types.h"
+#include "core/hle/kernel/kernel.h"
#include "core/memory_hook.h"
namespace Memory {
@@ -86,6 +87,7 @@ private:
std::shared_ptr<TestMemory> test_memory;
std::vector<WriteRecord> write_records;
Memory::PageTable* page_table = nullptr;
+ Kernel::KernelCore kernel;
};
} // namespace ArmTests
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index d0926d723d..eac0c05f27 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -77,9 +77,11 @@ QString WaitTreeText::GetText() const {
}
WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address) : mutex_address(mutex_address) {
+ auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
+
mutex_value = Memory::Read32(mutex_address);
owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Mutex::MutexOwnerMask);
- owner = Kernel::g_handle_table.Get<Kernel::Thread>(owner_handle);
+ owner = handle_table.Get<Kernel::Thread>(owner_handle);
}
QString WaitTreeMutexInfo::GetText() const {