summaryrefslogtreecommitdiffstats
path: root/src/core/hle
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle')
-rw-r--r--src/core/hle/kernel/errors.h2
-rw-r--r--src/core/hle/kernel/svc.cpp27
-rw-r--r--src/core/hle/kernel/thread.cpp6
3 files changed, 31 insertions, 4 deletions
diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h
index 5be20c878..e1b5430bf 100644
--- a/src/core/hle/kernel/errors.h
+++ b/src/core/hle/kernel/errors.h
@@ -21,7 +21,9 @@ enum {
// Confirmed Switch OS error codes
MisalignedAddress = 102,
+ InvalidProcessorId = 113,
InvalidHandle = 114,
+ InvalidCombination = 116,
Timeout = 117,
SynchronizationCanceled = 118,
TooLarge = 119,
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 0811a16b8..ec3601e8b 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -732,7 +732,7 @@ static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask)
}
static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
- NGLOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:08X}, core=0x{:X}", thread_handle,
+ NGLOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:16X}, core=0x{:X}", thread_handle,
mask, core);
const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
@@ -740,6 +740,31 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
return ERR_INVALID_HANDLE;
}
+ if (core == THREADPROCESSORID_DEFAULT) {
+ ASSERT(thread->owner_process->ideal_processor != THREADPROCESSORID_DEFAULT);
+ // Set the target CPU to the one specified in the process' exheader.
+ core = thread->owner_process->ideal_processor;
+ mask = 1 << core;
+ }
+
+ if (mask == 0) {
+ return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination);
+ }
+
+ /// This value is used to only change the affinity mask without changing the current ideal core.
+ static constexpr u32 OnlyChangeMask = static_cast<u32>(-3);
+
+ if (core == OnlyChangeMask) {
+ core = thread->ideal_core;
+ } else if (core >= Core::NUM_CPU_CORES && core != -1) {
+ return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidProcessorId);
+ }
+
+ // Error out if the input core isn't enabled in the input mask.
+ if (core < Core::NUM_CPU_CORES && (mask & (1 << core)) == 0) {
+ return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination);
+ }
+
thread->ChangeCore(core, mask);
return RESULT_SUCCESS;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 46fcdefb8..0075e4a0f 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -460,13 +460,13 @@ void Thread::UpdatePriority() {
void Thread::ChangeCore(u32 core, u64 mask) {
ideal_core = core;
- mask = mask;
+ affinity_mask = mask;
if (status != THREADSTATUS_READY) {
return;
}
- boost::optional<s32> new_processor_id{GetNextProcessorId(mask)};
+ boost::optional<s32> new_processor_id{GetNextProcessorId(affinity_mask)};
if (!new_processor_id) {
new_processor_id = processor_id;
@@ -476,7 +476,7 @@ void Thread::ChangeCore(u32 core, u64 mask) {
new_processor_id = ideal_core;
}
- ASSERT(new_processor_id < 4);
+ ASSERT(*new_processor_id < 4);
// Add thread to new core's scheduler
auto& next_scheduler = Core::System().GetInstance().Scheduler(*new_processor_id);