mirror of
https://gitlab.com/suyu-emu/suyu.git
synced 2024-03-15 23:15:44 +00:00
kernel/process: Make the handle table per-process
In the kernel, there isn't a singular handle table that everything gets tossed into or used, rather, each process gets its own handle table that it uses. This currently isn't an issue for us, since we only execute one process at the moment, but we may as well get this out of the way so it's not a headache later on.
This commit is contained in:
parent
8dc7db7e33
commit
90a981a03a
|
@ -77,7 +77,8 @@ HLERequestContext::HLERequestContext(SharedPtr<Kernel::ServerSession> server_ses
|
||||||
|
|
||||||
HLERequestContext::~HLERequestContext() = default;
|
HLERequestContext::~HLERequestContext() = default;
|
||||||
|
|
||||||
void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
|
void HLERequestContext::ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf,
|
||||||
|
bool incoming) {
|
||||||
IPC::RequestParser rp(src_cmdbuf);
|
IPC::RequestParser rp(src_cmdbuf);
|
||||||
command_header = std::make_shared<IPC::CommandHeader>(rp.PopRaw<IPC::CommandHeader>());
|
command_header = std::make_shared<IPC::CommandHeader>(rp.PopRaw<IPC::CommandHeader>());
|
||||||
|
|
||||||
|
@ -94,8 +95,6 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
|
||||||
rp.Skip(2, false);
|
rp.Skip(2, false);
|
||||||
}
|
}
|
||||||
if (incoming) {
|
if (incoming) {
|
||||||
auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
|
|
||||||
|
|
||||||
// Populate the object lists with the data in the IPC request.
|
// Populate the object lists with the data in the IPC request.
|
||||||
for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) {
|
for (u32 handle = 0; handle < handle_descriptor_header->num_handles_to_copy; ++handle) {
|
||||||
copy_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));
|
copy_objects.push_back(handle_table.GetGeneric(rp.Pop<Handle>()));
|
||||||
|
@ -189,10 +188,9 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
|
||||||
rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
|
rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf,
|
ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(const HandleTable& handle_table,
|
||||||
Process& src_process,
|
u32_le* src_cmdbuf) {
|
||||||
HandleTable& src_table) {
|
ParseCommandBuffer(handle_table, src_cmdbuf, true);
|
||||||
ParseCommandBuffer(src_cmdbuf, true);
|
|
||||||
if (command_header->type == IPC::CommandType::Close) {
|
if (command_header->type == IPC::CommandType::Close) {
|
||||||
// Close does not populate the rest of the IPC header
|
// Close does not populate the rest of the IPC header
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
@ -207,14 +205,17 @@ ResultCode HLERequestContext::PopulateFromIncomingCommandBuffer(u32_le* src_cmdb
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(const Thread& thread) {
|
ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(Thread& thread) {
|
||||||
|
auto& owner_process = *thread.GetOwnerProcess();
|
||||||
|
auto& handle_table = owner_process.GetHandleTable();
|
||||||
|
|
||||||
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmdbuf;
|
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> dst_cmdbuf;
|
||||||
Memory::ReadBlock(*thread.GetOwnerProcess(), thread.GetTLSAddress(), dst_cmdbuf.data(),
|
Memory::ReadBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(),
|
||||||
dst_cmdbuf.size() * sizeof(u32));
|
dst_cmdbuf.size() * sizeof(u32));
|
||||||
|
|
||||||
// The header was already built in the internal command buffer. Attempt to parse it to verify
|
// The header was already built in the internal command buffer. Attempt to parse it to verify
|
||||||
// the integrity and then copy it over to the target command buffer.
|
// the integrity and then copy it over to the target command buffer.
|
||||||
ParseCommandBuffer(cmd_buf.data(), false);
|
ParseCommandBuffer(handle_table, cmd_buf.data(), false);
|
||||||
|
|
||||||
// The data_size already includes the payload header, the padding and the domain header.
|
// The data_size already includes the payload header, the padding and the domain header.
|
||||||
std::size_t size = data_payload_offset + command_header->data_size -
|
std::size_t size = data_payload_offset + command_header->data_size -
|
||||||
|
@ -236,8 +237,6 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(const Thread& thread)
|
||||||
ASSERT(copy_objects.size() == handle_descriptor_header->num_handles_to_copy);
|
ASSERT(copy_objects.size() == handle_descriptor_header->num_handles_to_copy);
|
||||||
ASSERT(move_objects.size() == handle_descriptor_header->num_handles_to_move);
|
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
|
// 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
|
// services don't deal with handles directly. However, the guest applications might check
|
||||||
// for specific values in each of these descriptors.
|
// for specific values in each of these descriptors.
|
||||||
|
@ -268,7 +267,7 @@ ResultCode HLERequestContext::WriteToOutgoingCommandBuffer(const Thread& thread)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy the translated command buffer back into the thread's command buffer area.
|
// Copy the translated command buffer back into the thread's command buffer area.
|
||||||
Memory::WriteBlock(*thread.GetOwnerProcess(), thread.GetTLSAddress(), dst_cmdbuf.data(),
|
Memory::WriteBlock(owner_process, thread.GetTLSAddress(), dst_cmdbuf.data(),
|
||||||
dst_cmdbuf.size() * sizeof(u32));
|
dst_cmdbuf.size() * sizeof(u32));
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
|
|
@ -24,10 +24,10 @@ class ServiceFrameworkBase;
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
class Domain;
|
class Domain;
|
||||||
|
class Event;
|
||||||
class HandleTable;
|
class HandleTable;
|
||||||
class HLERequestContext;
|
class HLERequestContext;
|
||||||
class Process;
|
class Process;
|
||||||
class Event;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface implemented by HLE Session handlers.
|
* Interface implemented by HLE Session handlers.
|
||||||
|
@ -126,13 +126,12 @@ public:
|
||||||
u64 timeout, WakeupCallback&& callback,
|
u64 timeout, WakeupCallback&& callback,
|
||||||
Kernel::SharedPtr<Kernel::Event> event = nullptr);
|
Kernel::SharedPtr<Kernel::Event> event = nullptr);
|
||||||
|
|
||||||
void ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming);
|
|
||||||
|
|
||||||
/// Populates this context with data from the requesting process/thread.
|
/// Populates this context with data from the requesting process/thread.
|
||||||
ResultCode PopulateFromIncomingCommandBuffer(u32_le* src_cmdbuf, Process& src_process,
|
ResultCode PopulateFromIncomingCommandBuffer(const HandleTable& handle_table,
|
||||||
HandleTable& src_table);
|
u32_le* src_cmdbuf);
|
||||||
|
|
||||||
/// Writes data from this context back to the requesting process/thread.
|
/// Writes data from this context back to the requesting process/thread.
|
||||||
ResultCode WriteToOutgoingCommandBuffer(const Thread& thread);
|
ResultCode WriteToOutgoingCommandBuffer(Thread& thread);
|
||||||
|
|
||||||
u32_le GetCommand() const {
|
u32_le GetCommand() const {
|
||||||
return command;
|
return command;
|
||||||
|
@ -255,6 +254,8 @@ public:
|
||||||
std::string Description() const;
|
std::string Description() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ParseCommandBuffer(const HandleTable& handle_table, u32_le* src_cmdbuf, bool incoming);
|
||||||
|
|
||||||
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
|
||||||
SharedPtr<Kernel::ServerSession> server_session;
|
SharedPtr<Kernel::ServerSession> server_session;
|
||||||
// TODO(yuriks): Check common usage of this and optimize size accordingly
|
// TODO(yuriks): Check common usage of this and optimize size accordingly
|
||||||
|
|
|
@ -118,7 +118,6 @@ struct KernelCore::Impl {
|
||||||
process_list.clear();
|
process_list.clear();
|
||||||
current_process = nullptr;
|
current_process = nullptr;
|
||||||
|
|
||||||
handle_table.Clear();
|
|
||||||
resource_limits.fill(nullptr);
|
resource_limits.fill(nullptr);
|
||||||
|
|
||||||
thread_wakeup_callback_handle_table.Clear();
|
thread_wakeup_callback_handle_table.Clear();
|
||||||
|
@ -209,7 +208,6 @@ struct KernelCore::Impl {
|
||||||
std::vector<SharedPtr<Process>> process_list;
|
std::vector<SharedPtr<Process>> process_list;
|
||||||
Process* current_process = nullptr;
|
Process* current_process = nullptr;
|
||||||
|
|
||||||
Kernel::HandleTable handle_table;
|
|
||||||
std::array<SharedPtr<ResourceLimit>, 4> resource_limits;
|
std::array<SharedPtr<ResourceLimit>, 4> resource_limits;
|
||||||
|
|
||||||
/// The event type of the generic timer callback event
|
/// The event type of the generic timer callback event
|
||||||
|
@ -241,14 +239,6 @@ void KernelCore::Shutdown() {
|
||||||
impl->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(
|
SharedPtr<ResourceLimit> KernelCore::ResourceLimitForCategory(
|
||||||
ResourceLimitCategory category) const {
|
ResourceLimitCategory category) const {
|
||||||
return impl->resource_limits.at(static_cast<std::size_t>(category));
|
return impl->resource_limits.at(static_cast<std::size_t>(category));
|
||||||
|
|
|
@ -47,12 +47,6 @@ public:
|
||||||
/// Clears all resources in use by the kernel instance.
|
/// Clears all resources in use by the kernel instance.
|
||||||
void Shutdown();
|
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.
|
/// Retrieves a shared pointer to a ResourceLimit identified by the given category.
|
||||||
SharedPtr<ResourceLimit> ResourceLimitForCategory(ResourceLimitCategory category) const;
|
SharedPtr<ResourceLimit> ResourceLimitForCategory(ResourceLimitCategory category) const;
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <boost/container/static_vector.hpp>
|
#include <boost/container/static_vector.hpp>
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/object.h"
|
#include "core/hle/kernel/object.h"
|
||||||
#include "core/hle/kernel/thread.h"
|
#include "core/hle/kernel/thread.h"
|
||||||
#include "core/hle/kernel/vm_manager.h"
|
#include "core/hle/kernel/vm_manager.h"
|
||||||
|
@ -142,6 +143,16 @@ public:
|
||||||
return vm_manager;
|
return vm_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets a reference to the process' handle table.
|
||||||
|
HandleTable& GetHandleTable() {
|
||||||
|
return handle_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets a const reference to the process' handle table.
|
||||||
|
const HandleTable& GetHandleTable() const {
|
||||||
|
return handle_table;
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the current status of the process
|
/// Gets the current status of the process
|
||||||
ProcessStatus GetStatus() const {
|
ProcessStatus GetStatus() const {
|
||||||
return status;
|
return status;
|
||||||
|
@ -294,6 +305,9 @@ private:
|
||||||
/// specified by metadata provided to the process during loading.
|
/// specified by metadata provided to the process during loading.
|
||||||
bool is_64bit_process = true;
|
bool is_64bit_process = true;
|
||||||
|
|
||||||
|
/// Per-process handle table for storing created object handles in.
|
||||||
|
HandleTable handle_table;
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -107,8 +107,7 @@ ResultCode ServerSession::HandleSyncRequest(SharedPtr<Thread> thread) {
|
||||||
// similar.
|
// similar.
|
||||||
Kernel::HLERequestContext context(this);
|
Kernel::HLERequestContext context(this);
|
||||||
u32* cmd_buf = (u32*)Memory::GetPointer(thread->GetTLSAddress());
|
u32* cmd_buf = (u32*)Memory::GetPointer(thread->GetTLSAddress());
|
||||||
context.PopulateFromIncomingCommandBuffer(cmd_buf, *Core::CurrentProcess(),
|
context.PopulateFromIncomingCommandBuffer(kernel.CurrentProcess()->GetHandleTable(), cmd_buf);
|
||||||
kernel.HandleTable());
|
|
||||||
|
|
||||||
ResultCode result = RESULT_SUCCESS;
|
ResultCode result = RESULT_SUCCESS;
|
||||||
// If the session has been converted to a domain, handle the domain request
|
// If the session has been converted to a domain, handle the domain request
|
||||||
|
|
|
@ -189,14 +189,15 @@ static ResultCode ConnectToNamedPort(Handle* out_handle, VAddr port_name_address
|
||||||
CASCADE_RESULT(client_session, client_port->Connect());
|
CASCADE_RESULT(client_session, client_port->Connect());
|
||||||
|
|
||||||
// Return the client session
|
// Return the client session
|
||||||
CASCADE_RESULT(*out_handle, kernel.HandleTable().Create(client_session));
|
auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
|
CASCADE_RESULT(*out_handle, handle_table.Create(client_session));
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Makes a blocking IPC call to an OS service.
|
/// Makes a blocking IPC call to an OS service.
|
||||||
static ResultCode SendSyncRequest(Handle handle) {
|
static ResultCode SendSyncRequest(Handle handle) {
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
SharedPtr<ClientSession> session = kernel.HandleTable().Get<ClientSession>(handle);
|
SharedPtr<ClientSession> session = handle_table.Get<ClientSession>(handle);
|
||||||
if (!session) {
|
if (!session) {
|
||||||
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);
|
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -215,8 +216,8 @@ static ResultCode SendSyncRequest(Handle handle) {
|
||||||
static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
|
static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
|
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
|
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -229,8 +230,8 @@ static ResultCode GetThreadId(u32* thread_id, Handle thread_handle) {
|
||||||
static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
|
static ResultCode GetProcessId(u32* process_id, Handle process_handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
|
LOG_TRACE(Kernel_SVC, "called process=0x{:08X}", process_handle);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
const SharedPtr<Process> process = kernel.HandleTable().Get<Process>(process_handle);
|
const SharedPtr<Process> process = handle_table.Get<Process>(process_handle);
|
||||||
if (!process) {
|
if (!process) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -273,11 +274,11 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
|
||||||
|
|
||||||
using ObjectPtr = Thread::ThreadWaitObjects::value_type;
|
using ObjectPtr = Thread::ThreadWaitObjects::value_type;
|
||||||
Thread::ThreadWaitObjects objects(handle_count);
|
Thread::ThreadWaitObjects objects(handle_count);
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
|
|
||||||
for (u64 i = 0; i < handle_count; ++i) {
|
for (u64 i = 0; i < handle_count; ++i) {
|
||||||
const Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
|
const Handle handle = Memory::Read32(handles_address + i * sizeof(Handle));
|
||||||
const auto object = kernel.HandleTable().Get<WaitObject>(handle);
|
const auto object = handle_table.Get<WaitObject>(handle);
|
||||||
|
|
||||||
if (object == nullptr) {
|
if (object == nullptr) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
@ -325,8 +326,8 @@ static ResultCode WaitSynchronization(Handle* index, VAddr handles_address, u64
|
||||||
static ResultCode CancelSynchronization(Handle thread_handle) {
|
static ResultCode CancelSynchronization(Handle thread_handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
|
LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
|
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -354,7 +355,7 @@ static ResultCode ArbitrateLock(Handle holding_thread_handle, VAddr mutex_addr,
|
||||||
return ERR_INVALID_ADDRESS;
|
return ERR_INVALID_ADDRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
|
auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle,
|
return Mutex::TryAcquire(handle_table, mutex_addr, holding_thread_handle,
|
||||||
requesting_thread_handle);
|
requesting_thread_handle);
|
||||||
}
|
}
|
||||||
|
@ -499,13 +500,12 @@ static ResultCode SetThreadActivity(Handle handle, u32 unknown) {
|
||||||
static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
|
static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called, context=0x{:08X}, thread=0x{:X}", thread_context, handle);
|
LOG_DEBUG(Kernel_SVC, "called, context=0x{:08X}, thread=0x{:X}", thread_context, handle);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto* current_process = Core::CurrentProcess();
|
||||||
const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);
|
const SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto* current_process = Core::CurrentProcess();
|
|
||||||
if (thread->GetOwnerProcess() != current_process) {
|
if (thread->GetOwnerProcess() != current_process) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -531,10 +531,11 @@ static ResultCode GetThreadContext(VAddr thread_context, Handle handle) {
|
||||||
|
|
||||||
/// Gets the priority for the specified thread
|
/// Gets the priority for the specified thread
|
||||||
static ResultCode GetThreadPriority(u32* priority, Handle handle) {
|
static ResultCode GetThreadPriority(u32* priority, Handle handle) {
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);
|
const SharedPtr<Thread> thread = handle_table.Get<Thread>(handle);
|
||||||
if (!thread)
|
if (!thread) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
*priority = thread->GetPriority();
|
*priority = thread->GetPriority();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
@ -546,14 +547,15 @@ static ResultCode SetThreadPriority(Handle handle, u32 priority) {
|
||||||
return ERR_INVALID_THREAD_PRIORITY;
|
return ERR_INVALID_THREAD_PRIORITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto* const current_process = Core::CurrentProcess();
|
||||||
SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(handle);
|
SharedPtr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle);
|
||||||
if (!thread)
|
if (!thread) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
// Note: The kernel uses the current process's resource limit instead of
|
// Note: The kernel uses the current process's resource limit instead of
|
||||||
// the one from the thread owner's resource limit.
|
// the one from the thread owner's resource limit.
|
||||||
const ResourceLimit& resource_limit = Core::CurrentProcess()->GetResourceLimit();
|
const ResourceLimit& resource_limit = current_process->GetResourceLimit();
|
||||||
if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
|
if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
|
||||||
return ERR_NOT_AUTHORIZED;
|
return ERR_NOT_AUTHORIZED;
|
||||||
}
|
}
|
||||||
|
@ -595,15 +597,13 @@ static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 s
|
||||||
return ERR_INVALID_MEMORY_PERMISSIONS;
|
return ERR_INVALID_MEMORY_PERMISSIONS;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
auto* const current_process = Core::CurrentProcess();
|
||||||
auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
|
auto shared_memory = current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle);
|
||||||
if (!shared_memory) {
|
if (!shared_memory) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* const current_process = Core::CurrentProcess();
|
|
||||||
const auto& vm_manager = current_process->VMManager();
|
const auto& vm_manager = current_process->VMManager();
|
||||||
|
|
||||||
if (!vm_manager.IsWithinASLRRegion(addr, size)) {
|
if (!vm_manager.IsWithinASLRRegion(addr, size)) {
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
}
|
}
|
||||||
|
@ -627,15 +627,13 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
auto* const current_process = Core::CurrentProcess();
|
||||||
auto shared_memory = kernel.HandleTable().Get<SharedMemory>(shared_memory_handle);
|
auto shared_memory = current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle);
|
||||||
if (!shared_memory) {
|
if (!shared_memory) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* const current_process = Core::CurrentProcess();
|
|
||||||
const auto& vm_manager = current_process->VMManager();
|
const auto& vm_manager = current_process->VMManager();
|
||||||
|
|
||||||
if (!vm_manager.IsWithinASLRRegion(addr, size)) {
|
if (!vm_manager.IsWithinASLRRegion(addr, size)) {
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ERR_INVALID_MEMORY_RANGE;
|
||||||
}
|
}
|
||||||
|
@ -646,9 +644,8 @@ static ResultCode UnmapSharedMemory(Handle shared_memory_handle, VAddr addr, u64
|
||||||
/// Query process memory
|
/// Query process memory
|
||||||
static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_info*/,
|
static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_info*/,
|
||||||
Handle process_handle, u64 addr) {
|
Handle process_handle, u64 addr) {
|
||||||
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
SharedPtr<Process> process = handle_table.Get<Process>(process_handle);
|
||||||
SharedPtr<Process> process = kernel.HandleTable().Get<Process>(process_handle);
|
|
||||||
if (!process) {
|
if (!process) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -695,20 +692,19 @@ static void ExitProcess() {
|
||||||
/// Creates a new thread
|
/// Creates a new thread
|
||||||
static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top,
|
static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, VAddr stack_top,
|
||||||
u32 priority, s32 processor_id) {
|
u32 priority, s32 processor_id) {
|
||||||
std::string name = fmt::format("thread-{:X}", entry_point);
|
|
||||||
|
|
||||||
if (priority > THREADPRIO_LOWEST) {
|
if (priority > THREADPRIO_LOWEST) {
|
||||||
return ERR_INVALID_THREAD_PRIORITY;
|
return ERR_INVALID_THREAD_PRIORITY;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ResourceLimit& resource_limit = Core::CurrentProcess()->GetResourceLimit();
|
auto* const current_process = Core::CurrentProcess();
|
||||||
|
const ResourceLimit& resource_limit = current_process->GetResourceLimit();
|
||||||
if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
|
if (resource_limit.GetMaxResourceValue(ResourceType::Priority) > priority) {
|
||||||
return ERR_NOT_AUTHORIZED;
|
return ERR_NOT_AUTHORIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (processor_id == THREADPROCESSORID_DEFAULT) {
|
if (processor_id == THREADPROCESSORID_DEFAULT) {
|
||||||
// Set the target CPU to the one specified in the process' exheader.
|
// Set the target CPU to the one specified in the process' exheader.
|
||||||
processor_id = Core::CurrentProcess()->GetDefaultProcessorID();
|
processor_id = current_process->GetDefaultProcessorID();
|
||||||
ASSERT(processor_id != THREADPROCESSORID_DEFAULT);
|
ASSERT(processor_id != THREADPROCESSORID_DEFAULT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,11 +719,13 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
|
||||||
return ERR_INVALID_PROCESSOR_ID;
|
return ERR_INVALID_PROCESSOR_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string name = fmt::format("thread-{:X}", entry_point);
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
auto& kernel = Core::System::GetInstance().Kernel();
|
||||||
CASCADE_RESULT(SharedPtr<Thread> thread,
|
CASCADE_RESULT(SharedPtr<Thread> thread,
|
||||||
Thread::Create(kernel, name, entry_point, priority, arg, processor_id, stack_top,
|
Thread::Create(kernel, name, entry_point, priority, arg, processor_id, stack_top,
|
||||||
*Core::CurrentProcess()));
|
*current_process));
|
||||||
const auto new_guest_handle = kernel.HandleTable().Create(thread);
|
|
||||||
|
const auto new_guest_handle = current_process->GetHandleTable().Create(thread);
|
||||||
if (new_guest_handle.Failed()) {
|
if (new_guest_handle.Failed()) {
|
||||||
return new_guest_handle.Code();
|
return new_guest_handle.Code();
|
||||||
}
|
}
|
||||||
|
@ -748,8 +746,8 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
|
||||||
static ResultCode StartThread(Handle thread_handle) {
|
static ResultCode StartThread(Handle thread_handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
|
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
|
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -796,8 +794,8 @@ static ResultCode WaitProcessWideKeyAtomic(VAddr mutex_addr, VAddr condition_var
|
||||||
"called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}",
|
"called mutex_addr={:X}, condition_variable_addr={:X}, thread_handle=0x{:08X}, timeout={}",
|
||||||
mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
|
mutex_addr, condition_variable_addr, thread_handle, nano_seconds);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
|
SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
|
||||||
ASSERT(thread);
|
ASSERT(thread);
|
||||||
|
|
||||||
CASCADE_CODE(Mutex::Release(mutex_addr));
|
CASCADE_CODE(Mutex::Release(mutex_addr));
|
||||||
|
@ -908,9 +906,9 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
|
||||||
mutex_val | Mutex::MutexHasWaitersFlag));
|
mutex_val | Mutex::MutexHasWaitersFlag));
|
||||||
|
|
||||||
// The mutex is already owned by some other thread, make this thread wait on it.
|
// The mutex is already owned by some other thread, make this thread wait on it.
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
|
||||||
Handle owner_handle = static_cast<Handle>(mutex_val & Mutex::MutexOwnerMask);
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
auto owner = kernel.HandleTable().Get<Thread>(owner_handle);
|
auto owner = handle_table.Get<Thread>(owner_handle);
|
||||||
ASSERT(owner);
|
ASSERT(owner);
|
||||||
ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex);
|
ASSERT(thread->GetStatus() == ThreadStatus::WaitMutex);
|
||||||
thread->InvalidateWakeupCallback();
|
thread->InvalidateWakeupCallback();
|
||||||
|
@ -989,16 +987,16 @@ static u64 GetSystemTick() {
|
||||||
static ResultCode CloseHandle(Handle handle) {
|
static ResultCode CloseHandle(Handle handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
|
LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
return kernel.HandleTable().Close(handle);
|
return handle_table.Close(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset an event
|
/// Reset an event
|
||||||
static ResultCode ResetSignal(Handle handle) {
|
static ResultCode ResetSignal(Handle handle) {
|
||||||
LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x{:08X}", handle);
|
LOG_WARNING(Kernel_SVC, "(STUBBED) called handle 0x{:08X}", handle);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
auto event = kernel.HandleTable().Get<Event>(handle);
|
auto event = handle_table.Get<Event>(handle);
|
||||||
|
|
||||||
ASSERT(event != nullptr);
|
ASSERT(event != nullptr);
|
||||||
|
|
||||||
|
@ -1017,8 +1015,8 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
|
||||||
static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) {
|
static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
|
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
|
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -1033,8 +1031,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,
|
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:16X}, core=0x{:X}", thread_handle,
|
||||||
mask, core);
|
mask, core);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
const SharedPtr<Thread> thread = kernel.HandleTable().Get<Thread>(thread_handle);
|
const SharedPtr<Thread> thread = handle_table.Get<Thread>(thread_handle);
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
@ -1095,7 +1093,7 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
auto& kernel = Core::System::GetInstance().Kernel();
|
||||||
auto& handle_table = kernel.HandleTable();
|
auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
auto shared_mem_handle =
|
auto shared_mem_handle =
|
||||||
SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
|
SharedMemory::Create(kernel, handle_table.Get<Process>(KernelHandle::CurrentProcess), size,
|
||||||
local_perms, remote_perms);
|
local_perms, remote_perms);
|
||||||
|
@ -1107,10 +1105,12 @@ static ResultCode CreateSharedMemory(Handle* handle, u64 size, u32 local_permiss
|
||||||
static ResultCode ClearEvent(Handle handle) {
|
static ResultCode ClearEvent(Handle handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
|
LOG_TRACE(Kernel_SVC, "called, event=0x{:08X}", handle);
|
||||||
|
|
||||||
auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
SharedPtr<Event> evt = kernel.HandleTable().Get<Event>(handle);
|
SharedPtr<Event> evt = handle_table.Get<Event>(handle);
|
||||||
if (evt == nullptr)
|
if (evt == nullptr) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
evt->Clear();
|
evt->Clear();
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1123,8 +1123,8 @@ static ResultCode GetProcessInfo(u64* out, Handle process_handle, u32 type) {
|
||||||
Status,
|
Status,
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto& kernel = Core::System::GetInstance().Kernel();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
const auto process = kernel.HandleTable().Get<Process>(process_handle);
|
const auto process = handle_table.Get<Process>(process_handle);
|
||||||
if (!process) {
|
if (!process) {
|
||||||
return ERR_INVALID_HANDLE;
|
return ERR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -266,7 +266,7 @@ SharedPtr<Thread> SetupMainThread(KernelCore& kernel, VAddr entry_point, u32 pri
|
||||||
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
|
SharedPtr<Thread> thread = std::move(thread_res).Unwrap();
|
||||||
|
|
||||||
// Register 1 must be a handle to the main thread
|
// Register 1 must be a handle to the main thread
|
||||||
const Handle guest_handle = kernel.HandleTable().Create(thread).Unwrap();
|
const Handle guest_handle = owner_process.GetHandleTable().Create(thread).Unwrap();
|
||||||
thread->SetGuestHandle(guest_handle);
|
thread->SetGuestHandle(guest_handle);
|
||||||
thread->GetContext().cpu_registers[1] = guest_handle;
|
thread->GetContext().cpu_registers[1] = guest_handle;
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/event.h"
|
#include "core/hle/kernel/event.h"
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
|
||||||
#include "core/hle/kernel/mutex.h"
|
#include "core/hle/kernel/mutex.h"
|
||||||
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/scheduler.h"
|
#include "core/hle/kernel/scheduler.h"
|
||||||
#include "core/hle/kernel/thread.h"
|
#include "core/hle/kernel/thread.h"
|
||||||
#include "core/hle/kernel/timer.h"
|
#include "core/hle/kernel/timer.h"
|
||||||
|
@ -83,7 +83,7 @@ QString WaitTreeText::GetText() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address) : mutex_address(mutex_address) {
|
WaitTreeMutexInfo::WaitTreeMutexInfo(VAddr mutex_address) : mutex_address(mutex_address) {
|
||||||
auto& handle_table = Core::System::GetInstance().Kernel().HandleTable();
|
const auto& handle_table = Core::CurrentProcess()->GetHandleTable();
|
||||||
|
|
||||||
mutex_value = Memory::Read32(mutex_address);
|
mutex_value = Memory::Read32(mutex_address);
|
||||||
owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Mutex::MutexOwnerMask);
|
owner_handle = static_cast<Kernel::Handle>(mutex_value & Kernel::Mutex::MutexOwnerMask);
|
||||||
|
|
Loading…
Reference in a new issue