diff options
| author | 2021-04-03 19:11:46 -0700 | |
|---|---|---|
| committer | 2021-05-05 16:40:50 -0700 | |
| commit | da7e9553dea4b1eaefb71aca8642ccce7c7f50fb (patch) | |
| tree | 3da10a60005ddcc4237900eb5e7473fe7b006152 /src/core/hle/kernel/svc.cpp | |
| parent | hle: kernel: svc: Migrate GetThreadPriority, StartThread, and ExitThread. (diff) | |
| download | yuzu-da7e9553dea4b1eaefb71aca8642ccce7c7f50fb.tar.gz yuzu-da7e9553dea4b1eaefb71aca8642ccce7c7f50fb.tar.xz yuzu-da7e9553dea4b1eaefb71aca8642ccce7c7f50fb.zip | |
hle: kernel: Migrate more of KThread to KAutoObject.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 268 |
1 files changed, 68 insertions, 200 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 395962885..813450115 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -355,7 +355,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) { | |||
| 355 | KScopedSchedulerLock lock(kernel); | 355 | KScopedSchedulerLock lock(kernel); |
| 356 | thread->SetState(ThreadState::Waiting); | 356 | thread->SetState(ThreadState::Waiting); |
| 357 | thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); | 357 | thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); |
| 358 | session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); | 358 | session->SendSyncRequest(thread, system.Memory(), system.CoreTiming()); |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | KSynchronizationObject* dummy{}; | 361 | KSynchronizationObject* dummy{}; |
| @@ -368,18 +368,13 @@ static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { | |||
| 368 | 368 | ||
| 369 | /// Get the ID for the specified thread. | 369 | /// Get the ID for the specified thread. |
| 370 | static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { | 370 | static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { |
| 371 | LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); | ||
| 372 | |||
| 373 | // Get the thread from its handle. | 371 | // Get the thread from its handle. |
| 374 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 372 | KScopedAutoObject thread = |
| 375 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 373 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); |
| 376 | if (!thread) { | 374 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 377 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 378 | return ResultInvalidHandle; | ||
| 379 | } | ||
| 380 | 375 | ||
| 381 | // Get the thread's id. | 376 | // Get the thread's id. |
| 382 | *out_thread_id = thread->GetThreadID(); | 377 | *out_thread_id = thread->GetId(); |
| 383 | return RESULT_SUCCESS; | 378 | return RESULT_SUCCESS; |
| 384 | } | 379 | } |
| 385 | 380 | ||
| @@ -396,30 +391,7 @@ static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low, | |||
| 396 | 391 | ||
| 397 | /// Gets the ID of the specified process or a specified thread's owning process. | 392 | /// Gets the ID of the specified process or a specified thread's owning process. |
| 398 | static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) { | 393 | static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) { |
| 399 | LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle); | 394 | __debugbreak(); |
| 400 | |||
| 401 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | ||
| 402 | const std::shared_ptr<Process> process = handle_table.Get<Process>(handle); | ||
| 403 | if (process) { | ||
| 404 | *process_id = process->GetProcessID(); | ||
| 405 | return RESULT_SUCCESS; | ||
| 406 | } | ||
| 407 | |||
| 408 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); | ||
| 409 | if (thread) { | ||
| 410 | const Process* const owner_process = thread->GetOwnerProcess(); | ||
| 411 | if (!owner_process) { | ||
| 412 | LOG_ERROR(Kernel_SVC, "Non-existent owning process encountered."); | ||
| 413 | return ResultInvalidHandle; | ||
| 414 | } | ||
| 415 | |||
| 416 | *process_id = owner_process->GetProcessID(); | ||
| 417 | return RESULT_SUCCESS; | ||
| 418 | } | ||
| 419 | |||
| 420 | // NOTE: This should also handle debug objects before returning. | ||
| 421 | |||
| 422 | LOG_ERROR(Kernel_SVC, "Handle does not exist, handle=0x{:08X}", handle); | ||
| 423 | return ResultInvalidHandle; | 395 | return ResultInvalidHandle; |
| 424 | } | 396 | } |
| 425 | 397 | ||
| @@ -460,14 +432,30 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha | |||
| 460 | 432 | ||
| 461 | for (u64 i = 0; i < handle_count; ++i) { | 433 | for (u64 i = 0; i < handle_count; ++i) { |
| 462 | const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); | 434 | const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); |
| 463 | const auto object = handle_table.Get<KSynchronizationObject>(handle); | ||
| 464 | 435 | ||
| 465 | if (object == nullptr) { | 436 | bool succeeded{}; |
| 466 | LOG_ERROR(Kernel_SVC, "Object is a nullptr"); | 437 | { |
| 467 | return ResultInvalidHandle; | 438 | auto object = handle_table.Get<KSynchronizationObject>(handle); |
| 439 | if (object) { | ||
| 440 | objects[i] = object.get(); | ||
| 441 | succeeded = true; | ||
| 442 | } | ||
| 468 | } | 443 | } |
| 469 | 444 | ||
| 470 | objects[i] = object.get(); | 445 | // TODO(bunnei): WORKAROUND WHILE WE HAVE TWO HANDLE TABLES |
| 446 | if (!succeeded) { | ||
| 447 | { | ||
| 448 | auto object = handle_table.GetObject<KSynchronizationObject>(handle); | ||
| 449 | |||
| 450 | if (object.IsNull()) { | ||
| 451 | LOG_ERROR(Kernel_SVC, "Object is a nullptr"); | ||
| 452 | return ResultInvalidHandle; | ||
| 453 | } | ||
| 454 | |||
| 455 | objects[i] = object.GetPointerUnsafe(); | ||
| 456 | succeeded = true; | ||
| 457 | } | ||
| 458 | } | ||
| 471 | } | 459 | } |
| 472 | return KSynchronizationObject::Wait(kernel, index, objects.data(), | 460 | return KSynchronizationObject::Wait(kernel, index, objects.data(), |
| 473 | static_cast<s32>(objects.size()), nano_seconds); | 461 | static_cast<s32>(objects.size()), nano_seconds); |
| @@ -481,19 +469,7 @@ static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u | |||
| 481 | 469 | ||
| 482 | /// Resumes a thread waiting on WaitSynchronization | 470 | /// Resumes a thread waiting on WaitSynchronization |
| 483 | static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) { | 471 | static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) { |
| 484 | LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); | 472 | __debugbreak(); |
| 485 | |||
| 486 | // Get the thread from its handle. | ||
| 487 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | ||
| 488 | std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | ||
| 489 | |||
| 490 | if (!thread) { | ||
| 491 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 492 | return ResultInvalidHandle; | ||
| 493 | } | ||
| 494 | |||
| 495 | // Cancel the thread's wait. | ||
| 496 | thread->WaitCancel(); | ||
| 497 | return RESULT_SUCCESS; | 473 | return RESULT_SUCCESS; |
| 498 | } | 474 | } |
| 499 | 475 | ||
| @@ -899,9 +875,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 899 | return ResultInvalidCombination; | 875 | return ResultInvalidCombination; |
| 900 | } | 876 | } |
| 901 | 877 | ||
| 902 | const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get<KThread>( | 878 | KScopedAutoObject thread = |
| 903 | static_cast<Handle>(handle)); | 879 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>( |
| 904 | if (!thread) { | 880 | static_cast<Handle>(handle)); |
| 881 | if (thread.IsNull()) { | ||
| 905 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", | 882 | LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", |
| 906 | static_cast<Handle>(handle)); | 883 | static_cast<Handle>(handle)); |
| 907 | return ResultInvalidHandle; | 884 | return ResultInvalidHandle; |
| @@ -910,7 +887,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha | |||
| 910 | const auto& core_timing = system.CoreTiming(); | 887 | const auto& core_timing = system.CoreTiming(); |
| 911 | const auto& scheduler = *system.Kernel().CurrentScheduler(); | 888 | const auto& scheduler = *system.Kernel().CurrentScheduler(); |
| 912 | const auto* const current_thread = scheduler.GetCurrentThread(); | 889 | const auto* const current_thread = scheduler.GetCurrentThread(); |
| 913 | const bool same_thread = current_thread == thread.get(); | 890 | const bool same_thread = current_thread == thread.GetPointerUnsafe(); |
| 914 | 891 | ||
| 915 | const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks(); | 892 | const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks(); |
| 916 | u64 out_ticks = 0; | 893 | u64 out_ticks = 0; |
| @@ -1055,45 +1032,7 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size | |||
| 1055 | /// Sets the thread activity | 1032 | /// Sets the thread activity |
| 1056 | static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, | 1033 | static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, |
| 1057 | ThreadActivity thread_activity) { | 1034 | ThreadActivity thread_activity) { |
| 1058 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle, | 1035 | __debugbreak(); |
| 1059 | thread_activity); | ||
| 1060 | |||
| 1061 | // Validate the activity. | ||
| 1062 | constexpr auto IsValidThreadActivity = [](ThreadActivity activity) { | ||
| 1063 | return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused; | ||
| 1064 | }; | ||
| 1065 | if (!IsValidThreadActivity(thread_activity)) { | ||
| 1066 | LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})", | ||
| 1067 | thread_activity); | ||
| 1068 | return ResultInvalidEnumValue; | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | // Get the thread from its handle. | ||
| 1072 | auto& kernel = system.Kernel(); | ||
| 1073 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | ||
| 1074 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | ||
| 1075 | if (!thread) { | ||
| 1076 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 1077 | return ResultInvalidHandle; | ||
| 1078 | } | ||
| 1079 | |||
| 1080 | // Check that the activity is being set on a non-current thread for the current process. | ||
| 1081 | if (thread->GetOwnerProcess() != kernel.CurrentProcess()) { | ||
| 1082 | LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread."); | ||
| 1083 | return ResultInvalidHandle; | ||
| 1084 | } | ||
| 1085 | if (thread.get() == GetCurrentThreadPointer(kernel)) { | ||
| 1086 | LOG_ERROR(Kernel_SVC, "Thread is busy"); | ||
| 1087 | return ResultBusy; | ||
| 1088 | } | ||
| 1089 | |||
| 1090 | // Set the activity. | ||
| 1091 | const auto set_result = thread->SetActivity(thread_activity); | ||
| 1092 | if (set_result.IsError()) { | ||
| 1093 | LOG_ERROR(Kernel_SVC, "Failed to set thread activity."); | ||
| 1094 | return set_result; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | return RESULT_SUCCESS; | 1036 | return RESULT_SUCCESS; |
| 1098 | } | 1037 | } |
| 1099 | 1038 | ||
| @@ -1107,36 +1046,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand | |||
| 1107 | LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, | 1046 | LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, |
| 1108 | thread_handle); | 1047 | thread_handle); |
| 1109 | 1048 | ||
| 1110 | // Get the thread from its handle. | 1049 | __debugbreak(); |
| 1111 | const auto* current_process = system.Kernel().CurrentProcess(); | ||
| 1112 | const std::shared_ptr<KThread> thread = | ||
| 1113 | current_process->GetHandleTable().Get<KThread>(thread_handle); | ||
| 1114 | if (!thread) { | ||
| 1115 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle); | ||
| 1116 | return ResultInvalidHandle; | ||
| 1117 | } | ||
| 1118 | |||
| 1119 | // Require the handle be to a non-current thread in the current process. | ||
| 1120 | if (thread->GetOwnerProcess() != current_process) { | ||
| 1121 | LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process."); | ||
| 1122 | return ResultInvalidHandle; | ||
| 1123 | } | ||
| 1124 | if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { | ||
| 1125 | LOG_ERROR(Kernel_SVC, "Current thread is busy."); | ||
| 1126 | return ResultBusy; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | // Get the thread context. | ||
| 1130 | std::vector<u8> context; | ||
| 1131 | const auto context_result = thread->GetThreadContext3(context); | ||
| 1132 | if (context_result.IsError()) { | ||
| 1133 | LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})", | ||
| 1134 | context_result.raw); | ||
| 1135 | return context_result; | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | // Copy the thread context to user space. | ||
| 1139 | system.Memory().WriteBlock(out_context, context.data(), context.size()); | ||
| 1140 | 1050 | ||
| 1141 | return RESULT_SUCCESS; | 1051 | return RESULT_SUCCESS; |
| 1142 | } | 1052 | } |
| @@ -1164,30 +1074,26 @@ static ResultCode GetThreadPriority32(Core::System& system, u32* out_priority, H | |||
| 1164 | } | 1074 | } |
| 1165 | 1075 | ||
| 1166 | /// Sets the priority for the specified thread | 1076 | /// Sets the priority for the specified thread |
| 1167 | static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) { | 1077 | static ResultCode SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority) { |
| 1168 | LOG_TRACE(Kernel_SVC, "called"); | 1078 | // Get the current process. |
| 1079 | Process& process = *system.Kernel().CurrentProcess(); | ||
| 1169 | 1080 | ||
| 1170 | // Validate the priority. | 1081 | // Validate the priority. |
| 1171 | if (HighestThreadPriority > priority || priority > LowestThreadPriority) { | 1082 | R_UNLESS(HighestThreadPriority <= priority && priority <= LowestThreadPriority, |
| 1172 | LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority); | 1083 | ResultInvalidPriority); |
| 1173 | return ResultInvalidPriority; | 1084 | R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority); |
| 1174 | } | ||
| 1175 | 1085 | ||
| 1176 | // Get the thread from its handle. | 1086 | // Get the thread from its handle. |
| 1177 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1087 | KScopedAutoObject thread = process.GetHandleTable().GetObject<KThread>(thread_handle); |
| 1178 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); | 1088 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 1179 | if (!thread) { | ||
| 1180 | LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle); | ||
| 1181 | return ResultInvalidHandle; | ||
| 1182 | } | ||
| 1183 | 1089 | ||
| 1184 | // Set the thread priority. | 1090 | // Set the thread priority. |
| 1185 | thread->SetBasePriority(priority); | 1091 | thread->SetBasePriority(priority); |
| 1186 | return RESULT_SUCCESS; | 1092 | return RESULT_SUCCESS; |
| 1187 | } | 1093 | } |
| 1188 | 1094 | ||
| 1189 | static ResultCode SetThreadPriority32(Core::System& system, Handle handle, u32 priority) { | 1095 | static ResultCode SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority) { |
| 1190 | return SetThreadPriority(system, handle, priority); | 1096 | return SetThreadPriority(system, thread_handle, priority); |
| 1191 | } | 1097 | } |
| 1192 | 1098 | ||
| 1193 | /// Get which CPU core is executing the current thread | 1099 | /// Get which CPU core is executing the current thread |
| @@ -1480,7 +1386,7 @@ static void ExitProcess32(Core::System& system) { | |||
| 1480 | ExitProcess(system); | 1386 | ExitProcess(system); |
| 1481 | } | 1387 | } |
| 1482 | 1388 | ||
| 1483 | static constexpr bool IsValidCoreId(int32_t core_id) { | 1389 | static constexpr bool IsValidVirtualCoreId(int32_t core_id) { |
| 1484 | return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES)); | 1390 | return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES)); |
| 1485 | } | 1391 | } |
| 1486 | 1392 | ||
| @@ -1500,7 +1406,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e | |||
| 1500 | } | 1406 | } |
| 1501 | 1407 | ||
| 1502 | // Validate arguments. | 1408 | // Validate arguments. |
| 1503 | if (!IsValidCoreId(core_id)) { | 1409 | if (!IsValidVirtualCoreId(core_id)) { |
| 1504 | LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id); | 1410 | LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id); |
| 1505 | return ResultInvalidCoreId; | 1411 | return ResultInvalidCoreId; |
| 1506 | } | 1412 | } |
| @@ -1822,8 +1728,11 @@ static void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high) | |||
| 1822 | static ResultCode CloseHandle(Core::System& system, Handle handle) { | 1728 | static ResultCode CloseHandle(Core::System& system, Handle handle) { |
| 1823 | LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); | 1729 | LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); |
| 1824 | 1730 | ||
| 1825 | auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1731 | // Remove the handle. |
| 1826 | return handle_table.Close(handle); | 1732 | R_UNLESS(system.Kernel().CurrentProcess()->GetHandleTable().Remove(handle), |
| 1733 | ResultInvalidHandle); | ||
| 1734 | |||
| 1735 | return RESULT_SUCCESS; | ||
| 1827 | } | 1736 | } |
| 1828 | 1737 | ||
| 1829 | static ResultCode CloseHandle32(Core::System& system, Handle handle) { | 1738 | static ResultCode CloseHandle32(Core::System& system, Handle handle) { |
| @@ -1925,23 +1834,7 @@ static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u | |||
| 1925 | 1834 | ||
| 1926 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, | 1835 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, |
| 1927 | u64* out_affinity_mask) { | 1836 | u64* out_affinity_mask) { |
| 1928 | LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); | 1837 | __debugbreak(); |
| 1929 | |||
| 1930 | // Get the thread from its handle. | ||
| 1931 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | ||
| 1932 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | ||
| 1933 | if (!thread) { | ||
| 1934 | LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle); | ||
| 1935 | return ResultInvalidHandle; | ||
| 1936 | } | ||
| 1937 | |||
| 1938 | // Get the core mask. | ||
| 1939 | const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask); | ||
| 1940 | if (result.IsError()) { | ||
| 1941 | LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw); | ||
| 1942 | return result; | ||
| 1943 | } | ||
| 1944 | |||
| 1945 | return RESULT_SUCCESS; | 1838 | return RESULT_SUCCESS; |
| 1946 | } | 1839 | } |
| 1947 | 1840 | ||
| @@ -1956,58 +1849,33 @@ static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle | |||
| 1956 | 1849 | ||
| 1957 | static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id, | 1850 | static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id, |
| 1958 | u64 affinity_mask) { | 1851 | u64 affinity_mask) { |
| 1959 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core_id=0x{:X}, affinity_mask=0x{:016X}", | ||
| 1960 | thread_handle, core_id, affinity_mask); | ||
| 1961 | |||
| 1962 | const auto& current_process = *system.Kernel().CurrentProcess(); | ||
| 1963 | |||
| 1964 | // Determine the core id/affinity mask. | 1852 | // Determine the core id/affinity mask. |
| 1965 | if (core_id == Svc::IdealCoreUseProcessValue) { | 1853 | if (core_id == IdealCoreUseProcessValue) { |
| 1966 | core_id = current_process.GetIdealCoreId(); | 1854 | core_id = system.Kernel().CurrentProcess()->GetIdealCoreId(); |
| 1967 | affinity_mask = (1ULL << core_id); | 1855 | affinity_mask = (1ULL << core_id); |
| 1968 | } else { | 1856 | } else { |
| 1969 | // Validate the affinity mask. | 1857 | // Validate the affinity mask. |
| 1970 | const u64 process_core_mask = current_process.GetCoreMask(); | 1858 | const u64 process_core_mask = system.Kernel().CurrentProcess()->GetCoreMask(); |
| 1971 | if ((affinity_mask | process_core_mask) != process_core_mask) { | 1859 | R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, ResultInvalidCoreId); |
| 1972 | LOG_ERROR(Kernel_SVC, | 1860 | R_UNLESS(affinity_mask != 0, ResultInvalidCombination); |
| 1973 | "Affinity mask does match the process core mask (affinity mask={:016X}, core " | ||
| 1974 | "mask={:016X})", | ||
| 1975 | affinity_mask, process_core_mask); | ||
| 1976 | return ResultInvalidCoreId; | ||
| 1977 | } | ||
| 1978 | if (affinity_mask == 0) { | ||
| 1979 | LOG_ERROR(Kernel_SVC, "Affinity mask is zero."); | ||
| 1980 | return ResultInvalidCombination; | ||
| 1981 | } | ||
| 1982 | 1861 | ||
| 1983 | // Validate the core id. | 1862 | // Validate the core id. |
| 1984 | if (IsValidCoreId(core_id)) { | 1863 | if (IsValidVirtualCoreId(core_id)) { |
| 1985 | if (((1ULL << core_id) & affinity_mask) == 0) { | 1864 | R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, ResultInvalidCombination); |
| 1986 | LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); | ||
| 1987 | return ResultInvalidCombination; | ||
| 1988 | } | ||
| 1989 | } else { | 1865 | } else { |
| 1990 | if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) { | 1866 | R_UNLESS(core_id == IdealCoreNoUpdate || core_id == IdealCoreDontCare, |
| 1991 | LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); | 1867 | ResultInvalidCoreId); |
| 1992 | return ResultInvalidCoreId; | ||
| 1993 | } | ||
| 1994 | } | 1868 | } |
| 1995 | } | 1869 | } |
| 1996 | 1870 | ||
| 1997 | // Get the thread from its handle. | 1871 | // Get the thread from its handle. |
| 1998 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1872 | KScopedAutoObject thread = |
| 1999 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 1873 | system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle); |
| 2000 | if (!thread) { | 1874 | R_UNLESS(thread.IsNotNull(), ResultInvalidHandle); |
| 2001 | LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle); | ||
| 2002 | return ResultInvalidHandle; | ||
| 2003 | } | ||
| 2004 | 1875 | ||
| 2005 | // Set the core mask. | 1876 | // Set the core mask. |
| 2006 | const auto set_result = thread->SetCoreMask(core_id, affinity_mask); | 1877 | R_TRY(thread->SetCoreMask(core_id, affinity_mask)); |
| 2007 | if (set_result.IsError()) { | 1878 | |
| 2008 | LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw); | ||
| 2009 | return set_result; | ||
| 2010 | } | ||
| 2011 | return RESULT_SUCCESS; | 1879 | return RESULT_SUCCESS; |
| 2012 | } | 1880 | } |
| 2013 | 1881 | ||
| @@ -2105,7 +1973,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o | |||
| 2105 | *out_write = *write_create_result; | 1973 | *out_write = *write_create_result; |
| 2106 | 1974 | ||
| 2107 | // Add the writable event to the handle table. | 1975 | // Add the writable event to the handle table. |
| 2108 | auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); }); | 1976 | auto handle_guard = SCOPE_GUARD({ handle_table.Remove(*write_create_result); }); |
| 2109 | 1977 | ||
| 2110 | // Add the readable event to the handle table. | 1978 | // Add the readable event to the handle table. |
| 2111 | const auto read_create_result = handle_table.Create(event->GetReadableEvent()); | 1979 | const auto read_create_result = handle_table.Create(event->GetReadableEvent()); |