hle: kernel: Migrate more of KThread to KAutoObject.

This commit is contained in:
bunnei 2021-04-03 19:11:46 -07:00
parent 6fca1c82fd
commit da7e9553de
18 changed files with 451 additions and 294 deletions

View file

@ -355,7 +355,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
KScopedSchedulerLock lock(kernel);
thread->SetState(ThreadState::Waiting);
thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming());
session->SendSyncRequest(thread, system.Memory(), system.CoreTiming());
}
KSynchronizationObject* dummy{};
@ -368,18 +368,13 @@ static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
/// Get the ID for the specified thread.
static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
return ResultInvalidHandle;
}
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Get the thread's id.
*out_thread_id = thread->GetThreadID();
*out_thread_id = thread->GetId();
return RESULT_SUCCESS;
}
@ -396,30 +391,7 @@ static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low,
/// Gets the ID of the specified process or a specified thread's owning process.
static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<Process> process = handle_table.Get<Process>(handle);
if (process) {
*process_id = process->GetProcessID();
return RESULT_SUCCESS;
}
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
if (thread) {
const Process* const owner_process = thread->GetOwnerProcess();
if (!owner_process) {
LOG_ERROR(Kernel_SVC, "Non-existent owning process encountered.");
return ResultInvalidHandle;
}
*process_id = owner_process->GetProcessID();
return RESULT_SUCCESS;
}
// NOTE: This should also handle debug objects before returning.
LOG_ERROR(Kernel_SVC, "Handle does not exist, handle=0x{:08X}", handle);
__debugbreak();
return ResultInvalidHandle;
}
@ -460,14 +432,30 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha
for (u64 i = 0; i < handle_count; ++i) {
const Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
const auto object = handle_table.Get<KSynchronizationObject>(handle);
if (object == nullptr) {
LOG_ERROR(Kernel_SVC, "Object is a nullptr");
return ResultInvalidHandle;
bool succeeded{};
{
auto object = handle_table.Get<KSynchronizationObject>(handle);
if (object) {
objects[i] = object.get();
succeeded = true;
}
}
objects[i] = object.get();
// TODO(bunnei): WORKAROUND WHILE WE HAVE TWO HANDLE TABLES
if (!succeeded) {
{
auto object = handle_table.GetObject<KSynchronizationObject>(handle);
if (object.IsNull()) {
LOG_ERROR(Kernel_SVC, "Object is a nullptr");
return ResultInvalidHandle;
}
objects[i] = object.GetPointerUnsafe();
succeeded = true;
}
}
}
return KSynchronizationObject::Wait(kernel, index, objects.data(),
static_cast<s32>(objects.size()), nano_seconds);
@ -481,19 +469,7 @@ static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u
/// Resumes a thread waiting on WaitSynchronization
static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
return ResultInvalidHandle;
}
// Cancel the thread's wait.
thread->WaitCancel();
__debugbreak();
return RESULT_SUCCESS;
}
@ -899,9 +875,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
return ResultInvalidCombination;
}
const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get<KThread>(
static_cast<Handle>(handle));
if (!thread) {
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(
static_cast<Handle>(handle));
if (thread.IsNull()) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
static_cast<Handle>(handle));
return ResultInvalidHandle;
@ -910,7 +887,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
const auto& core_timing = system.CoreTiming();
const auto& scheduler = *system.Kernel().CurrentScheduler();
const auto* const current_thread = scheduler.GetCurrentThread();
const bool same_thread = current_thread == thread.get();
const bool same_thread = current_thread == thread.GetPointerUnsafe();
const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks();
u64 out_ticks = 0;
@ -1055,45 +1032,7 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size
/// Sets the thread activity
static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle,
ThreadActivity thread_activity) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle,
thread_activity);
// Validate the activity.
constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused;
};
if (!IsValidThreadActivity(thread_activity)) {
LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})",
thread_activity);
return ResultInvalidEnumValue;
}
// Get the thread from its handle.
auto& kernel = system.Kernel();
const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
return ResultInvalidHandle;
}
// Check that the activity is being set on a non-current thread for the current process.
if (thread->GetOwnerProcess() != kernel.CurrentProcess()) {
LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread.");
return ResultInvalidHandle;
}
if (thread.get() == GetCurrentThreadPointer(kernel)) {
LOG_ERROR(Kernel_SVC, "Thread is busy");
return ResultBusy;
}
// Set the activity.
const auto set_result = thread->SetActivity(thread_activity);
if (set_result.IsError()) {
LOG_ERROR(Kernel_SVC, "Failed to set thread activity.");
return set_result;
}
__debugbreak();
return RESULT_SUCCESS;
}
@ -1107,36 +1046,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
thread_handle);
// Get the thread from its handle.
const auto* current_process = system.Kernel().CurrentProcess();
const std::shared_ptr<KThread> thread =
current_process->GetHandleTable().Get<KThread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle);
return ResultInvalidHandle;
}
// Require the handle be to a non-current thread in the current process.
if (thread->GetOwnerProcess() != current_process) {
LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process.");
return ResultInvalidHandle;
}
if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) {
LOG_ERROR(Kernel_SVC, "Current thread is busy.");
return ResultBusy;
}
// Get the thread context.
std::vector<u8> context;
const auto context_result = thread->GetThreadContext3(context);
if (context_result.IsError()) {
LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})",
context_result.raw);
return context_result;
}
// Copy the thread context to user space.
system.Memory().WriteBlock(out_context, context.data(), context.size());
__debugbreak();
return RESULT_SUCCESS;
}
@ -1164,30 +1074,26 @@ static ResultCode GetThreadPriority32(Core::System& system, u32* out_priority, H
}
/// Sets the priority for the specified thread
static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) {
LOG_TRACE(Kernel_SVC, "called");
static ResultCode SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority) {
// Get the current process.
Process& process = *system.Kernel().CurrentProcess();
// Validate the priority.
if (HighestThreadPriority > priority || priority > LowestThreadPriority) {
LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority);
return ResultInvalidPriority;
}
R_UNLESS(HighestThreadPriority <= priority && priority <= LowestThreadPriority,
ResultInvalidPriority);
R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority);
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle);
return ResultInvalidHandle;
}
KScopedAutoObject thread = process.GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Set the thread priority.
thread->SetBasePriority(priority);
return RESULT_SUCCESS;
}
static ResultCode SetThreadPriority32(Core::System& system, Handle handle, u32 priority) {
return SetThreadPriority(system, handle, priority);
static ResultCode SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority) {
return SetThreadPriority(system, thread_handle, priority);
}
/// Get which CPU core is executing the current thread
@ -1480,7 +1386,7 @@ static void ExitProcess32(Core::System& system) {
ExitProcess(system);
}
static constexpr bool IsValidCoreId(int32_t core_id) {
static constexpr bool IsValidVirtualCoreId(int32_t core_id) {
return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES));
}
@ -1500,7 +1406,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
}
// Validate arguments.
if (!IsValidCoreId(core_id)) {
if (!IsValidVirtualCoreId(core_id)) {
LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id);
return ResultInvalidCoreId;
}
@ -1822,8 +1728,11 @@ static void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high)
static ResultCode CloseHandle(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
return handle_table.Close(handle);
// Remove the handle.
R_UNLESS(system.Kernel().CurrentProcess()->GetHandleTable().Remove(handle),
ResultInvalidHandle);
return RESULT_SUCCESS;
}
static ResultCode CloseHandle32(Core::System& system, Handle handle) {
@ -1925,23 +1834,7 @@ static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u
static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
u64* out_affinity_mask) {
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle);
return ResultInvalidHandle;
}
// Get the core mask.
const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask);
if (result.IsError()) {
LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw);
return result;
}
__debugbreak();
return RESULT_SUCCESS;
}
@ -1956,58 +1849,33 @@ static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle
static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id,
u64 affinity_mask) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core_id=0x{:X}, affinity_mask=0x{:016X}",
thread_handle, core_id, affinity_mask);
const auto& current_process = *system.Kernel().CurrentProcess();
// Determine the core id/affinity mask.
if (core_id == Svc::IdealCoreUseProcessValue) {
core_id = current_process.GetIdealCoreId();
if (core_id == IdealCoreUseProcessValue) {
core_id = system.Kernel().CurrentProcess()->GetIdealCoreId();
affinity_mask = (1ULL << core_id);
} else {
// Validate the affinity mask.
const u64 process_core_mask = current_process.GetCoreMask();
if ((affinity_mask | process_core_mask) != process_core_mask) {
LOG_ERROR(Kernel_SVC,
"Affinity mask does match the process core mask (affinity mask={:016X}, core "
"mask={:016X})",
affinity_mask, process_core_mask);
return ResultInvalidCoreId;
}
if (affinity_mask == 0) {
LOG_ERROR(Kernel_SVC, "Affinity mask is zero.");
return ResultInvalidCombination;
}
const u64 process_core_mask = system.Kernel().CurrentProcess()->GetCoreMask();
R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, ResultInvalidCoreId);
R_UNLESS(affinity_mask != 0, ResultInvalidCombination);
// Validate the core id.
if (IsValidCoreId(core_id)) {
if (((1ULL << core_id) & affinity_mask) == 0) {
LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
return ResultInvalidCombination;
}
if (IsValidVirtualCoreId(core_id)) {
R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, ResultInvalidCombination);
} else {
if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) {
LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
return ResultInvalidCoreId;
}
R_UNLESS(core_id == IdealCoreNoUpdate || core_id == IdealCoreDontCare,
ResultInvalidCoreId);
}
}
// Get the thread from its handle.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
if (!thread) {
LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle);
return ResultInvalidHandle;
}
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Set the core mask.
const auto set_result = thread->SetCoreMask(core_id, affinity_mask);
if (set_result.IsError()) {
LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw);
return set_result;
}
R_TRY(thread->SetCoreMask(core_id, affinity_mask));
return RESULT_SUCCESS;
}
@ -2105,7 +1973,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o
*out_write = *write_create_result;
// Add the writable event to the handle table.
auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); });
auto handle_guard = SCOPE_GUARD({ handle_table.Remove(*write_create_result); });
// Add the readable event to the handle table.
const auto read_create_result = handle_table.Create(event->GetReadableEvent());