summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp102
1 files changed, 93 insertions, 9 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 1bd5d9ebf..46fcdefb8 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -64,7 +64,7 @@ void Thread::Stop() {
64 // Clean up thread from ready queue 64 // Clean up thread from ready queue
65 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) 65 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
66 if (status == THREADSTATUS_READY) { 66 if (status == THREADSTATUS_READY) {
67 Core::System::GetInstance().Scheduler().UnscheduleThread(this, current_priority); 67 scheduler->UnscheduleThread(this, current_priority);
68 } 68 }
69 69
70 status = THREADSTATUS_DEAD; 70 status = THREADSTATUS_DEAD;
@@ -92,7 +92,7 @@ void WaitCurrentThread_Sleep() {
92void ExitCurrentThread() { 92void ExitCurrentThread() {
93 Thread* thread = GetCurrentThread(); 93 Thread* thread = GetCurrentThread();
94 thread->Stop(); 94 thread->Stop();
95 Core::System::GetInstance().Scheduler().RemoveThread(thread); 95 Core::System::GetInstance().CurrentScheduler().RemoveThread(thread);
96} 96}
97 97
98/** 98/**
@@ -154,6 +154,18 @@ void Thread::CancelWakeupTimer() {
154 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle); 154 CoreTiming::UnscheduleEvent(ThreadWakeupEventType, callback_handle);
155} 155}
156 156
157static boost::optional<s32> GetNextProcessorId(u64 mask) {
158 for (s32 index = 0; index < Core::NUM_CPU_CORES; ++index) {
159 if (mask & (1ULL << index)) {
160 if (!Core::System().GetInstance().Scheduler(index)->GetCurrentThread()) {
161 // Core is enabled and not running any threads, use this one
162 return index;
163 }
164 }
165 }
166 return {};
167}
168
157void Thread::ResumeFromWait() { 169void Thread::ResumeFromWait() {
158 ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects"); 170 ASSERT_MSG(wait_objects.empty(), "Thread is waking up while waiting for objects");
159 171
@@ -188,8 +200,37 @@ void Thread::ResumeFromWait() {
188 wakeup_callback = nullptr; 200 wakeup_callback = nullptr;
189 201
190 status = THREADSTATUS_READY; 202 status = THREADSTATUS_READY;
191 Core::System::GetInstance().Scheduler().ScheduleThread(this, current_priority); 203
192 Core::System::GetInstance().PrepareReschedule(); 204 boost::optional<s32> new_processor_id = GetNextProcessorId(affinity_mask);
205 if (!new_processor_id) {
206 new_processor_id = processor_id;
207 }
208 if (ideal_core != -1 &&
209 Core::System().GetInstance().Scheduler(ideal_core)->GetCurrentThread() == nullptr) {
210 new_processor_id = ideal_core;
211 }
212
213 ASSERT(*new_processor_id < 4);
214
215 // Add thread to new core's scheduler
216 auto& next_scheduler = Core::System().GetInstance().Scheduler(*new_processor_id);
217
218 if (*new_processor_id != processor_id) {
219 // Remove thread from previous core's scheduler
220 scheduler->RemoveThread(this);
221 next_scheduler->AddThread(this, current_priority);
222 }
223
224 processor_id = *new_processor_id;
225
226 // If the thread was ready, unschedule from the previous core and schedule on the new core
227 scheduler->UnscheduleThread(this, current_priority);
228 next_scheduler->ScheduleThread(this, current_priority);
229
230 // Change thread's scheduler
231 scheduler = next_scheduler;
232
233 Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule();
193} 234}
194 235
195/** 236/**
@@ -259,8 +300,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
259 300
260 SharedPtr<Thread> thread(new Thread); 301 SharedPtr<Thread> thread(new Thread);
261 302
262 Core::System::GetInstance().Scheduler().AddThread(thread, priority);
263
264 thread->thread_id = NewThreadId(); 303 thread->thread_id = NewThreadId();
265 thread->status = THREADSTATUS_DORMANT; 304 thread->status = THREADSTATUS_DORMANT;
266 thread->entry_point = entry_point; 305 thread->entry_point = entry_point;
@@ -268,6 +307,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
268 thread->nominal_priority = thread->current_priority = priority; 307 thread->nominal_priority = thread->current_priority = priority;
269 thread->last_running_ticks = CoreTiming::GetTicks(); 308 thread->last_running_ticks = CoreTiming::GetTicks();
270 thread->processor_id = processor_id; 309 thread->processor_id = processor_id;
310 thread->ideal_core = processor_id;
311 thread->affinity_mask = 1ULL << processor_id;
271 thread->wait_objects.clear(); 312 thread->wait_objects.clear();
272 thread->mutex_wait_address = 0; 313 thread->mutex_wait_address = 0;
273 thread->condvar_wait_address = 0; 314 thread->condvar_wait_address = 0;
@@ -275,6 +316,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
275 thread->name = std::move(name); 316 thread->name = std::move(name);
276 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); 317 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
277 thread->owner_process = owner_process; 318 thread->owner_process = owner_process;
319 thread->scheduler = Core::System().GetInstance().Scheduler(processor_id);
320 thread->scheduler->AddThread(thread, priority);
278 321
279 // Find the next available TLS index, and mark it as used 322 // Find the next available TLS index, and mark it as used
280 auto& tls_slots = owner_process->tls_slots; 323 auto& tls_slots = owner_process->tls_slots;
@@ -337,7 +380,7 @@ void Thread::SetPriority(u32 priority) {
337} 380}
338 381
339void Thread::BoostPriority(u32 priority) { 382void Thread::BoostPriority(u32 priority) {
340 Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority); 383 scheduler->SetThreadPriority(this, priority);
341 current_priority = priority; 384 current_priority = priority;
342} 385}
343 386
@@ -406,7 +449,7 @@ void Thread::UpdatePriority() {
406 if (new_priority == current_priority) 449 if (new_priority == current_priority)
407 return; 450 return;
408 451
409 Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority); 452 scheduler->SetThreadPriority(this, new_priority);
410 453
411 current_priority = new_priority; 454 current_priority = new_priority;
412 455
@@ -415,13 +458,54 @@ void Thread::UpdatePriority() {
415 lock_owner->UpdatePriority(); 458 lock_owner->UpdatePriority();
416} 459}
417 460
461void Thread::ChangeCore(u32 core, u64 mask) {
462 ideal_core = core;
463 mask = mask;
464
465 if (status != THREADSTATUS_READY) {
466 return;
467 }
468
469 boost::optional<s32> new_processor_id{GetNextProcessorId(mask)};
470
471 if (!new_processor_id) {
472 new_processor_id = processor_id;
473 }
474 if (ideal_core != -1 &&
475 Core::System().GetInstance().Scheduler(ideal_core)->GetCurrentThread() == nullptr) {
476 new_processor_id = ideal_core;
477 }
478
479 ASSERT(new_processor_id < 4);
480
481 // Add thread to new core's scheduler
482 auto& next_scheduler = Core::System().GetInstance().Scheduler(*new_processor_id);
483
484 if (*new_processor_id != processor_id) {
485 // Remove thread from previous core's scheduler
486 scheduler->RemoveThread(this);
487 next_scheduler->AddThread(this, current_priority);
488 }
489
490 processor_id = *new_processor_id;
491
492 // If the thread was ready, unschedule from the previous core and schedule on the new core
493 scheduler->UnscheduleThread(this, current_priority);
494 next_scheduler->ScheduleThread(this, current_priority);
495
496 // Change thread's scheduler
497 scheduler = next_scheduler;
498
499 Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule();
500}
501
418//////////////////////////////////////////////////////////////////////////////////////////////////// 502////////////////////////////////////////////////////////////////////////////////////////////////////
419 503
420/** 504/**
421 * Gets the current thread 505 * Gets the current thread
422 */ 506 */
423Thread* GetCurrentThread() { 507Thread* GetCurrentThread() {
424 return Core::System::GetInstance().Scheduler().GetCurrentThread(); 508 return Core::System::GetInstance().CurrentScheduler().GetCurrentThread();
425} 509}
426 510
427void ThreadingInit() { 511void ThreadingInit() {