From a434fdcb102e96ddf564dc0973d7073d49bf19fc Mon Sep 17 00:00:00 2001 From: bunnei Date: Wed, 2 May 2018 22:36:51 -0400 Subject: core: Implement multicore support. --- src/core/hle/kernel/thread.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 1bd5d9ebf..0a5441684 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -64,7 +64,7 @@ void Thread::Stop() { // Clean up thread from ready queue // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) if (status == THREADSTATUS_READY) { - Core::System::GetInstance().Scheduler().UnscheduleThread(this, current_priority); + scheduler->UnscheduleThread(this, current_priority); } status = THREADSTATUS_DEAD; @@ -92,7 +92,7 @@ void WaitCurrentThread_Sleep() { void ExitCurrentThread() { Thread* thread = GetCurrentThread(); thread->Stop(); - Core::System::GetInstance().Scheduler().RemoveThread(thread); + Core::System::GetInstance().CurrentScheduler().RemoveThread(thread); } /** @@ -188,7 +188,7 @@ void Thread::ResumeFromWait() { wakeup_callback = nullptr; status = THREADSTATUS_READY; - Core::System::GetInstance().Scheduler().ScheduleThread(this, current_priority); + scheduler->ScheduleThread(this, current_priority); Core::System::GetInstance().PrepareReschedule(); } @@ -259,8 +259,6 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, SharedPtr thread(new Thread); - Core::System::GetInstance().Scheduler().AddThread(thread, priority); - thread->thread_id = NewThreadId(); thread->status = THREADSTATUS_DORMANT; thread->entry_point = entry_point; @@ -275,6 +273,8 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, thread->name = std::move(name); thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); thread->owner_process = owner_process; + thread->scheduler = Core::System().GetInstance().Scheduler(static_cast(processor_id)); + thread->scheduler->AddThread(thread, priority); // Find the next available TLS index, and mark it as used auto& tls_slots = owner_process->tls_slots; @@ -337,7 +337,7 @@ void Thread::SetPriority(u32 priority) { } void Thread::BoostPriority(u32 priority) { - Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority); + scheduler->SetThreadPriority(this, priority); current_priority = priority; } @@ -406,7 +406,7 @@ void Thread::UpdatePriority() { if (new_priority == current_priority) return; - Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority); + scheduler->SetThreadPriority(this, new_priority); current_priority = new_priority; @@ -421,7 +421,7 @@ void Thread::UpdatePriority() { * Gets the current thread */ Thread* GetCurrentThread() { - return Core::System::GetInstance().Scheduler().GetCurrentThread(); + return Core::System::GetInstance().CurrentScheduler().GetCurrentThread(); } void ThreadingInit() { -- cgit v1.2.3 From 6ea8b3ef60bba657ca10c7e62dd849be9217faf3 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 5 May 2018 23:03:01 -0400 Subject: thread: Implement ChangeCore function. --- src/core/hle/kernel/thread.cpp | 53 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 0a5441684..c370776e8 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -273,7 +273,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, thread->name = std::move(name); thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); thread->owner_process = owner_process; - thread->scheduler = Core::System().GetInstance().Scheduler(static_cast(processor_id)); + thread->scheduler = Core::System().GetInstance().Scheduler(processor_id); thread->scheduler->AddThread(thread, priority); // Find the next available TLS index, and mark it as used @@ -415,6 +415,57 @@ void Thread::UpdatePriority() { lock_owner->UpdatePriority(); } +static s32 GetNextProcessorId(u64 mask) { + s32 processor_id{}; + for (s32 index = 0; index < Core::NUM_CPU_CORES; ++index) { + if (mask & (1ULL << index)) { + if (!Core::System().GetInstance().Scheduler(index)->GetCurrentThread()) { + // Core is enabled and not running any threads, use this one + return index; + } + + // Core is enabled, but running a thread, less ideal + processor_id = index; + } + } + + return processor_id; +} + +void Thread::ChangeCore(u32 core, u64 mask) { + const s32 new_processor_id{GetNextProcessorId(mask)}; + + ASSERT(ideal_core == core); // We're not doing anything with this yet, so assert the expected + ASSERT(new_processor_id < Core::NUM_CPU_CORES); + + if (new_processor_id == processor_id) { + // Already running on ideal core, nothing to do here + return; + } + + ASSERT(status != THREADSTATUS_RUNNING); // Unsupported + + processor_id = new_processor_id; + ideal_core = core; + mask = mask; + + // Add thread to new core's scheduler + auto& next_scheduler = Core::System().GetInstance().Scheduler(new_processor_id); + next_scheduler->AddThread(this, current_priority); + + if (status == THREADSTATUS_READY) { + // If the thread was ready, unschedule from the previous core and schedule on the new core + scheduler->UnscheduleThread(this, current_priority); + next_scheduler->ScheduleThread(this, current_priority); + } + + // Remove thread from previous core's scheduler + scheduler->RemoveThread(this); + + // Change thread's scheduler + scheduler = next_scheduler; +} + //////////////////////////////////////////////////////////////////////////////////////////////////// /** -- cgit v1.2.3 From 8aa5d25f826c8969a1e9938d8c8e12fa6df8be82 Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 5 May 2018 23:54:43 -0400 Subject: threading: Reschedule only on cores that are necessary. --- src/core/hle/kernel/thread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index c370776e8..31cf1551d 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -189,7 +189,7 @@ void Thread::ResumeFromWait() { status = THREADSTATUS_READY; scheduler->ScheduleThread(this, current_priority); - Core::System::GetInstance().PrepareReschedule(); + Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); } /** -- cgit v1.2.3 From 4822765fefbb81ad55fe4db7561ccf69b9a60bcd Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 7 May 2018 21:57:42 -0400 Subject: thread: Initialize ideal_core and mask members. --- src/core/hle/kernel/thread.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 31cf1551d..ac6252eac 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -266,6 +266,8 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, thread->nominal_priority = thread->current_priority = priority; thread->last_running_ticks = CoreTiming::GetTicks(); thread->processor_id = processor_id; + thread->ideal_core = processor_id; + thread->mask = 1 << processor_id; thread->wait_objects.clear(); thread->mutex_wait_address = 0; thread->condvar_wait_address = 0; -- cgit v1.2.3 From fbd7afefaade8f96defaa5b7353da8933f626917 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 7 May 2018 22:29:48 -0400 Subject: thread: Support core change on ResumeFromWait and improve ChangeCore. --- src/core/hle/kernel/thread.cpp | 105 ++++++++++++++++++++++++++--------------- 1 file changed, 68 insertions(+), 37 deletions(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index ac6252eac..04d18dc2f 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -154,6 +154,18 @@ void Thread::CancelWakeupTimer() { CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle); } +static boost::optional GetNextProcessorId(u64 mask) { + for (s32 index = 0; index < Core::NUM_CPU_CORES; ++index) { + if (mask & (1ULL << index)) { + if (!Core::System().GetInstance().Scheduler(index)->GetCurrentThread()) { + // Core is enabled and not running any threads, use this one + return index; + } + } + } + return {}; +} + void Thread::ResumeFromWait() { ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects"); @@ -188,7 +200,36 @@ void Thread::ResumeFromWait() { wakeup_callback = nullptr; status = THREADSTATUS_READY; - scheduler->ScheduleThread(this, current_priority); + + boost::optional new_processor_id = GetNextProcessorId(mask); + if (!new_processor_id) { + new_processor_id = processor_id; + } + if (ideal_core != -1 && + Core::System().GetInstance().Scheduler(ideal_core)->GetCurrentThread() == nullptr) { + new_processor_id = ideal_core; + } + + ASSERT(*new_processor_id < 4); + + // Add thread to new core's scheduler + auto& next_scheduler = Core::System().GetInstance().Scheduler(*new_processor_id); + + if (*new_processor_id != processor_id) { + // Remove thread from previous core's scheduler + scheduler->RemoveThread(this); + next_scheduler->AddThread(this, current_priority); + } + + processor_id = *new_processor_id; + + // If the thread was ready, unschedule from the previous core and schedule on the new core + scheduler->UnscheduleThread(this, current_priority); + next_scheduler->ScheduleThread(this, current_priority); + + // Change thread's scheduler + scheduler = next_scheduler; + Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); } @@ -267,7 +308,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, thread->last_running_ticks = CoreTiming::GetTicks(); thread->processor_id = processor_id; thread->ideal_core = processor_id; - thread->mask = 1 << processor_id; + thread->mask = 1ULL << processor_id; thread->wait_objects.clear(); thread->mutex_wait_address = 0; thread->condvar_wait_address = 0; @@ -417,55 +458,45 @@ void Thread::UpdatePriority() { lock_owner->UpdatePriority(); } -static s32 GetNextProcessorId(u64 mask) { - s32 processor_id{}; - for (s32 index = 0; index < Core::NUM_CPU_CORES; ++index) { - if (mask & (1ULL << index)) { - if (!Core::System().GetInstance().Scheduler(index)->GetCurrentThread()) { - // Core is enabled and not running any threads, use this one - return index; - } - - // Core is enabled, but running a thread, less ideal - processor_id = index; - } - } - - return processor_id; -} - void Thread::ChangeCore(u32 core, u64 mask) { - const s32 new_processor_id{GetNextProcessorId(mask)}; - - ASSERT(ideal_core == core); // We're not doing anything with this yet, so assert the expected - ASSERT(new_processor_id < Core::NUM_CPU_CORES); + ideal_core = core; + mask = mask; - if (new_processor_id == processor_id) { - // Already running on ideal core, nothing to do here + if (status != THREADSTATUS_READY) { return; } - ASSERT(status != THREADSTATUS_RUNNING); // Unsupported + boost::optional new_processor_id{GetNextProcessorId(mask)}; - processor_id = new_processor_id; - ideal_core = core; - mask = mask; + if (!new_processor_id) { + new_processor_id = processor_id; + } + if (ideal_core != -1 && + Core::System().GetInstance().Scheduler(ideal_core)->GetCurrentThread() == nullptr) { + new_processor_id = ideal_core; + } + + ASSERT(new_processor_id < 4); // Add thread to new core's scheduler - auto& next_scheduler = Core::System().GetInstance().Scheduler(new_processor_id); - next_scheduler->AddThread(this, current_priority); + auto& next_scheduler = Core::System().GetInstance().Scheduler(*new_processor_id); - if (status == THREADSTATUS_READY) { - // If the thread was ready, unschedule from the previous core and schedule on the new core - scheduler->UnscheduleThread(this, current_priority); - next_scheduler->ScheduleThread(this, current_priority); + if (*new_processor_id != processor_id) { + // Remove thread from previous core's scheduler + scheduler->RemoveThread(this); + next_scheduler->AddThread(this, current_priority); } - // Remove thread from previous core's scheduler - scheduler->RemoveThread(this); + processor_id = *new_processor_id; + + // If the thread was ready, unschedule from the previous core and schedule on the new core + scheduler->UnscheduleThread(this, current_priority); + next_scheduler->ScheduleThread(this, current_priority); // Change thread's scheduler scheduler = next_scheduler; + + Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); } //////////////////////////////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 46ec9a9bc924aa1151db349541976521b72c41da Mon Sep 17 00:00:00 2001 From: bunnei Date: Thu, 10 May 2018 19:12:46 -0400 Subject: thread: Rename mask to affinity_masks. --- src/core/hle/kernel/thread.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 04d18dc2f..46fcdefb8 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -201,7 +201,7 @@ void Thread::ResumeFromWait() { status = THREADSTATUS_READY; - boost::optional new_processor_id = GetNextProcessorId(mask); + boost::optional new_processor_id = GetNextProcessorId(affinity_mask); if (!new_processor_id) { new_processor_id = processor_id; } @@ -308,7 +308,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, thread->last_running_ticks = CoreTiming::GetTicks(); thread->processor_id = processor_id; thread->ideal_core = processor_id; - thread->mask = 1ULL << processor_id; + thread->affinity_mask = 1ULL << processor_id; thread->wait_objects.clear(); thread->mutex_wait_address = 0; thread->condvar_wait_address = 0; -- cgit v1.2.3