diff options
Diffstat (limited to 'src/core/hle')
| -rw-r--r-- | src/core/hle/kernel/global_scheduler_context.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_scheduler.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.h | 22 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 7 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 66 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_results.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_types.h | 4 |
9 files changed, 41 insertions, 75 deletions
diff --git a/src/core/hle/kernel/global_scheduler_context.h b/src/core/hle/kernel/global_scheduler_context.h index 11592843e..0f7b9a61c 100644 --- a/src/core/hle/kernel/global_scheduler_context.h +++ b/src/core/hle/kernel/global_scheduler_context.h | |||
| @@ -21,7 +21,7 @@ class KernelCore; | |||
| 21 | class SchedulerLock; | 21 | class SchedulerLock; |
| 22 | 22 | ||
| 23 | using KSchedulerPriorityQueue = | 23 | using KSchedulerPriorityQueue = |
| 24 | KPriorityQueue<KThread, Core::Hardware::NUM_CPU_CORES, Svc::LowestThreadPriority, | 24 | KPriorityQueue<KThread, Core::Hardware::NUM_CPU_CORES, Svc::LowestThreadPriority + 1, |
| 25 | Svc::HighestThreadPriority>; | 25 | Svc::HighestThreadPriority>; |
| 26 | 26 | ||
| 27 | static constexpr s32 HighestCoreMigrationAllowedPriority = 2; | 27 | static constexpr s32 HighestCoreMigrationAllowedPriority = 2; |
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 0e6300760..233022023 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -764,7 +764,7 @@ void KScheduler::Initialize() { | |||
| 764 | std::function<void(void*)> init_func = Core::CpuManager::GetIdleThreadStartFunc(); | 764 | std::function<void(void*)> init_func = Core::CpuManager::GetIdleThreadStartFunc(); |
| 765 | void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); | 765 | void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater(); |
| 766 | auto thread_res = KThread::Create(system, ThreadType::Kernel, name, 0, | 766 | auto thread_res = KThread::Create(system, ThreadType::Kernel, name, 0, |
| 767 | Svc::LowestThreadPriority, 0, static_cast<u32>(core_id), 0, | 767 | KThread::IdleThreadPriority, 0, static_cast<u32>(core_id), 0, |
| 768 | nullptr, std::move(init_func), init_func_parameter); | 768 | nullptr, std::move(init_func), init_func_parameter); |
| 769 | idle_thread = thread_res.Unwrap().get(); | 769 | idle_thread = thread_res.Unwrap().get(); |
| 770 | 770 | ||
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 518c5d5df..e5be849bb 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp | |||
| @@ -127,14 +127,6 @@ ResultVal<std::shared_ptr<KThread>> KThread::Create(Core::System& system, Thread | |||
| 127 | void* thread_start_parameter) { | 127 | void* thread_start_parameter) { |
| 128 | auto& kernel = system.Kernel(); | 128 | auto& kernel = system.Kernel(); |
| 129 | 129 | ||
| 130 | R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority, | ||
| 131 | Svc::ResultInvalidPriority); | ||
| 132 | |||
| 133 | if (processor_id > THREADPROCESSORID_MAX) { | ||
| 134 | LOG_ERROR(Kernel_SVC, "Invalid processor id: {}", processor_id); | ||
| 135 | return ERR_INVALID_PROCESSOR_ID; | ||
| 136 | } | ||
| 137 | |||
| 138 | if (owner_process) { | 130 | if (owner_process) { |
| 139 | if (!system.Memory().IsValidVirtualAddress(*owner_process, entry_point)) { | 131 | if (!system.Memory().IsValidVirtualAddress(*owner_process, entry_point)) { |
| 140 | LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point); | 132 | LOG_ERROR(Kernel_SVC, "(name={}): invalid entry {:016X}", name, entry_point); |
| @@ -423,7 +415,7 @@ ResultCode KThread::SetCoreAndAffinityMask(s32 new_core, u64 new_affinity_mask) | |||
| 423 | }; | 415 | }; |
| 424 | 416 | ||
| 425 | const bool use_override = affinity_override_count != 0; | 417 | const bool use_override = affinity_override_count != 0; |
| 426 | if (new_core == THREADPROCESSORID_DONT_UPDATE) { | 418 | if (new_core == Svc::IdealCoreNoUpdate) { |
| 427 | new_core = use_override ? ideal_core_override : ideal_core; | 419 | new_core = use_override ? ideal_core_override : ideal_core; |
| 428 | if ((new_affinity_mask & (1ULL << new_core)) == 0) { | 420 | if ((new_affinity_mask & (1ULL << new_core)) == 0) { |
| 429 | LOG_ERROR(Kernel, "New affinity mask is incorrect! new_core={}, new_affinity_mask={}", | 421 | LOG_ERROR(Kernel, "New affinity mask is incorrect! new_core={}, new_affinity_mask={}", |
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 83a6d36ae..ef2313f87 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h | |||
| @@ -47,28 +47,6 @@ enum class ThreadType : u32 { | |||
| 47 | }; | 47 | }; |
| 48 | DECLARE_ENUM_FLAG_OPERATORS(ThreadType); | 48 | DECLARE_ENUM_FLAG_OPERATORS(ThreadType); |
| 49 | 49 | ||
| 50 | enum ThreadProcessorId : s32 { | ||
| 51 | /// Indicates that no particular processor core is preferred. | ||
| 52 | THREADPROCESSORID_DONT_CARE = -1, | ||
| 53 | |||
| 54 | /// Run thread on the ideal core specified by the process. | ||
| 55 | THREADPROCESSORID_IDEAL = -2, | ||
| 56 | |||
| 57 | /// Indicates that the preferred processor ID shouldn't be updated in | ||
| 58 | /// a core mask setting operation. | ||
| 59 | THREADPROCESSORID_DONT_UPDATE = -3, | ||
| 60 | |||
| 61 | THREADPROCESSORID_0 = 0, ///< Run thread on core 0 | ||
| 62 | THREADPROCESSORID_1 = 1, ///< Run thread on core 1 | ||
| 63 | THREADPROCESSORID_2 = 2, ///< Run thread on core 2 | ||
| 64 | THREADPROCESSORID_3 = 3, ///< Run thread on core 3 | ||
| 65 | THREADPROCESSORID_MAX = 4, ///< Processor ID must be less than this | ||
| 66 | |||
| 67 | /// Allowed CPU mask | ||
| 68 | THREADPROCESSORID_DEFAULT_MASK = (1 << THREADPROCESSORID_0) | (1 << THREADPROCESSORID_1) | | ||
| 69 | (1 << THREADPROCESSORID_2) | (1 << THREADPROCESSORID_3) | ||
| 70 | }; | ||
| 71 | |||
| 72 | enum class ThreadState : u16 { | 50 | enum class ThreadState : u16 { |
| 73 | Initialized = 0, | 51 | Initialized = 0, |
| 74 | Waiting = 1, | 52 | Waiting = 1, |
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index e47da2b7f..819e275ff 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -39,7 +39,7 @@ namespace { | |||
| 39 | void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) { | 39 | void SetupMainThread(Core::System& system, Process& owner_process, u32 priority, VAddr stack_top) { |
| 40 | const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); | 40 | const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); |
| 41 | auto thread_res = KThread::Create(system, ThreadType::User, "main", entry_point, priority, 0, | 41 | auto thread_res = KThread::Create(system, ThreadType::User, "main", entry_point, priority, 0, |
| 42 | owner_process.GetIdealCore(), stack_top, &owner_process); | 42 | owner_process.GetIdealCoreId(), stack_top, &owner_process); |
| 43 | 43 | ||
| 44 | std::shared_ptr<KThread> thread = std::move(thread_res).Unwrap(); | 44 | std::shared_ptr<KThread> thread = std::move(thread_res).Unwrap(); |
| 45 | 45 | ||
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index db01d6c8a..5a2cfdb36 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -173,10 +173,15 @@ public: | |||
| 173 | std::shared_ptr<ResourceLimit> GetResourceLimit() const; | 173 | std::shared_ptr<ResourceLimit> GetResourceLimit() const; |
| 174 | 174 | ||
| 175 | /// Gets the ideal CPU core ID for this process | 175 | /// Gets the ideal CPU core ID for this process |
| 176 | u8 GetIdealCore() const { | 176 | u8 GetIdealCoreId() const { |
| 177 | return ideal_core; | 177 | return ideal_core; |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | /// Checks if the specified thread priority is valid. | ||
| 181 | bool CheckThreadPriority(s32 prio) const { | ||
| 182 | return ((1ULL << prio) & GetPriorityMask()) != 0; | ||
| 183 | } | ||
| 184 | |||
| 180 | /// Gets the bitmask of allowed cores that this process' threads can run on. | 185 | /// Gets the bitmask of allowed cores that this process' threads can run on. |
| 181 | u64 GetCoreMask() const { | 186 | u64 GetCoreMask() const { |
| 182 | return capabilities.GetCoreMask(); | 187 | return capabilities.GetCoreMask(); |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 70a8ef34b..2512bfd98 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -1443,54 +1443,40 @@ static void ExitProcess32(Core::System& system) { | |||
| 1443 | ExitProcess(system); | 1443 | ExitProcess(system); |
| 1444 | } | 1444 | } |
| 1445 | 1445 | ||
| 1446 | static constexpr bool IsValidCoreId(int32_t core_id) { | ||
| 1447 | return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES)); | ||
| 1448 | } | ||
| 1449 | |||
| 1446 | /// Creates a new thread | 1450 | /// Creates a new thread |
| 1447 | static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg, | 1451 | static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg, |
| 1448 | VAddr stack_top, u32 priority, s32 processor_id) { | 1452 | VAddr stack_bottom, u32 priority, s32 core_id) { |
| 1449 | LOG_DEBUG(Kernel_SVC, | 1453 | LOG_DEBUG(Kernel_SVC, |
| 1450 | "called entrypoint=0x{:08X}, arg=0x{:08X}, stacktop=0x{:08X}, " | 1454 | "called entry_point=0x{:08X}, arg=0x{:08X}, stack_bottom=0x{:08X}, " |
| 1451 | "threadpriority=0x{:08X}, processorid=0x{:08X} : created handle=0x{:08X}", | 1455 | "priority=0x{:08X}, core_id=0x{:08X}", |
| 1452 | entry_point, arg, stack_top, priority, processor_id, *out_handle); | 1456 | entry_point, arg, stack_bottom, priority, core_id); |
| 1453 | 1457 | ||
| 1454 | auto* const current_process = system.Kernel().CurrentProcess(); | 1458 | // Adjust core id, if it's the default magic. |
| 1455 | 1459 | auto& kernel = system.Kernel(); | |
| 1456 | if (processor_id == THREADPROCESSORID_IDEAL) { | 1460 | auto& process = *kernel.CurrentProcess(); |
| 1457 | // Set the target CPU to the one specified by the process. | 1461 | if (core_id == Svc::IdealCoreUseProcessValue) { |
| 1458 | processor_id = current_process->GetIdealCore(); | 1462 | core_id = process.GetIdealCoreId(); |
| 1459 | ASSERT(processor_id != THREADPROCESSORID_IDEAL); | ||
| 1460 | } | ||
| 1461 | |||
| 1462 | if (processor_id < THREADPROCESSORID_0 || processor_id > THREADPROCESSORID_3) { | ||
| 1463 | LOG_ERROR(Kernel_SVC, "Invalid thread processor ID: {}", processor_id); | ||
| 1464 | return ERR_INVALID_PROCESSOR_ID; | ||
| 1465 | } | ||
| 1466 | |||
| 1467 | const u64 core_mask = current_process->GetCoreMask(); | ||
| 1468 | if ((core_mask | (1ULL << processor_id)) != core_mask) { | ||
| 1469 | LOG_ERROR(Kernel_SVC, "Invalid thread core specified ({})", processor_id); | ||
| 1470 | return ERR_INVALID_PROCESSOR_ID; | ||
| 1471 | } | ||
| 1472 | |||
| 1473 | if (priority > Svc::LowestThreadPriority) { | ||
| 1474 | LOG_ERROR(Kernel_SVC, | ||
| 1475 | "Invalid thread priority specified ({}). Must be within the range 0-64", | ||
| 1476 | priority); | ||
| 1477 | return ERR_INVALID_THREAD_PRIORITY; | ||
| 1478 | } | 1463 | } |
| 1479 | 1464 | ||
| 1480 | if (((1ULL << priority) & current_process->GetPriorityMask()) == 0) { | 1465 | // Validate arguments. |
| 1481 | LOG_ERROR(Kernel_SVC, "Invalid thread priority specified ({})", priority); | 1466 | R_UNLESS(IsValidCoreId(core_id), Svc::ResultInvalidCoreId); |
| 1482 | return ERR_INVALID_THREAD_PRIORITY; | 1467 | R_UNLESS(((1ULL << core_id) & process.GetCoreMask()) != 0, Svc::ResultInvalidCoreId); |
| 1483 | } | ||
| 1484 | 1468 | ||
| 1485 | auto& kernel = system.Kernel(); | 1469 | R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority, |
| 1470 | Svc::ResultInvalidPriority); | ||
| 1471 | R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); | ||
| 1486 | 1472 | ||
| 1487 | ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Threads, 1)); | 1473 | ASSERT(kernel.CurrentProcess()->GetResourceLimit()->Reserve(ResourceType::Threads, 1)); |
| 1488 | 1474 | ||
| 1489 | CASCADE_RESULT(std::shared_ptr<KThread> thread, | 1475 | CASCADE_RESULT(std::shared_ptr<KThread> thread, |
| 1490 | KThread::Create(system, ThreadType::User, "", entry_point, priority, arg, | 1476 | KThread::Create(system, ThreadType::User, "", entry_point, priority, arg, |
| 1491 | processor_id, stack_top, current_process)); | 1477 | core_id, stack_bottom, &process)); |
| 1492 | 1478 | ||
| 1493 | const auto new_thread_handle = current_process->GetHandleTable().Create(thread); | 1479 | const auto new_thread_handle = process.GetHandleTable().Create(thread); |
| 1494 | if (new_thread_handle.Failed()) { | 1480 | if (new_thread_handle.Failed()) { |
| 1495 | LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}", | 1481 | LOG_ERROR(Kernel_SVC, "Failed to create handle with error=0x{:X}", |
| 1496 | new_thread_handle.Code().raw); | 1482 | new_thread_handle.Code().raw); |
| @@ -1872,10 +1858,10 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 1872 | 1858 | ||
| 1873 | const auto* const current_process = system.Kernel().CurrentProcess(); | 1859 | const auto* const current_process = system.Kernel().CurrentProcess(); |
| 1874 | 1860 | ||
| 1875 | if (core == static_cast<u32>(THREADPROCESSORID_IDEAL)) { | 1861 | if (core == static_cast<u32>(Svc::IdealCoreUseProcessValue)) { |
| 1876 | const u8 ideal_cpu_core = current_process->GetIdealCore(); | 1862 | const u8 ideal_cpu_core = current_process->GetIdealCoreId(); |
| 1877 | 1863 | ||
| 1878 | ASSERT(ideal_cpu_core != static_cast<u8>(THREADPROCESSORID_IDEAL)); | 1864 | ASSERT(ideal_cpu_core != static_cast<u8>(Svc::IdealCoreUseProcessValue)); |
| 1879 | 1865 | ||
| 1880 | // Set the target CPU to the ideal core specified by the process. | 1866 | // Set the target CPU to the ideal core specified by the process. |
| 1881 | core = ideal_cpu_core; | 1867 | core = ideal_cpu_core; |
| @@ -1903,8 +1889,8 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 1903 | affinity_mask); | 1889 | affinity_mask); |
| 1904 | return ERR_INVALID_COMBINATION; | 1890 | return ERR_INVALID_COMBINATION; |
| 1905 | } | 1891 | } |
| 1906 | } else if (core != static_cast<u32>(THREADPROCESSORID_DONT_CARE) && | 1892 | } else if (core != static_cast<u32>(Svc::IdealCoreDontCare) && |
| 1907 | core != static_cast<u32>(THREADPROCESSORID_DONT_UPDATE)) { | 1893 | core != static_cast<u32>(Svc::IdealCoreNoUpdate)) { |
| 1908 | LOG_ERROR(Kernel_SVC, "Invalid processor ID specified (core={}).", core); | 1894 | LOG_ERROR(Kernel_SVC, "Invalid processor ID specified (core={}).", core); |
| 1909 | return ERR_INVALID_PROCESSOR_ID; | 1895 | return ERR_INVALID_PROCESSOR_ID; |
| 1910 | } | 1896 | } |
diff --git a/src/core/hle/kernel/svc_results.h b/src/core/hle/kernel/svc_results.h index 74adabc11..67bdf5424 100644 --- a/src/core/hle/kernel/svc_results.h +++ b/src/core/hle/kernel/svc_results.h | |||
| @@ -12,6 +12,7 @@ constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59}; | |||
| 12 | constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102}; | 12 | constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102}; |
| 13 | constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106}; | 13 | constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106}; |
| 14 | constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112}; | 14 | constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112}; |
| 15 | constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113}; | ||
| 15 | constexpr ResultCode ResultInvalidHandle{ErrorModule::Kernel, 114}; | 16 | constexpr ResultCode ResultInvalidHandle{ErrorModule::Kernel, 114}; |
| 16 | constexpr ResultCode ResultTimedOut{ErrorModule::Kernel, 117}; | 17 | constexpr ResultCode ResultTimedOut{ErrorModule::Kernel, 117}; |
| 17 | constexpr ResultCode ResultCancelled{ErrorModule::Kernel, 118}; | 18 | constexpr ResultCode ResultCancelled{ErrorModule::Kernel, 118}; |
diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h index 09b858f2a..8909dbfab 100644 --- a/src/core/hle/kernel/svc_types.h +++ b/src/core/hle/kernel/svc_types.h | |||
| @@ -77,6 +77,10 @@ enum class ArbitrationType : u32 { | |||
| 77 | WaitIfEqual = 2, | 77 | WaitIfEqual = 2, |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | constexpr inline s32 IdealCoreDontCare = -1; | ||
| 81 | constexpr inline s32 IdealCoreUseProcessValue = -2; | ||
| 82 | constexpr inline s32 IdealCoreNoUpdate = -3; | ||
| 83 | |||
| 80 | constexpr inline s32 LowestThreadPriority = 63; | 84 | constexpr inline s32 LowestThreadPriority = 63; |
| 81 | constexpr inline s32 HighestThreadPriority = 0; | 85 | constexpr inline s32 HighestThreadPriority = 0; |
| 82 | 86 | ||