summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2021-01-29 23:06:40 -0800
committerGravatar GitHub2021-01-29 23:06:40 -0800
commita4526c4e1acb50808bbe205952101142288e1c60 (patch)
tree7109edf89606c43352da9de40d0e3a920a08b659 /src/core/hle/kernel/svc.cpp
parentMerge pull request #5795 from ReinUsesLisp/bytes-to-map-end (diff)
parenthle: kernel: KLightLock: Fix several bugs. (diff)
downloadyuzu-a4526c4e1acb50808bbe205952101142288e1c60.tar.gz
yuzu-a4526c4e1acb50808bbe205952101142288e1c60.tar.xz
yuzu-a4526c4e1acb50808bbe205952101142288e1c60.zip
Merge pull request #5779 from bunnei/kthread-rewrite
Rewrite KThread to be more accurate
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp439
1 files changed, 187 insertions, 252 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index cc8b661af..7fd514e9d 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -29,6 +29,7 @@
29#include "core/hle/kernel/k_scheduler.h" 29#include "core/hle/kernel/k_scheduler.h"
30#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 30#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
31#include "core/hle/kernel/k_synchronization_object.h" 31#include "core/hle/kernel/k_synchronization_object.h"
32#include "core/hle/kernel/k_thread.h"
32#include "core/hle/kernel/kernel.h" 33#include "core/hle/kernel/kernel.h"
33#include "core/hle/kernel/memory/memory_block.h" 34#include "core/hle/kernel/memory/memory_block.h"
34#include "core/hle/kernel/memory/memory_layout.h" 35#include "core/hle/kernel/memory/memory_layout.h"
@@ -42,7 +43,6 @@
42#include "core/hle/kernel/svc_results.h" 43#include "core/hle/kernel/svc_results.h"
43#include "core/hle/kernel/svc_types.h" 44#include "core/hle/kernel/svc_types.h"
44#include "core/hle/kernel/svc_wrap.h" 45#include "core/hle/kernel/svc_wrap.h"
45#include "core/hle/kernel/thread.h"
46#include "core/hle/kernel/time_manager.h" 46#include "core/hle/kernel/time_manager.h"
47#include "core/hle/kernel/transfer_memory.h" 47#include "core/hle/kernel/transfer_memory.h"
48#include "core/hle/kernel/writable_event.h" 48#include "core/hle/kernel/writable_event.h"
@@ -351,7 +351,8 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
351 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); 351 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming());
352 } 352 }
353 353
354 return thread->GetSignalingResult(); 354 KSynchronizationObject* dummy{};
355 return thread->GetWaitResult(std::addressof(dummy));
355} 356}
356 357
357static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { 358static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
@@ -359,27 +360,26 @@ static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
359} 360}
360 361
361/// Get the ID for the specified thread. 362/// Get the ID for the specified thread.
362static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle thread_handle) { 363static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) {
363 LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); 364 LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
364 365
366 // Get the thread from its handle.
365 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 367 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
366 const std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); 368 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
367 if (!thread) { 369 R_UNLESS(thread, Svc::ResultInvalidHandle);
368 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", thread_handle);
369 return ERR_INVALID_HANDLE;
370 }
371 370
372 *thread_id = thread->GetThreadID(); 371 // Get the thread's id.
372 *out_thread_id = thread->GetThreadID();
373 return RESULT_SUCCESS; 373 return RESULT_SUCCESS;
374} 374}
375 375
376static ResultCode GetThreadId32(Core::System& system, u32* thread_id_low, u32* thread_id_high, 376static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low,
377 Handle thread_handle) { 377 u32* out_thread_id_high, Handle thread_handle) {
378 u64 thread_id{}; 378 u64 out_thread_id{};
379 const ResultCode result{GetThreadId(system, &thread_id, thread_handle)}; 379 const ResultCode result{GetThreadId(system, &out_thread_id, thread_handle)};
380 380
381 *thread_id_low = static_cast<u32>(thread_id >> 32); 381 *out_thread_id_low = static_cast<u32>(out_thread_id >> 32);
382 *thread_id_high = static_cast<u32>(thread_id & std::numeric_limits<u32>::max()); 382 *out_thread_id_high = static_cast<u32>(out_thread_id & std::numeric_limits<u32>::max());
383 383
384 return result; 384 return result;
385} 385}
@@ -395,7 +395,7 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han
395 return RESULT_SUCCESS; 395 return RESULT_SUCCESS;
396 } 396 }
397 397
398 const std::shared_ptr<Thread> thread = handle_table.Get<Thread>(handle); 398 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
399 if (thread) { 399 if (thread) {
400 const Process* const owner_process = thread->GetOwnerProcess(); 400 const Process* const owner_process = thread->GetOwnerProcess();
401 if (!owner_process) { 401 if (!owner_process) {
@@ -473,15 +473,13 @@ static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u
473static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) { 473static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) {
474 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); 474 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
475 475
476 // Get the thread from its handle.
476 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 477 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
477 std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); 478 std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
478 if (!thread) { 479 R_UNLESS(thread, Svc::ResultInvalidHandle);
479 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
480 thread_handle);
481 return ERR_INVALID_HANDLE;
482 }
483 480
484 thread->CancelWait(); 481 // Cancel the thread's wait.
482 thread->WaitCancel();
485 return RESULT_SUCCESS; 483 return RESULT_SUCCESS;
486} 484}
487 485
@@ -630,7 +628,7 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
630 handle_debug_buffer(info1, info2); 628 handle_debug_buffer(info1, info2);
631 629
632 auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); 630 auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
633 const auto thread_processor_id = current_thread->GetProcessorID(); 631 const auto thread_processor_id = current_thread->GetActiveCore();
634 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); 632 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
635 } 633 }
636} 634}
@@ -872,7 +870,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
872 return ERR_INVALID_COMBINATION; 870 return ERR_INVALID_COMBINATION;
873 } 871 }
874 872
875 const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get<Thread>( 873 const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get<KThread>(
876 static_cast<Handle>(handle)); 874 static_cast<Handle>(handle));
877 if (!thread) { 875 if (!thread) {
878 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", 876 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
@@ -888,7 +886,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
888 const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks(); 886 const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks();
889 u64 out_ticks = 0; 887 u64 out_ticks = 0;
890 if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) { 888 if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
891 const u64 thread_ticks = current_thread->GetTotalCPUTimeTicks(); 889 const u64 thread_ticks = current_thread->GetCpuTime();
892 890
893 out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks); 891 out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks);
894 } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) { 892 } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) {
@@ -1025,129 +1023,109 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size
1025 return UnmapPhysicalMemory(system, addr, size); 1023 return UnmapPhysicalMemory(system, addr, size);
1026} 1024}
1027 1025
1028/// Sets the thread activity 1026constexpr bool IsValidThreadActivity(Svc::ThreadActivity thread_activity) {
1029static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 activity) { 1027 switch (thread_activity) {
1030 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity); 1028 case Svc::ThreadActivity::Runnable:
1031 if (activity > static_cast<u32>(ThreadActivity::Paused)) { 1029 case Svc::ThreadActivity::Paused:
1032 return ERR_INVALID_ENUM_VALUE; 1030 return true;
1031 default:
1032 return false;
1033 } 1033 }
1034}
1034 1035
1035 const auto* current_process = system.Kernel().CurrentProcess(); 1036/// Sets the thread activity
1036 const std::shared_ptr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle); 1037static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle,
1037 if (!thread) { 1038 Svc::ThreadActivity thread_activity) {
1038 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); 1039 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle,
1039 return ERR_INVALID_HANDLE; 1040 thread_activity);
1040 }
1041 1041
1042 if (thread->GetOwnerProcess() != current_process) { 1042 // Validate the activity.
1043 LOG_ERROR(Kernel_SVC, 1043 R_UNLESS(IsValidThreadActivity(thread_activity), Svc::ResultInvalidEnumValue);
1044 "The current process does not own the current thread, thread_handle={:08X} "
1045 "thread_pid={}, "
1046 "current_process_pid={}",
1047 handle, thread->GetOwnerProcess()->GetProcessID(),
1048 current_process->GetProcessID());
1049 return ERR_INVALID_HANDLE;
1050 }
1051 1044
1052 if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { 1045 // Get the thread from its handle.
1053 LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); 1046 auto& kernel = system.Kernel();
1054 return ERR_BUSY; 1047 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
1055 } 1048 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1049 R_UNLESS(thread, Svc::ResultInvalidHandle);
1050
1051 // Check that the activity is being set on a non-current thread for the current process.
1052 R_UNLESS(thread->GetOwnerProcess() == kernel.CurrentProcess(), Svc::ResultInvalidHandle);
1053 R_UNLESS(thread.get() != GetCurrentThreadPointer(kernel), Svc::ResultBusy);
1054
1055 // Set the activity.
1056 R_TRY(thread->SetActivity(thread_activity));
1056 1057
1057 return thread->SetActivity(static_cast<ThreadActivity>(activity)); 1058 return RESULT_SUCCESS;
1058} 1059}
1059 1060
1060static ResultCode SetThreadActivity32(Core::System& system, Handle handle, u32 activity) { 1061static ResultCode SetThreadActivity32(Core::System& system, Handle thread_handle,
1061 return SetThreadActivity(system, handle, activity); 1062 Svc::ThreadActivity thread_activity) {
1063 return SetThreadActivity(system, thread_handle, thread_activity);
1062} 1064}
1063 1065
1064/// Gets the thread context 1066/// Gets the thread context
1065static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, Handle handle) { 1067static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Handle thread_handle) {
1066 LOG_DEBUG(Kernel_SVC, "called, context=0x{:08X}, thread=0x{:X}", thread_context, handle); 1068 LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
1069 thread_handle);
1067 1070
1071 // Get the thread from its handle.
1068 const auto* current_process = system.Kernel().CurrentProcess(); 1072 const auto* current_process = system.Kernel().CurrentProcess();
1069 const std::shared_ptr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle); 1073 const std::shared_ptr<KThread> thread =
1070 if (!thread) { 1074 current_process->GetHandleTable().Get<KThread>(thread_handle);
1071 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); 1075 R_UNLESS(thread, Svc::ResultInvalidHandle);
1072 return ERR_INVALID_HANDLE;
1073 }
1074 1076
1075 if (thread->GetOwnerProcess() != current_process) { 1077 // Require the handle be to a non-current thread in the current process.
1076 LOG_ERROR(Kernel_SVC, 1078 R_UNLESS(thread->GetOwnerProcess() == current_process, Svc::ResultInvalidHandle);
1077 "The current process does not own the current thread, thread_handle={:08X} " 1079 R_UNLESS(thread.get() != system.Kernel().CurrentScheduler()->GetCurrentThread(),
1078 "thread_pid={}, " 1080 Svc::ResultBusy);
1079 "current_process_pid={}",
1080 handle, thread->GetOwnerProcess()->GetProcessID(),
1081 current_process->GetProcessID());
1082 return ERR_INVALID_HANDLE;
1083 }
1084 1081
1085 if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { 1082 // Get the thread context.
1086 LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); 1083 std::vector<u8> context;
1087 return ERR_BUSY; 1084 R_TRY(thread->GetThreadContext3(context));
1088 }
1089
1090 Core::ARM_Interface::ThreadContext64 ctx = thread->GetContext64();
1091 // Mask away mode bits, interrupt bits, IL bit, and other reserved bits.
1092 ctx.pstate &= 0xFF0FFE20;
1093 1085
1094 // If 64-bit, we can just write the context registers directly and we're good. 1086 // Copy the thread context to user space.
1095 // However, if 32-bit, we have to ensure some registers are zeroed out. 1087 system.Memory().WriteBlock(out_context, context.data(), context.size());
1096 if (!current_process->Is64BitProcess()) {
1097 std::fill(ctx.cpu_registers.begin() + 15, ctx.cpu_registers.end(), 0);
1098 std::fill(ctx.vector_registers.begin() + 16, ctx.vector_registers.end(), u128{});
1099 }
1100 1088
1101 system.Memory().WriteBlock(thread_context, &ctx, sizeof(ctx));
1102 return RESULT_SUCCESS; 1089 return RESULT_SUCCESS;
1103} 1090}
1104 1091
1105static ResultCode GetThreadContext32(Core::System& system, u32 thread_context, Handle handle) { 1092static ResultCode GetThreadContext32(Core::System& system, u32 out_context, Handle thread_handle) {
1106 return GetThreadContext(system, thread_context, handle); 1093 return GetThreadContext(system, out_context, thread_handle);
1107} 1094}
1108 1095
1109/// Gets the priority for the specified thread 1096/// Gets the priority for the specified thread
1110static ResultCode GetThreadPriority(Core::System& system, u32* priority, Handle handle) { 1097static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Handle handle) {
1111 LOG_TRACE(Kernel_SVC, "called"); 1098 LOG_TRACE(Kernel_SVC, "called");
1112 1099
1100 // Get the thread from its handle.
1113 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1101 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1114 const std::shared_ptr<Thread> thread = handle_table.Get<Thread>(handle); 1102 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
1115 if (!thread) { 1103 R_UNLESS(thread, Svc::ResultInvalidHandle);
1116 *priority = 0;
1117 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
1118 return ERR_INVALID_HANDLE;
1119 }
1120 1104
1121 *priority = thread->GetPriority(); 1105 // Get the thread's priority.
1106 *out_priority = thread->GetPriority();
1122 return RESULT_SUCCESS; 1107 return RESULT_SUCCESS;
1123} 1108}
1124 1109
1125static ResultCode GetThreadPriority32(Core::System& system, u32* priority, Handle handle) { 1110static ResultCode GetThreadPriority32(Core::System& system, u32* out_priority, Handle handle) {
1126 return GetThreadPriority(system, priority, handle); 1111 return GetThreadPriority(system, out_priority, handle);
1127} 1112}
1128 1113
1129/// Sets the priority for the specified thread 1114/// Sets the priority for the specified thread
1130static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) { 1115static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) {
1131 LOG_TRACE(Kernel_SVC, "called"); 1116 LOG_TRACE(Kernel_SVC, "called");
1132 1117
1133 if (priority > THREADPRIO_LOWEST) { 1118 // Validate the priority.
1134 LOG_ERROR( 1119 R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority,
1135 Kernel_SVC, 1120 Svc::ResultInvalidPriority);
1136 "An invalid priority was specified, expected {} but got {} for thread_handle={:08X}",
1137 THREADPRIO_LOWEST, priority, handle);
1138 return ERR_INVALID_THREAD_PRIORITY;
1139 }
1140 1121
1141 const auto* const current_process = system.Kernel().CurrentProcess(); 1122 // Get the thread from its handle.
1142 1123 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1143 std::shared_ptr<Thread> thread = current_process->GetHandleTable().Get<Thread>(handle); 1124 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
1144 if (!thread) { 1125 R_UNLESS(thread, Svc::ResultInvalidHandle);
1145 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
1146 return ERR_INVALID_HANDLE;
1147 }
1148 1126
1127 // Set the thread priority.
1149 thread->SetBasePriority(priority); 1128 thread->SetBasePriority(priority);
1150
1151 return RESULT_SUCCESS; 1129 return RESULT_SUCCESS;
1152} 1130}
1153 1131
@@ -1438,62 +1416,50 @@ static void ExitProcess(Core::System& system) {
1438 current_process->PrepareForTermination(); 1416 current_process->PrepareForTermination();
1439 1417
1440 // Kill the current thread 1418 // Kill the current thread
1441 system.Kernel().CurrentScheduler()->GetCurrentThread()->Stop(); 1419 system.Kernel().CurrentScheduler()->GetCurrentThread()->Exit();
1442} 1420}
1443 1421
1444static void ExitProcess32(Core::System& system) { 1422static void ExitProcess32(Core::System& system) {
1445 ExitProcess(system); 1423 ExitProcess(system);
1446} 1424}
1447 1425
1426static constexpr bool IsValidCoreId(int32_t core_id) {
1427 return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES));
1428}
1429
1448/// Creates a new thread 1430/// Creates a new thread
1449static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg, 1431static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg,
1450 VAddr stack_top, u32 priority, s32 processor_id) { 1432 VAddr stack_bottom, u32 priority, s32 core_id) {
1451 LOG_DEBUG(Kernel_SVC, 1433 LOG_DEBUG(Kernel_SVC,
1452 "called entrypoint=0x{:08X}, arg=0x{:08X}, stacktop=0x{:08X}, " 1434 "called entry_point=0x{:08X}, arg=0x{:08X}, stack_bottom=0x{:08X}, "
1453 "threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}", 1435 "priority=0x{:08X}, core_id=0x{:08X}",
1454 entry_point, arg, stack_top, priority, processor_id, *out_handle); 1436 entry_point, arg, stack_bottom, priority, core_id);
1455 1437
1456 auto* const current_process = system.Kernel().CurrentProcess(); 1438 // Adjust core id, if it's the default magic.
1457 1439 auto& kernel = system.Kernel();
1458 if (processor_id == THREADPROCESSORID_IDEAL) { 1440 auto& process = *kernel.CurrentProcess();
1459 // Set the target CPU to the one specified by the process. 1441 if (core_id == Svc::IdealCoreUseProcessValue) {
1460 processor_id = current_process->GetIdealCore(); 1442 core_id = process.GetIdealCoreId();
1461 ASSERT(processor_id != THREADPROCESSORID_IDEAL);
1462 } 1443 }
1463 1444
1464 if (processor_id < THREADPROCESSORID_0 || processor_id > THREADPROCESSORID_3) { 1445 // Validate arguments.
1465 LOG_ERROR(Kernel_SVC, "Invalid thread processor ID: {}", processor_id); 1446 R_UNLESS(IsValidCoreId(core_id), Svc::ResultInvalidCoreId);
1466 return ERR_INVALID_PROCESSOR_ID; 1447 R_UNLESS(((1ULL << core_id) & process.GetCoreMask()) != 0, Svc::ResultInvalidCoreId);
1467 }
1468 1448
1469 const u64 core_mask = current_process->GetCoreMask(); 1449 R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority,
1470 if ((core_mask | (1ULL << processor_id)) != core_mask) { 1450 Svc::ResultInvalidPriority);
1471 LOG_ERROR(Kernel_SVC, "Invalid thread core specified ({})", processor_id); 1451 R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority);
1472 return ERR_INVALID_PROCESSOR_ID;
1473 }
1474 1452
1475 if (priority > THREADPRIO_LOWEST) { 1453 ASSERT(process.GetResourceLimit()->Reserve(ResourceType::Threads, 1));
1476 LOG_ERROR(Kernel_SVC,
1477 "Invalid thread priority specified ({}). Must be within the range 0-64",
1478 priority);
1479 return ERR_INVALID_THREAD_PRIORITY;
1480 }
1481 1454
1482 if (((1ULL << priority) & current_process->GetPriorityMask()) == 0) { 1455 std::shared_ptr<KThread> thread;
1483 LOG_ERROR(Kernel_SVC, "Invalid thread priority specified ({})", priority); 1456 {
1484 return ERR_INVALID_THREAD_PRIORITY; 1457 KScopedLightLock lk{process.GetStateLock()};
1458 CASCADE_RESULT(thread, KThread::Create(system, ThreadType::User, "", entry_point, priority,
1459 arg, core_id, stack_bottom, &process));
1485 } 1460 }
1486 1461
1487 auto& kernel = system.Kernel(); 1462 const auto new_thread_handle = process.GetHandleTable().Create(thread);
1488
1489 ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Threads, 1));
1490
1491 ThreadType type = THREADTYPE_USER;
1492 CASCADE_RESULT(std::shared_ptr<Thread> thread,
1493 Thread::Create(system, type, "", entry_point, priority, arg, processor_id,
1494 stack_top, current_process));
1495
1496 const auto new_thread_handle = current_process->GetHandleTable().Create(thread);
1497 if (new_thread_handle.Failed()) { 1463 if (new_thread_handle.Failed()) {
1498 LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}", 1464 LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}",
1499 new_thread_handle.Code().raw); 1465 new_thread_handle.Code().raw);
@@ -1517,17 +1483,15 @@ static ResultCode CreateThread32(Core::System& system, Handle* out_handle, u32 p
1517static ResultCode StartThread(Core::System& system, Handle thread_handle) { 1483static ResultCode StartThread(Core::System& system, Handle thread_handle) {
1518 LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); 1484 LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
1519 1485
1486 // Get the thread from its handle.
1520 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1487 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1521 const std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); 1488 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1522 if (!thread) { 1489 R_UNLESS(thread, Svc::ResultInvalidHandle);
1523 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
1524 thread_handle);
1525 return ERR_INVALID_HANDLE;
1526 }
1527 1490
1528 ASSERT(thread->GetState() == ThreadState::Initialized); 1491 // Try to start the thread.
1492 R_TRY(thread->Run());
1529 1493
1530 return thread->Start(); 1494 return RESULT_SUCCESS;
1531} 1495}
1532 1496
1533static ResultCode StartThread32(Core::System& system, Handle thread_handle) { 1497static ResultCode StartThread32(Core::System& system, Handle thread_handle) {
@@ -1540,7 +1504,7 @@ static void ExitThread(Core::System& system) {
1540 1504
1541 auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); 1505 auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
1542 system.GlobalSchedulerContext().RemoveThread(SharedFrom(current_thread)); 1506 system.GlobalSchedulerContext().RemoveThread(SharedFrom(current_thread));
1543 current_thread->Stop(); 1507 current_thread->Exit();
1544} 1508}
1545 1509
1546static void ExitThread32(Core::System& system) { 1510static void ExitThread32(Core::System& system) {
@@ -1549,34 +1513,28 @@ static void ExitThread32(Core::System& system) {
1549 1513
1550/// Sleep the current thread 1514/// Sleep the current thread
1551static void SleepThread(Core::System& system, s64 nanoseconds) { 1515static void SleepThread(Core::System& system, s64 nanoseconds) {
1552 LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); 1516 auto& kernel = system.Kernel();
1517 const auto yield_type = static_cast<Svc::YieldType>(nanoseconds);
1553 1518
1554 enum class SleepType : s64 { 1519 LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
1555 YieldWithoutCoreMigration = 0,
1556 YieldWithCoreMigration = -1,
1557 YieldAndWaitForLoadBalancing = -2,
1558 };
1559 1520
1560 auto& scheduler = *system.Kernel().CurrentScheduler(); 1521 // When the input tick is positive, sleep.
1561 if (nanoseconds <= 0) { 1522 if (nanoseconds > 0) {
1562 switch (static_cast<SleepType>(nanoseconds)) { 1523 // Convert the timeout from nanoseconds to ticks.
1563 case SleepType::YieldWithoutCoreMigration: { 1524 // NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
1564 scheduler.YieldWithoutCoreMigration(); 1525
1565 break; 1526 // Sleep.
1566 } 1527 // NOTE: Nintendo does not check the result of this sleep.
1567 case SleepType::YieldWithCoreMigration: { 1528 static_cast<void>(GetCurrentThread(kernel).Sleep(nanoseconds));
1568 scheduler.YieldWithCoreMigration(); 1529 } else if (yield_type == Svc::YieldType::WithoutCoreMigration) {
1569 break; 1530 KScheduler::YieldWithoutCoreMigration(kernel);
1570 } 1531 } else if (yield_type == Svc::YieldType::WithCoreMigration) {
1571 case SleepType::YieldAndWaitForLoadBalancing: { 1532 KScheduler::YieldWithCoreMigration(kernel);
1572 scheduler.YieldToAnyThread(); 1533 } else if (yield_type == Svc::YieldType::ToAnyThread) {
1573 break; 1534 KScheduler::YieldToAnyThread(kernel);
1574 }
1575 default:
1576 UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
1577 }
1578 } else { 1535 } else {
1579 scheduler.GetCurrentThread()->Sleep(nanoseconds); 1536 // Nintendo does nothing at all if an otherwise invalid value is passed.
1537 UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
1580 } 1538 }
1581} 1539}
1582 1540
@@ -1839,95 +1797,72 @@ static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u
1839 return CreateTransferMemory(system, handle, addr, size, permissions); 1797 return CreateTransferMemory(system, handle, addr, size, permissions);
1840} 1798}
1841 1799
1842static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core, 1800static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
1843 u64* mask) { 1801 u64* out_affinity_mask) {
1844 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); 1802 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
1845 1803
1804 // Get the thread from its handle.
1846 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1805 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1847 const std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); 1806 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1848 if (!thread) { 1807 R_UNLESS(thread, Svc::ResultInvalidHandle);
1849 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
1850 thread_handle);
1851 *core = 0;
1852 *mask = 0;
1853 return ERR_INVALID_HANDLE;
1854 }
1855 1808
1856 *core = thread->GetIdealCore(); 1809 // Get the core mask.
1857 *mask = thread->GetAffinityMask().GetAffinityMask(); 1810 R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask));
1858 1811
1859 return RESULT_SUCCESS; 1812 return RESULT_SUCCESS;
1860} 1813}
1861 1814
1862static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle, u32* core, 1815static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle, s32* out_core_id,
1863 u32* mask_low, u32* mask_high) { 1816 u32* out_affinity_mask_low, u32* out_affinity_mask_high) {
1864 u64 mask{}; 1817 u64 out_affinity_mask{};
1865 const auto result = GetThreadCoreMask(system, thread_handle, core, &mask); 1818 const auto result = GetThreadCoreMask(system, thread_handle, out_core_id, &out_affinity_mask);
1866 *mask_high = static_cast<u32>(mask >> 32); 1819 *out_affinity_mask_high = static_cast<u32>(out_affinity_mask >> 32);
1867 *mask_low = static_cast<u32>(mask); 1820 *out_affinity_mask_low = static_cast<u32>(out_affinity_mask);
1868 return result; 1821 return result;
1869} 1822}
1870 1823
1871static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core, 1824static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id,
1872 u64 affinity_mask) { 1825 u64 affinity_mask) {
1873 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core=0x{:X}, affinity_mask=0x{:016X}", 1826 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core_id=0x{:X}, affinity_mask=0x{:016X}",
1874 thread_handle, core, affinity_mask); 1827 thread_handle, core_id, affinity_mask);
1875
1876 const auto* const current_process = system.Kernel().CurrentProcess();
1877 1828
1878 if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) { 1829 const auto& current_process = *system.Kernel().CurrentProcess();
1879 const u8 ideal_cpu_core = current_process->GetIdealCore();
1880 1830
1881 ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL)); 1831 // Determine the core id/affinity mask.
1882 1832 if (core_id == Svc::IdealCoreUseProcessValue) {
1883 // Set the target CPU to the ideal core specified by the process. 1833 core_id = current_process.GetIdealCoreId();
1884 core = ideal_cpu_core; 1834 affinity_mask = (1ULL << core_id);
1885 affinity_mask = 1ULL << core;
1886 } else { 1835 } else {
1887 const u64 core_mask = current_process->GetCoreMask(); 1836 // Validate the affinity mask.
1888 1837 const u64 process_core_mask = current_process.GetCoreMask();
1889 if ((core_mask | affinity_mask) != core_mask) { 1838 R_UNLESS((affinity_mask | process_core_mask) == process_core_mask,
1890 LOG_ERROR( 1839 Svc::ResultInvalidCoreId);
1891 Kernel_SVC, 1840 R_UNLESS(affinity_mask != 0, Svc::ResultInvalidCombination);
1892 "Invalid processor ID specified (core_mask=0x{:08X}, affinity_mask=0x{:016X})", 1841
1893 core_mask, affinity_mask); 1842 // Validate the core id.
1894 return ERR_INVALID_PROCESSOR_ID; 1843 if (IsValidCoreId(core_id)) {
1895 } 1844 R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, Svc::ResultInvalidCombination);
1896 1845 } else {
1897 if (affinity_mask == 0) { 1846 R_UNLESS(core_id == Svc::IdealCoreNoUpdate || core_id == Svc::IdealCoreDontCare,
1898 LOG_ERROR(Kernel_SVC, "Specfified affinity mask is zero."); 1847 Svc::ResultInvalidCoreId);
1899 return ERR_INVALID_COMBINATION;
1900 }
1901
1902 if (core < Core::Hardware::NUM_CPU_CORES) {
1903 if ((affinity_mask & (1ULL << core)) == 0) {
1904 LOG_ERROR(Kernel_SVC,
1905 "Core is not enabled for the current mask, core={}, mask={:016X}", core,
1906 affinity_mask);
1907 return ERR_INVALID_COMBINATION;
1908 }
1909 } else if (core != static_cast<u32>(THREADPROCESSORID_DONT_CARE) &&
1910 core != static_cast<u32>(THREADPROCESSORID_DONT_UPDATE)) {
1911 LOG_ERROR(Kernel_SVC, "Invalid processor ID specified (core={}).", core);
1912 return ERR_INVALID_PROCESSOR_ID;
1913 } 1848 }
1914 } 1849 }
1915 1850
1916 const auto& handle_table = current_process->GetHandleTable(); 1851 // Get the thread from its handle.
1917 const std::shared_ptr<Thread> thread = handle_table.Get<Thread>(thread_handle); 1852 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1918 if (!thread) { 1853 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1919 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}", 1854 R_UNLESS(thread, Svc::ResultInvalidHandle);
1920 thread_handle);
1921 return ERR_INVALID_HANDLE;
1922 }
1923 1855
1924 return thread->SetCoreAndAffinityMask(core, affinity_mask); 1856 // Set the core mask.
1857 R_TRY(thread->SetCoreMask(core_id, affinity_mask));
1858
1859 return RESULT_SUCCESS;
1925} 1860}
1926 1861
1927static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, u32 core, 1862static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, s32 core_id,
1928 u32 affinity_mask_low, u32 affinity_mask_high) { 1863 u32 affinity_mask_low, u32 affinity_mask_high) {
1929 const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32); 1864 const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32);
1930 return SetThreadCoreMask(system, thread_handle, core, affinity_mask); 1865 return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
1931} 1866}
1932 1867
1933static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) { 1868static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) {
@@ -2491,7 +2426,7 @@ void Call(Core::System& system, u32 immediate) {
2491 kernel.EnterSVCProfile(); 2426 kernel.EnterSVCProfile();
2492 2427
2493 auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); 2428 auto* thread = kernel.CurrentScheduler()->GetCurrentThread();
2494 thread->SetContinuousOnSVC(true); 2429 thread->SetIsCallingSvc();
2495 2430
2496 const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) 2431 const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate)
2497 : GetSVCInfo32(immediate); 2432 : GetSVCInfo32(immediate);
@@ -2507,7 +2442,7 @@ void Call(Core::System& system, u32 immediate) {
2507 2442
2508 kernel.ExitSVCProfile(); 2443 kernel.ExitSVCProfile();
2509 2444
2510 if (!thread->IsContinuousOnSVC()) { 2445 if (!thread->IsCallingSvc()) {
2511 auto* host_context = thread->GetHostContext().get(); 2446 auto* host_context = thread->GetHostContext().get();
2512 host_context->Rewind(); 2447 host_context->Rewind();
2513 } 2448 }