aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/hle_ipc.cpp36
-rw-r--r--src/core/hle/kernel/hle_ipc.h123
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp10
-rw-r--r--src/core/hle/kernel/k_class_token.cpp79
-rw-r--r--src/core/hle/kernel/k_client_port.cpp8
-rw-r--r--src/core/hle/kernel/k_client_port.h9
-rw-r--r--src/core/hle/kernel/k_client_session.h4
-rw-r--r--src/core/hle/kernel/k_event.h14
-rw-r--r--src/core/hle/kernel/k_port.cpp7
-rw-r--r--src/core/hle/kernel/k_port.h3
-rw-r--r--src/core/hle/kernel/k_process.h8
-rw-r--r--src/core/hle/kernel/k_readable_event.h4
-rw-r--r--src/core/hle/kernel/k_resource_limit.h4
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp1
-rw-r--r--src/core/hle/kernel/k_server_port.h28
-rw-r--r--src/core/hle/kernel/k_server_session.cpp35
-rw-r--r--src/core/hle/kernel/k_server_session.h42
-rw-r--r--src/core/hle/kernel/k_session.cpp2
-rw-r--r--src/core/hle/kernel/k_session.h14
-rw-r--r--src/core/hle/kernel/k_shared_memory.h4
-rw-r--r--src/core/hle/kernel/k_slab_heap.h69
-rw-r--r--src/core/hle/kernel/k_synchronization_object.h4
-rw-r--r--src/core/hle/kernel/k_thread.cpp10
-rw-r--r--src/core/hle/kernel/k_thread.h10
-rw-r--r--src/core/hle/kernel/k_transfer_memory.h10
-rw-r--r--src/core/hle/kernel/k_writable_event.h2
-rw-r--r--src/core/hle/kernel/kernel.cpp5
-rw-r--r--src/core/hle/kernel/process_capability.cpp9
-rw-r--r--src/core/hle/kernel/process_capability.h3
-rw-r--r--src/core/hle/kernel/service_thread.cpp14
-rw-r--r--src/core/hle/kernel/slab_helpers.h4
31 files changed, 329 insertions, 246 deletions
diff --git a/src/core/hle/kernel/hle_ipc.cpp b/src/core/hle/kernel/hle_ipc.cpp
index 24700f7a5..9d069a78f 100644
--- a/src/core/hle/kernel/hle_ipc.cpp
+++ b/src/core/hle/kernel/hle_ipc.cpp
@@ -35,11 +35,11 @@ SessionRequestHandler::SessionRequestHandler() = default;
SessionRequestHandler::~SessionRequestHandler() = default;
void SessionRequestHandler::ClientConnected(KServerSession* session) {
- session->SetHleHandler(shared_from_this());
+ session->SetSessionHandler(shared_from_this());
}
void SessionRequestHandler::ClientDisconnected(KServerSession* session) {
- session->SetHleHandler(nullptr);
+ session->SetSessionHandler(nullptr);
}
HLERequestContext::HLERequestContext(KernelCore& kernel_, Core::Memory::Memory& memory_,
@@ -69,14 +69,10 @@ void HLERequestContext::ParseCommandBuffer(const KHandleTable& handle_table, u32
if (incoming) {
// Populate the object lists with the data in the IPC request.
for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) {
- const u32 copy_handle{rp.Pop<Handle>()};
- copy_handles.push_back(copy_handle);
- copy_objects.push_back(handle_table.GetObject(copy_handle).GetPointerUnsafe());
+ incoming_copy_handles.push_back(rp.Pop<Handle>());
}
for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_move; ++handle) {
- const u32 move_handle{rp.Pop<Handle>()};
- move_handles.push_back(move_handle);
- move_objects.push_back(handle_table.GetObject(move_handle).GetPointerUnsafe());
+ incoming_move_handles.push_back(rp.Pop<Handle>());
}
} else {
// For responses we just ignore the handles, they're empty and will be populated when
@@ -186,26 +182,14 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_t
auto& owner_process = *requesting_thread.GetOwnerProcess();
auto& handle_table = owner_process.GetHandleTable();
- // The data_size already includes the payload header, the padding and the domain header.
- std::size_t size{};
-
- if (IsTipc()) {
- size = cmd_buf.size();
- } else {
- size = data_payload_offset + data_size - sizeof(IPC::DataPayloadHeader) / sizeof(u32) - 4;
- if (Session()->IsDomain()) {
- size -= sizeof(IPC::DomainMessageHeader) / sizeof(u32);
- }
- }
-
- for (auto& object : copy_objects) {
+ for (auto& object : outgoing_copy_objects) {
Handle handle{};
if (object) {
R_TRY(handle_table.Add(&handle, object));
}
cmd_buf[current_offset++] = handle;
}
- for (auto& object : move_objects) {
+ for (auto& object : outgoing_move_objects) {
Handle handle{};
if (object) {
R_TRY(handle_table.Add(&handle, object));
@@ -220,9 +204,9 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_t
// TODO(Subv): This completely ignores C buffers.
if (Session()->IsDomain()) {
- current_offset = domain_offset - static_cast<u32>(domain_objects.size());
- for (const auto& object : domain_objects) {
- server_session->AppendDomainRequestHandler(object);
+ current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size());
+ for (const auto& object : outgoing_domain_objects) {
+ server_session->AppendDomainHandler(object);
cmd_buf[current_offset++] =
static_cast<u32_le>(server_session->NumDomainRequestHandlers());
}
@@ -230,7 +214,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(KThread& requesting_t
// Copy the translated command buffer back into the thread's command buffer area.
memory.WriteBlock(owner_process, requesting_thread.GetTLSAddress(), cmd_buf.data(),
- size * sizeof(u32));
+ write_size * sizeof(u32));
return RESULT_SUCCESS;
}
diff --git a/src/core/hle/kernel/hle_ipc.h b/src/core/hle/kernel/hle_ipc.h
index e1b128281..b47e363cc 100644
--- a/src/core/hle/kernel/hle_ipc.h
+++ b/src/core/hle/kernel/hle_ipc.h
@@ -11,7 +11,8 @@
#include <string>
#include <type_traits>
#include <vector>
-#include <boost/container/small_vector.hpp>
+
+#include "common/assert.h"
#include "common/common_types.h"
#include "common/concepts.h"
#include "common/swap.h"
@@ -84,6 +85,69 @@ public:
void ClientDisconnected(KServerSession* session);
};
+using SessionRequestHandlerPtr = std::shared_ptr<SessionRequestHandler>;
+
+/**
+ * Manages the underlying HLE requests for a session, and whether (or not) the session should be
+ * treated as a domain. This is managed separately from server sessions, as this state is shared
+ * when objects are cloned.
+ */
+class SessionRequestManager final {
+public:
+ SessionRequestManager() = default;
+
+ bool IsDomain() const {
+ return is_domain;
+ }
+
+ void ConvertToDomain() {
+ domain_handlers = {session_handler};
+ is_domain = true;
+ }
+
+ std::size_t DomainHandlerCount() const {
+ return domain_handlers.size();
+ }
+
+ bool HasSessionHandler() const {
+ return session_handler != nullptr;
+ }
+
+ SessionRequestHandler& SessionHandler() {
+ return *session_handler;
+ }
+
+ const SessionRequestHandler& SessionHandler() const {
+ return *session_handler;
+ }
+
+ void CloseDomainHandler(std::size_t index) {
+ if (index < DomainHandlerCount()) {
+ domain_handlers[index] = nullptr;
+ } else {
+ UNREACHABLE_MSG("Unexpected handler index {}", index);
+ }
+ }
+
+ SessionRequestHandlerPtr DomainHandler(std::size_t index) const {
+ ASSERT_MSG(index < DomainHandlerCount(), "Unexpected handler index {}", index);
+ return domain_handlers.at(index);
+ }
+
+ void AppendDomainHandler(SessionRequestHandlerPtr&& handler) {
+ domain_handlers.emplace_back(std::move(handler));
+ }
+
+ void SetSessionHandler(SessionRequestHandlerPtr&& handler) {
+ session_handler = std::move(handler);
+ }
+
+private:
+ bool is_domain{};
+ SessionRequestHandlerPtr session_handler;
+ std::vector<SessionRequestHandlerPtr> domain_handlers;
+};
+
/**
* Class containing information about an in-flight IPC request being handled by an HLE service
* implementation. Services should avoid using old global APIs (e.g. Kernel::GetCommandBuffer()) and
@@ -224,53 +288,32 @@ public:
bool CanWriteBuffer(std::size_t buffer_index = 0) const;
Handle GetCopyHandle(std::size_t index) const {
- return copy_handles.at(index);
+ return incoming_copy_handles.at(index);
}
Handle GetMoveHandle(std::size_t index) const {
- return move_handles.at(index);
+ return incoming_move_handles.at(index);
}
void AddMoveObject(KAutoObject* object) {
- move_objects.emplace_back(object);
+ outgoing_move_objects.emplace_back(object);
}
void AddCopyObject(KAutoObject* object) {
- copy_objects.emplace_back(object);
+ outgoing_copy_objects.emplace_back(object);
}
- void AddDomainObject(std::shared_ptr<SessionRequestHandler> object) {
- domain_objects.emplace_back(std::move(object));
+ void AddDomainObject(SessionRequestHandlerPtr object) {
+ outgoing_domain_objects.emplace_back(std::move(object));
}
template <typename T>
- std::shared_ptr<T> GetDomainRequestHandler(std::size_t index) const {
- return std::static_pointer_cast<T>(domain_request_handlers.at(index));
- }
-
- void SetDomainRequestHandlers(
- const std::vector<std::shared_ptr<SessionRequestHandler>>& handlers) {
- domain_request_handlers = handlers;
- }
-
- /// Clears the list of objects so that no lingering objects are written accidentally to the
- /// response buffer.
- void ClearIncomingObjects() {
- move_objects.clear();
- copy_objects.clear();
- domain_objects.clear();
+ std::shared_ptr<T> GetDomainHandler(std::size_t index) const {
+ return std::static_pointer_cast<T>(manager->DomainHandler(index));
}
- std::size_t NumMoveObjects() const {
- return move_objects.size();
- }
-
- std::size_t NumCopyObjects() const {
- return copy_objects.size();
- }
-
- std::size_t NumDomainObjects() const {
- return domain_objects.size();
+ void SetSessionRequestManager(std::shared_ptr<SessionRequestManager> manager_) {
+ manager = std::move(manager_);
}
std::string Description() const;
@@ -292,12 +335,12 @@ private:
Kernel::KServerSession* server_session{};
KThread* thread;
- // TODO(yuriks): Check common usage of this and optimize size accordingly
- boost::container::small_vector<Handle, 8> move_handles;
- boost::container::small_vector<Handle, 8> copy_handles;
- boost::container::small_vector<KAutoObject*, 8> move_objects;
- boost::container::small_vector<KAutoObject*, 8> copy_objects;
- boost::container::small_vector<std::shared_ptr<SessionRequestHandler>, 8> domain_objects;
+ std::vector<Handle> incoming_move_handles;
+ std::vector<Handle> incoming_copy_handles;
+
+ std::vector<KAutoObject*> outgoing_move_objects;
+ std::vector<KAutoObject*> outgoing_copy_objects;
+ std::vector<SessionRequestHandlerPtr> outgoing_domain_objects;
std::optional<IPC::CommandHeader> command_header;
std::optional<IPC::HandleDescriptorHeader> handle_descriptor_header;
@@ -311,12 +354,12 @@ private:
u32_le command{};
u64 pid{};
+ u32 write_size{};
u32 data_payload_offset{};
u32 handles_offset{};
u32 domain_offset{};
- u32 data_size{};
- std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers;
+ std::shared_ptr<SessionRequestManager> manager;
bool is_thread_waiting{};
KernelCore& kernel;
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index 69ae405e6..10edede17 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -70,14 +70,22 @@ constexpr size_t SlabCountExtraKThread = 160;
template <typename T>
VAddr InitializeSlabHeap(Core::System& system, KMemoryLayout& memory_layout, VAddr address,
size_t num_objects) {
+ // TODO(bunnei): This is just a place holder. We should initialize the appropriate KSlabHeap for
+ // kernel object type T with the backing kernel memory pointer once we emulate kernel memory.
+
const size_t size = Common::AlignUp(sizeof(T) * num_objects, alignof(void*));
VAddr start = Common::AlignUp(address, alignof(T));
+ // This is intentionally empty. Once KSlabHeap is fully implemented, we can replace this with
+ // the pointer to emulated memory to pass along. Until then, KSlabHeap will just allocate/free
+ // host memory.
+ void* backing_kernel_memory{};
+
if (size > 0) {
const KMemoryRegion* region = memory_layout.FindVirtual(start + size - 1);
ASSERT(region != nullptr);
ASSERT(region->IsDerivedFrom(KMemoryRegionType_KernelSlab));
- T::InitializeSlabHeap(system.Kernel(), system.Memory().GetKernelBuffer(start, size), size);
+ T::InitializeSlabHeap(system.Kernel(), backing_kernel_memory, size);
}
return start + size;
diff --git a/src/core/hle/kernel/k_class_token.cpp b/src/core/hle/kernel/k_class_token.cpp
index beb8a2a05..0be0027be 100644
--- a/src/core/hle/kernel/k_class_token.cpp
+++ b/src/core/hle/kernel/k_class_token.cpp
@@ -84,50 +84,43 @@ static_assert(ClassToken<KTransferMemory> == ((0b10010001 << 8) | ClassToken<KAu
// Ensure that the token hierarchy reflects the class hierarchy.
// Base classes.
-static_assert(!std::is_final<KSynchronizationObject>::value &&
- std::is_base_of<KAutoObject, KSynchronizationObject>::value);
-static_assert(!std::is_final<KReadableEvent>::value &&
- std::is_base_of<KSynchronizationObject, KReadableEvent>::value);
+static_assert(!std::is_final_v<KSynchronizationObject> &&
+ std::is_base_of_v<KAutoObject, KSynchronizationObject>);
+static_assert(!std::is_final_v<KReadableEvent> &&
+ std::is_base_of_v<KSynchronizationObject, KReadableEvent>);
// Final classes
-// static_assert(std::is_final<KInterruptEvent>::value &&
-// std::is_base_of<KReadableEvent, KInterruptEvent>::value);
-// static_assert(std::is_final<KDebug>::value &&
-// std::is_base_of<KSynchronizationObject, KDebug>::value);
-static_assert(std::is_final<KThread>::value &&
- std::is_base_of<KSynchronizationObject, KThread>::value);
-static_assert(std::is_final<KServerPort>::value &&
- std::is_base_of<KSynchronizationObject, KServerPort>::value);
-static_assert(std::is_final<KServerSession>::value &&
- std::is_base_of<KSynchronizationObject, KServerSession>::value);
-static_assert(std::is_final<KClientPort>::value &&
- std::is_base_of<KSynchronizationObject, KClientPort>::value);
-static_assert(std::is_final<KClientSession>::value &&
- std::is_base_of<KAutoObject, KClientSession>::value);
-static_assert(std::is_final<KProcess>::value &&
- std::is_base_of<KSynchronizationObject, KProcess>::value);
-static_assert(std::is_final<KResourceLimit>::value &&
- std::is_base_of<KAutoObject, KResourceLimit>::value);
-// static_assert(std::is_final<KLightSession>::value &&
-// std::is_base_of<KAutoObject, KLightSession>::value);
-static_assert(std::is_final<KPort>::value && std::is_base_of<KAutoObject, KPort>::value);
-static_assert(std::is_final<KSession>::value && std::is_base_of<KAutoObject, KSession>::value);
-static_assert(std::is_final<KSharedMemory>::value &&
- std::is_base_of<KAutoObject, KSharedMemory>::value);
-static_assert(std::is_final<KEvent>::value && std::is_base_of<KAutoObject, KEvent>::value);
-static_assert(std::is_final<KWritableEvent>::value &&
- std::is_base_of<KAutoObject, KWritableEvent>::value);
-// static_assert(std::is_final<KLightClientSession>::value &&
-// std::is_base_of<KAutoObject, KLightClientSession>::value);
-// static_assert(std::is_final<KLightServerSession>::value &&
-// std::is_base_of<KAutoObject, KLightServerSession>::value);
-static_assert(std::is_final<KTransferMemory>::value &&
- std::is_base_of<KAutoObject, KTransferMemory>::value);
-// static_assert(std::is_final<KDeviceAddressSpace>::value &&
-// std::is_base_of<KAutoObject, KDeviceAddressSpace>::value);
-// static_assert(std::is_final<KSessionRequest>::value &&
-// std::is_base_of<KAutoObject, KSessionRequest>::value);
-// static_assert(std::is_final<KCodeMemory>::value &&
-// std::is_base_of<KAutoObject, KCodeMemory>::value);
+// static_assert(std::is_final_v<KInterruptEvent> &&
+// std::is_base_of_v<KReadableEvent, KInterruptEvent>);
+// static_assert(std::is_final_v<KDebug> &&
+// std::is_base_of_v<KSynchronizationObject, KDebug>);
+static_assert(std::is_final_v<KThread> && std::is_base_of_v<KSynchronizationObject, KThread>);
+static_assert(std::is_final_v<KServerPort> &&
+ std::is_base_of_v<KSynchronizationObject, KServerPort>);
+static_assert(std::is_final_v<KServerSession> &&
+ std::is_base_of_v<KSynchronizationObject, KServerSession>);
+static_assert(std::is_final_v<KClientPort> &&
+ std::is_base_of_v<KSynchronizationObject, KClientPort>);
+static_assert(std::is_final_v<KClientSession> && std::is_base_of_v<KAutoObject, KClientSession>);
+static_assert(std::is_final_v<KProcess> && std::is_base_of_v<KSynchronizationObject, KProcess>);
+static_assert(std::is_final_v<KResourceLimit> && std::is_base_of_v<KAutoObject, KResourceLimit>);
+// static_assert(std::is_final_v<KLightSession> &&
+// std::is_base_of_v<KAutoObject, KLightSession>);
+static_assert(std::is_final_v<KPort> && std::is_base_of_v<KAutoObject, KPort>);
+static_assert(std::is_final_v<KSession> && std::is_base_of_v<KAutoObject, KSession>);
+static_assert(std::is_final_v<KSharedMemory> && std::is_base_of_v<KAutoObject, KSharedMemory>);
+static_assert(std::is_final_v<KEvent> && std::is_base_of_v<KAutoObject, KEvent>);
+static_assert(std::is_final_v<KWritableEvent> && std::is_base_of_v<KAutoObject, KWritableEvent>);
+// static_assert(std::is_final_v<KLightClientSession> &&
+// std::is_base_of_v<KAutoObject, KLightClientSession>);
+// static_assert(std::is_final_v<KLightServerSession> &&
+// std::is_base_of_v<KAutoObject, KLightServerSession>);
+static_assert(std::is_final_v<KTransferMemory> && std::is_base_of_v<KAutoObject, KTransferMemory>);
+// static_assert(std::is_final_v<KDeviceAddressSpace> &&
+// std::is_base_of_v<KAutoObject, KDeviceAddressSpace>);
+// static_assert(std::is_final_v<KSessionRequest> &&
+// std::is_base_of_v<KAutoObject, KSessionRequest>);
+// static_assert(std::is_final_v<KCodeMemory> &&
+// std::is_base_of_v<KAutoObject, KCodeMemory>);
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp
index ad01cf67e..4a12dee10 100644
--- a/src/core/hle/kernel/k_client_port.cpp
+++ b/src/core/hle/kernel/k_client_port.cpp
@@ -58,9 +58,9 @@ bool KClientPort::IsSignaled() const {
ResultCode KClientPort::CreateSession(KClientSession** out) {
// Reserve a new session from the resource limit.
- // KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(),
- // LimitableResource::Sessions);
- // R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);
+ KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(),
+ LimitableResource::Sessions);
+ R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);
// Update the session counts.
{
@@ -104,7 +104,7 @@ ResultCode KClientPort::CreateSession(KClientSession** out) {
session->Initialize(this, parent->GetName());
// Commit the session reservation.
- // session_reservation.Commit();
+ session_reservation.Commit();
// Register the session.
KSession::Register(kernel, session);
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h
index d00ce3ddd..f2fff3b01 100644
--- a/src/core/hle/kernel/k_client_port.h
+++ b/src/core/hle/kernel/k_client_port.h
@@ -22,7 +22,7 @@ class KClientPort final : public KSynchronizationObject {
public:
explicit KClientPort(KernelCore& kernel_);
- virtual ~KClientPort() override;
+ ~KClientPort() override;
void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_);
void OnSessionFinalized();
@@ -31,6 +31,9 @@ public:
const KPort* GetParent() const {
return parent;
}
+ KPort* GetParent() {
+ return parent;
+ }
s32 GetNumSessions() const {
return num_sessions;
@@ -46,8 +49,8 @@ public:
bool IsServerClosed() const;
// Overridden virtual functions.
- virtual void Destroy() override;
- virtual bool IsSignaled() const override;
+ void Destroy() override;
+ bool IsSignaled() const override;
ResultCode CreateSession(KClientSession** out);
diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h
index 720a8c243..b11d5b4e3 100644
--- a/src/core/hle/kernel/k_client_session.h
+++ b/src/core/hle/kernel/k_client_session.h
@@ -34,7 +34,7 @@ class KClientSession final
public:
explicit KClientSession(KernelCore& kernel_);
- virtual ~KClientSession();
+ ~KClientSession() override;
void Initialize(KSession* parent_, std::string&& name_) {
// Set member variables.
@@ -42,7 +42,7 @@ public:
name = std::move(name_);
}
- virtual void Destroy() override;
+ void Destroy() override;
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
KSession* GetParent() const {
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h
index 9a59ffb70..3d3ec99e2 100644
--- a/src/core/hle/kernel/k_event.h
+++ b/src/core/hle/kernel/k_event.h
@@ -20,23 +20,21 @@ class KEvent final : public KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObj
public:
explicit KEvent(KernelCore& kernel_);
- virtual ~KEvent();
+ ~KEvent() override;
void Initialize(std::string&& name);
- virtual void Finalize() override;
+ void Finalize() override;
- virtual bool IsInitialized() const override {
+ bool IsInitialized() const override {
return initialized;
}
- virtual uintptr_t GetPostDestroyArgument() const override {
+ uintptr_t GetPostDestroyArgument() const override {
return reinterpret_cast<uintptr_t>(owner);
}
- static void PostDestroy(uintptr_t arg);
-
- virtual KProcess* GetOwner() const override {
+ KProcess* GetOwner() const override {
return owner;
}
@@ -48,6 +46,8 @@ public:
return writable_event;
}
+ static void PostDestroy(uintptr_t arg);
+
private:
KReadableEvent readable_event;
KWritableEvent writable_event;
diff --git a/src/core/hle/kernel/k_port.cpp b/src/core/hle/kernel/k_port.cpp
index feb2bb11f..223c0b205 100644
--- a/src/core/hle/kernel/k_port.cpp
+++ b/src/core/hle/kernel/k_port.cpp
@@ -56,11 +56,8 @@ ResultCode KPort::EnqueueSession(KServerSession* session) {
R_UNLESS(state == State::Normal, ResultPortClosed);
- if (server.HasHLEHandler()) {
- server.GetHLEHandler()->ClientConnected(session);
- } else {
- server.EnqueueSession(session);
- }
+ server.EnqueueSession(session);
+ server.GetSessionRequestHandler()->ClientConnected(server.AcceptSession());
return RESULT_SUCCESS;
}
diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h
index 960f1f3a3..4018ea2df 100644
--- a/src/core/hle/kernel/k_port.h
+++ b/src/core/hle/kernel/k_port.h
@@ -22,7 +22,7 @@ class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjec
public:
explicit KPort(KernelCore& kernel_);
- virtual ~KPort();
+ ~KPort() override;
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
@@ -59,7 +59,6 @@ private:
ServerClosed = 3,
};
-private:
KServerPort server;
KClientPort client;
State state{State::Invalid};
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 123d71cd3..c0656b9af 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -331,19 +331,19 @@ public:
void LoadModule(CodeSet code_set, VAddr base_addr);
- virtual bool IsInitialized() const override {
+ bool IsInitialized() const override {
return is_initialized;
}
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
- virtual void Finalize();
+ void Finalize() override;
- virtual u64 GetId() const override final {
+ u64 GetId() const override {
return GetProcessID();
}
- virtual bool IsSignaled() const override;
+ bool IsSignaled() const override;
void PinCurrentThread();
void UnpinCurrentThread();
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h
index 33cd1dd3e..b2850ac7b 100644
--- a/src/core/hle/kernel/k_readable_event.h
+++ b/src/core/hle/kernel/k_readable_event.h
@@ -31,8 +31,8 @@ public:
return parent;
}
- virtual bool IsSignaled() const override;
- virtual void Destroy() override;
+ bool IsSignaled() const override;
+ void Destroy() override;
ResultCode Signal();
ResultCode Clear();
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index 0debbbb51..fab6005ff 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -37,10 +37,10 @@ class KResourceLimit final
public:
explicit KResourceLimit(KernelCore& kernel_);
- virtual ~KResourceLimit();
+ ~KResourceLimit() override;
void Initialize(const Core::Timing::CoreTiming* core_timing_);
- virtual void Finalize() override;
+ void Finalize() override;
s64 GetLimitValue(LimitableResource which) const;
s64 GetCurrentValue(LimitableResource which) const;
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 2f82fbcd6..6a7d80d03 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -659,7 +659,6 @@ void KScheduler::Unload(KThread* thread) {
if (thread) {
if (thread->IsCallingSvc()) {
- system.ArmInterface(core_id).ExceptionalExit();
thread->ClearIsCallingSvc();
}
if (!thread->IsTerminationRequested()) {
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h
index e76792253..55481d63f 100644
--- a/src/core/hle/kernel/k_server_port.h
+++ b/src/core/hle/kernel/k_server_port.h
@@ -25,33 +25,28 @@ class SessionRequestHandler;
class KServerPort final : public KSynchronizationObject {
KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject);
-private:
- using SessionList = boost::intrusive::list<KServerSession>;
-
public:
explicit KServerPort(KernelCore& kernel_);
- virtual ~KServerPort() override;
-
- using HLEHandler = std::shared_ptr<SessionRequestHandler>;
+ ~KServerPort() override;
void Initialize(KPort* parent_, std::string&& name_);
/// Whether or not this server port has an HLE handler available.
- bool HasHLEHandler() const {
- return hle_handler != nullptr;
+ bool HasSessionRequestHandler() const {
+ return session_handler != nullptr;
}
/// Gets the HLE handler for this port.
- HLEHandler GetHLEHandler() const {
- return hle_handler;
+ SessionRequestHandlerPtr GetSessionRequestHandler() const {
+ return session_handler;
}
/**
* Sets the HLE handler template for the port. ServerSessions crated by connecting to this port
* will inherit a reference to this handler.
*/
- void SetHleHandler(HLEHandler hle_handler_) {
- hle_handler = std::move(hle_handler_);
+ void SetSessionHandler(SessionRequestHandlerPtr&& handler) {
+ session_handler = std::move(handler);
}
void EnqueueSession(KServerSession* pending_session);
@@ -65,15 +60,16 @@ public:
bool IsLight() const;
// Overridden virtual functions.
- virtual void Destroy() override;
- virtual bool IsSignaled() const override;
+ void Destroy() override;
+ bool IsSignaled() const override;
private:
+ using SessionList = boost::intrusive::list<KServerSession>;
+
void CleanupSessions();
-private:
SessionList session_list;
- HLEHandler hle_handler;
+ SessionRequestHandlerPtr session_handler;
KPort* parent{};
};
diff --git a/src/core/hle/kernel/k_server_session.cpp b/src/core/hle/kernel/k_server_session.cpp
index 8850d9af5..457fdfd60 100644
--- a/src/core/hle/kernel/k_server_session.cpp
+++ b/src/core/hle/kernel/k_server_session.cpp
@@ -23,7 +23,8 @@
namespace Kernel {
-KServerSession::KServerSession(KernelCore& kernel_) : KSynchronizationObject{kernel_} {}
+KServerSession::KServerSession(KernelCore& kernel_)
+ : KSynchronizationObject{kernel_}, manager{std::make_shared<SessionRequestManager>()} {}
KServerSession::~KServerSession() {
kernel.ReleaseServiceThread(service_thread);
@@ -43,14 +44,8 @@ void KServerSession::Destroy() {
}
void KServerSession::OnClientClosed() {
- // We keep a shared pointer to the hle handler to keep it alive throughout
- // the call to ClientDisconnected, as ClientDisconnected invalidates the
- // hle_handler member itself during the course of the function executing.
- std::shared_ptr<SessionRequestHandler> handler = hle_handler;
- if (handler) {
- // Note that after this returns, this server session's hle_handler is
- // invalidated (set to null).
- handler->ClientDisconnected(this);
+ if (manager->HasSessionHandler()) {
+ manager->SessionHandler().ClientDisconnected(this);
}
}
@@ -66,12 +61,12 @@ bool KServerSession::IsSignaled() const {
return false;
}
-void KServerSession::AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler) {
- domain_request_handlers.push_back(std::move(handler));
+void KServerSession::AppendDomainHandler(SessionRequestHandlerPtr handler) {
+ manager->AppendDomainHandler(std::move(handler));
}
std::size_t KServerSession::NumDomainRequestHandlers() const {
- return domain_request_handlers.size();
+ return manager->DomainHandlerCount();
}
ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& context) {
@@ -80,14 +75,14 @@ ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& co
}
// Set domain handlers in HLE context, used for domain objects (IPC interfaces) as inputs
- context.SetDomainRequestHandlers(domain_request_handlers);
+ context.SetSessionRequestManager(manager);
// If there is a DomainMessageHeader, then this is CommandType "Request"
const auto& domain_message_header = context.GetDomainMessageHeader();
const u32 object_id{domain_message_header.object_id};
switch (domain_message_header.command) {
case IPC::DomainMessageHeader::CommandType::SendMessage:
- if (object_id > domain_request_handlers.size()) {
+ if (object_id > manager->DomainHandlerCount()) {
LOG_CRITICAL(IPC,
"object_id {} is too big! This probably means a recent service call "
"to {} needed to return a new interface!",
@@ -95,12 +90,12 @@ ResultCode KServerSession::HandleDomainSyncRequest(Kernel::HLERequestContext& co
UNREACHABLE();
return RESULT_SUCCESS; // Ignore error if asserts are off
}
- return domain_request_handlers[object_id - 1]->HandleSyncRequest(*this, context);
+ return manager->DomainHandler(object_id - 1)->HandleSyncRequest(*this, context);
case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id);
- domain_request_handlers[object_id - 1] = nullptr;
+ manager->CloseDomainHandler(object_id - 1);
IPC::ResponseBuilder rb{context, 2};
rb.Push(RESULT_SUCCESS);
@@ -133,14 +128,14 @@ ResultCode KServerSession::CompleteSyncRequest(HLERequestContext& context) {
if (IsDomain() && context.HasDomainMessageHeader()) {
result = HandleDomainSyncRequest(context);
// If there is no domain header, the regular session handler is used
- } else if (hle_handler != nullptr) {
+ } else if (manager->HasSessionHandler()) {
// If this ServerSession has an associated HLE handler, forward the request to it.
- result = hle_handler->HandleSyncRequest(*this, context);
+ result = manager->SessionHandler().HandleSyncRequest(*this, context);
}
if (convert_to_domain) {
- ASSERT_MSG(IsSession(), "ServerSession is already a domain instance.");
- domain_request_handlers = {hle_handler};
+ ASSERT_MSG(!IsDomain(), "ServerSession is already a domain instance.");
+ manager->ConvertToDomain();
convert_to_domain = false;
}
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h
index 597d76d38..27b757ad2 100644
--- a/src/core/hle/kernel/k_server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -12,6 +12,7 @@
#include <boost/intrusive/list.hpp>
#include "common/threadsafe_queue.h"
+#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/k_synchronization_object.h"
#include "core/hle/kernel/service_thread.h"
#include "core/hle/result.h"
@@ -41,9 +42,9 @@ class KServerSession final : public KSynchronizationObject,
public:
explicit KServerSession(KernelCore& kernel_);
- virtual ~KServerSession() override;
+ ~KServerSession() override;
- virtual void Destroy() override;
+ void Destroy() override;
void Initialize(KSession* parent_, std::string&& name_);
@@ -55,7 +56,7 @@ public:
return parent;
}
- virtual bool IsSignaled() const override;
+ bool IsSignaled() const override;
void OnClientClosed();
@@ -64,8 +65,8 @@ public:
* instead of the regular IPC machinery. (The regular IPC machinery is currently not
* implemented.)
*/
- void SetHleHandler(std::shared_ptr<SessionRequestHandler> hle_handler_) {
- hle_handler = std::move(hle_handler_);
+ void SetSessionHandler(SessionRequestHandlerPtr handler) {
+ manager->SetSessionHandler(std::move(handler));
}
/**
@@ -82,7 +83,7 @@ public:
/// Adds a new domain request handler to the collection of request handlers within
/// this ServerSession instance.
- void AppendDomainRequestHandler(std::shared_ptr<SessionRequestHandler> handler);
+ void AppendDomainHandler(SessionRequestHandlerPtr handler);
/// Retrieves the total number of domain request handlers that have been
/// appended to this ServerSession instance.
@@ -90,12 +91,7 @@ public:
/// Returns true if the session has been converted to a domain, otherwise False
bool IsDomain() const {
- return !IsSession();
- }
-
- /// Returns true if this session has not been converted to a domain, otherwise false.
- bool IsSession() const {
- return domain_request_handlers.empty();
+ return manager->IsDomain();
}
/// Converts the session to a domain at the end of the current command
@@ -103,6 +99,21 @@ public:
convert_to_domain = true;
}
+ /// Gets the session request manager, which forwards requests to the underlying service
+ std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() {
+ return manager;
+ }
+
+ /// Gets the session request manager, which forwards requests to the underlying service
+ const std::shared_ptr<SessionRequestManager>& GetSessionRequestManager() const {
+ return manager;
+ }
+
+ /// Sets the session request manager, which forwards requests to the underlying service
+ void SetSessionRequestManager(std::shared_ptr<SessionRequestManager> manager_) {
+ manager = std::move(manager_);
+ }
+
private:
/// Queues a sync request from the emulated application.
ResultCode QueueSyncRequest(KThread* thread, Core::Memory::Memory& memory);
@@ -114,11 +125,8 @@ private:
/// object handle.
ResultCode HandleDomainSyncRequest(Kernel::HLERequestContext& context);
- /// This session's HLE request handler (applicable when not a domain)
- std::shared_ptr<SessionRequestHandler> hle_handler;
-
- /// This is the list of domain request handlers (after conversion to a domain)
- std::vector<std::shared_ptr<SessionRequestHandler>> domain_request_handlers;
+ /// This session's HLE request handlers
+ std::shared_ptr<SessionRequestManager> manager;
/// When set to True, converts the session to a domain at the end of the command
bool convert_to_domain{};
diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp
index b7ce27a0b..025b8b555 100644
--- a/src/core/hle/kernel/k_session.cpp
+++ b/src/core/hle/kernel/k_session.cpp
@@ -78,7 +78,7 @@ void KSession::OnClientClosed() {
void KSession::PostDestroy(uintptr_t arg) {
// Release the session count resource the owner process holds.
KProcess* owner = reinterpret_cast<KProcess*>(arg);
- // owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1);
+ owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1);
owner->Close();
}
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h
index 16901e19c..4ddd080d2 100644
--- a/src/core/hle/kernel/k_session.h
+++ b/src/core/hle/kernel/k_session.h
@@ -18,17 +18,17 @@ class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAut
public:
explicit KSession(KernelCore& kernel_);
- virtual ~KSession() override;
+ ~KSession() override;
void Initialize(KClientPort* port_, const std::string& name_);
- virtual void Finalize() override;
+ void Finalize() override;
- virtual bool IsInitialized() const override {
+ bool IsInitialized() const override {
return initialized;
}
- virtual uintptr_t GetPostDestroyArgument() const override {
+ uintptr_t GetPostDestroyArgument() const override {
return reinterpret_cast<uintptr_t>(process);
}
@@ -66,6 +66,10 @@ public:
return port;
}
+ KClientPort* GetParent() {
+ return port;
+ }
+
private:
enum class State : u8 {
Invalid = 0,
@@ -74,7 +78,6 @@ private:
ServerClosed = 3,
};
-private:
void SetState(State state) {
atomic_state = static_cast<u8>(state);
}
@@ -83,7 +86,6 @@ private:
return static_cast<State>(atomic_state.load(std::memory_order_relaxed));
}
-private:
KServerSession server;
KClientSession client;
std::atomic<std::underlying_type_t<State>> atomic_state{
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h
index 553a56327..e9815f90b 100644
--- a/src/core/hle/kernel/k_shared_memory.h
+++ b/src/core/hle/kernel/k_shared_memory.h
@@ -68,9 +68,9 @@ public:
return device_memory->GetPointer(physical_address + offset);
}
- virtual void Finalize() override;
+ void Finalize() override;
- virtual bool IsInitialized() const override {
+ bool IsInitialized() const override {
return is_initialized;
}
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h
index 5ce9a1d7c..0ad74b0a0 100644
--- a/src/core/hle/kernel/k_slab_heap.h
+++ b/src/core/hle/kernel/k_slab_heap.h
@@ -11,6 +11,8 @@
namespace Kernel {
+class KernelCore;
+
namespace impl {
class KSlabHeapImpl final : NonCopyable {
@@ -135,35 +137,80 @@ private:
template <typename T>
class KSlabHeap final : public KSlabHeapBase {
public:
- constexpr KSlabHeap() : KSlabHeapBase() {}
+ enum class AllocationType {
+ Host,
+ Guest,
+ };
+
+ explicit constexpr KSlabHeap(AllocationType allocation_type_ = AllocationType::Host)
+ : KSlabHeapBase(), allocation_type{allocation_type_} {}
void Initialize(void* memory, std::size_t memory_size) {
- InitializeImpl(sizeof(T), memory, memory_size);
+ if (allocation_type == AllocationType::Guest) {
+ InitializeImpl(sizeof(T), memory, memory_size);
+ }
}
T* Allocate() {
- T* obj = static_cast<T*>(AllocateImpl());
- if (obj != nullptr) {
- new (obj) T();
+ switch (allocation_type) {
+ case AllocationType::Host:
+ // Fallback for cases where we do not yet support allocating guest memory from the slab
+ // heap, such as for kernel memory regions.
+ return new T;
+
+ case AllocationType::Guest:
+ T* obj = static_cast<T*>(AllocateImpl());
+ if (obj != nullptr) {
+ new (obj) T();
+ }
+ return obj;
}
- return obj;
+
+ UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type);
+ return nullptr;
}
T* AllocateWithKernel(KernelCore& kernel) {
- T* obj = static_cast<T*>(AllocateImpl());
- if (obj != nullptr) {
- new (obj) T(kernel);
+ switch (allocation_type) {
+ case AllocationType::Host:
+ // Fallback for cases where we do not yet support allocating guest memory from the slab
+ // heap, such as for kernel memory regions.
+ return new T(kernel);
+
+ case AllocationType::Guest:
+ T* obj = static_cast<T*>(AllocateImpl());
+ if (obj != nullptr) {
+ new (obj) T(kernel);
+ }
+ return obj;
}
- return obj;
+
+ UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type);
+ return nullptr;
}
void Free(T* obj) {
- FreeImpl(obj);
+ switch (allocation_type) {
+ case AllocationType::Host:
+ // Fallback for cases where we do not yet support allocating guest memory from the slab
+ // heap, such as for kernel memory regions.
+ delete obj;
+ return;
+
+ case AllocationType::Guest:
+ FreeImpl(obj);
+ return;
+ }
+
+ UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type);
}
constexpr std::size_t GetObjectIndex(const T* obj) const {
return GetObjectIndexImpl(obj);
}
+
+private:
+ const AllocationType allocation_type;
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h
index a41dd1220..3d4ce1fbc 100644
--- a/src/core/hle/kernel/k_synchronization_object.h
+++ b/src/core/hle/kernel/k_synchronization_object.h
@@ -29,7 +29,7 @@ public:
KSynchronizationObject** objects, const s32 num_objects,
s64 timeout);
- virtual void Finalize() override;
+ void Finalize() override;
[[nodiscard]] virtual bool IsSignaled() const = 0;
@@ -37,7 +37,7 @@ public:
protected:
explicit KSynchronizationObject(KernelCore& kernel);
- virtual ~KSynchronizationObject();
+ ~KSynchronizationObject() override;
virtual void OnFinalizeSynchronizationObject() {}
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index e3f08f256..3cf43d290 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -168,13 +168,13 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
std::memset(static_cast<void*>(std::addressof(GetStackParameters())), 0,
sizeof(StackParameters));
- // Setup the TLS, if needed.
- if (type == ThreadType::User) {
- tls_address = owner->CreateTLSRegion();
- }
-
// Set parent, if relevant.
if (owner != nullptr) {
+ // Setup the TLS, if needed.
+ if (type == ThreadType::User) {
+ tls_address = owner->CreateTLSRegion();
+ }
+
parent = owner;
parent->Open();
parent->IncrementThreadCount();
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 4abfc2b49..01eebb165 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -358,21 +358,21 @@ public:
return termination_requested || GetRawState() == ThreadState::Terminated;
}
- [[nodiscard]] virtual u64 GetId() const override final {
+ [[nodiscard]] u64 GetId() const override {
return this->GetThreadID();
}
- [[nodiscard]] virtual bool IsInitialized() const override {
+ [[nodiscard]] bool IsInitialized() const override {
return initialized;
}
- [[nodiscard]] virtual uintptr_t GetPostDestroyArgument() const override {
+ [[nodiscard]] uintptr_t GetPostDestroyArgument() const override {
return reinterpret_cast<uintptr_t>(parent) | (resource_limit_release_hint ? 1 : 0);
}
- virtual void Finalize() override;
+ void Finalize() override;
- [[nodiscard]] virtual bool IsSignaled() const override;
+ [[nodiscard]] bool IsSignaled() const override;
static void PostDestroy(uintptr_t arg);
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h
index c2d0f1eaf..31029a5c2 100644
--- a/src/core/hle/kernel/k_transfer_memory.h
+++ b/src/core/hle/kernel/k_transfer_memory.h
@@ -27,23 +27,23 @@ class KTransferMemory final
public:
explicit KTransferMemory(KernelCore& kernel_);
- virtual ~KTransferMemory() override;
+ ~KTransferMemory() override;
ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_);
- virtual void Finalize() override;
+ void Finalize() override;
- virtual bool IsInitialized() const override {
+ bool IsInitialized() const override {
return is_initialized;
}
- virtual uintptr_t GetPostDestroyArgument() const override {
+ uintptr_t GetPostDestroyArgument() const override {
return reinterpret_cast<uintptr_t>(owner);
}
static void PostDestroy(uintptr_t arg);
- KProcess* GetOwner() const {
+ KProcess* GetOwner() const override {
return owner;
}
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h
index 607b0eadb..858d982c4 100644
--- a/src/core/hle/kernel/k_writable_event.h
+++ b/src/core/hle/kernel/k_writable_event.h
@@ -21,7 +21,7 @@ public:
explicit KWritableEvent(KernelCore& kernel_);
~KWritableEvent() override;
- virtual void Destroy() override;
+ void Destroy() override;
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8b55df82e..0ffb78d51 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -258,7 +258,7 @@ struct KernelCore::Impl {
KAutoObject::Create(thread.get());
ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess());
thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));
- return std::move(thread);
+ return thread;
};
thread_local auto thread = make_thread();
@@ -620,7 +620,8 @@ struct KernelCore::Impl {
void InitializePageSlab() {
// Allocate slab heaps
- user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>();
+ user_slab_heap_pages =
+ std::make_unique<KSlabHeap<Page>>(KSlabHeap<Page>::AllocationType::Guest);
// TODO(ameerj): This should be derived, not hardcoded within the kernel
constexpr u64 user_slab_heap_size{0x3de000};
diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp
index fcb8b1ea5..b2ceeceb3 100644
--- a/src/core/hle/kernel/process_capability.cpp
+++ b/src/core/hle/kernel/process_capability.cpp
@@ -22,6 +22,7 @@ enum : u32 {
CapabilityOffset_Syscall = 4,
CapabilityOffset_MapPhysical = 6,
CapabilityOffset_MapIO = 7,
+ CapabilityOffset_MapRegion = 10,
CapabilityOffset_Interrupt = 11,
CapabilityOffset_ProgramType = 13,
CapabilityOffset_KernelVersion = 14,
@@ -46,6 +47,7 @@ enum class CapabilityType : u32 {
Syscall = (1U << CapabilityOffset_Syscall) - 1,
MapPhysical = (1U << CapabilityOffset_MapPhysical) - 1,
MapIO = (1U << CapabilityOffset_MapIO) - 1,
+ MapRegion = (1U << CapabilityOffset_MapRegion) - 1,
Interrupt = (1U << CapabilityOffset_Interrupt) - 1,
ProgramType = (1U << CapabilityOffset_ProgramType) - 1,
KernelVersion = (1U << CapabilityOffset_KernelVersion) - 1,
@@ -187,6 +189,8 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s
return HandleSyscallFlags(set_svc_bits, flag);
case CapabilityType::MapIO:
return HandleMapIOFlags(flag, page_table);
+ case CapabilityType::MapRegion:
+ return HandleMapRegionFlags(flag, page_table);
case CapabilityType::Interrupt:
return HandleInterruptFlags(flag);
case CapabilityType::ProgramType:
@@ -298,6 +302,11 @@ ResultCode ProcessCapabilities::HandleMapIOFlags(u32 flags, KPageTable& page_tab
return RESULT_SUCCESS;
}
+ResultCode ProcessCapabilities::HandleMapRegionFlags(u32 flags, KPageTable& page_table) {
+ // TODO(Lioncache): Implement once the memory manager can handle this.
+ return RESULT_SUCCESS;
+}
+
ResultCode ProcessCapabilities::HandleInterruptFlags(u32 flags) {
constexpr u32 interrupt_ignore_value = 0x3FF;
const u32 interrupt0 = (flags >> 12) & 0x3FF;
diff --git a/src/core/hle/kernel/process_capability.h b/src/core/hle/kernel/process_capability.h
index b7a9b2e45..2a7bf5505 100644
--- a/src/core/hle/kernel/process_capability.h
+++ b/src/core/hle/kernel/process_capability.h
@@ -231,6 +231,9 @@ private:
/// Handles flags related to mapping IO pages.
ResultCode HandleMapIOFlags(u32 flags, KPageTable& page_table);
+ /// Handles flags related to mapping physical memory regions.
+ ResultCode HandleMapRegionFlags(u32 flags, KPageTable& page_table);
+
/// Handles flags related to the interrupt capability flags.
ResultCode HandleInterruptFlags(u32 flags);
diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp
index 04be8a502..2ae80beca 100644
--- a/src/core/hle/kernel/service_thread.cpp
+++ b/src/core/hle/kernel/service_thread.cpp
@@ -74,21 +74,17 @@ void ServiceThread::Impl::QueueSyncRequest(KSession& session,
{
std::unique_lock lock{queue_mutex};
+ auto* server_session{&session.GetServerSession()};
+
// Open a reference to the session to ensure it is not closes while the service request
// completes asynchronously.
- session.Open();
+ server_session->Open();
- requests.emplace([session_ptr{&session}, context{std::move(context)}]() {
+ requests.emplace([server_session, context{std::move(context)}]() {
// Close the reference.
- SCOPE_EXIT({ session_ptr->Close(); });
-
- // If the session has been closed, we are done.
- if (session_ptr->IsServerClosed()) {
- return;
- }
+ SCOPE_EXIT({ server_session->Close(); });
// Complete the service request.
- KScopedAutoObject server_session{&session_ptr->GetServerSession()};
server_session->CompleteSyncRequest(*context);
});
}
diff --git a/src/core/hle/kernel/slab_helpers.h b/src/core/hle/kernel/slab_helpers.h
index d0f7f084b..0c5995db0 100644
--- a/src/core/hle/kernel/slab_helpers.h
+++ b/src/core/hle/kernel/slab_helpers.h
@@ -67,11 +67,11 @@ class KAutoObjectWithSlabHeapAndContainer : public Base {
private:
static Derived* Allocate(KernelCore& kernel) {
- return new Derived(kernel);
+ return kernel.SlabHeap<Derived>().AllocateWithKernel(kernel);
}
static void Free(KernelCore& kernel, Derived* obj) {
- delete obj;
+ kernel.SlabHeap<Derived>().Free(obj);
}
public: