|
|
@ -47,13 +47,13 @@ u32 GlobalScheduler::SelectThreads() { |
|
|
ASSERT(is_locked); |
|
|
ASSERT(is_locked); |
|
|
const auto update_thread = [](Thread* thread, Scheduler& sched) { |
|
|
const auto update_thread = [](Thread* thread, Scheduler& sched) { |
|
|
sched.guard.lock(); |
|
|
sched.guard.lock(); |
|
|
if (thread != sched.selected_thread.get()) { |
|
|
|
|
|
|
|
|
if (thread != sched.selected_thread_set.get()) { |
|
|
if (thread == nullptr) { |
|
|
if (thread == nullptr) { |
|
|
++sched.idle_selection_count; |
|
|
++sched.idle_selection_count; |
|
|
} |
|
|
} |
|
|
sched.selected_thread = SharedFrom(thread); |
|
|
|
|
|
|
|
|
sched.selected_thread_set = SharedFrom(thread); |
|
|
} |
|
|
} |
|
|
const bool reschedule_pending = sched.selected_thread != sched.current_thread; |
|
|
|
|
|
|
|
|
const bool reschedule_pending = sched.selected_thread_set != sched.current_thread; |
|
|
sched.is_context_switch_pending = reschedule_pending; |
|
|
sched.is_context_switch_pending = reschedule_pending; |
|
|
std::atomic_thread_fence(std::memory_order_seq_cst); |
|
|
std::atomic_thread_fence(std::memory_order_seq_cst); |
|
|
sched.guard.unlock(); |
|
|
sched.guard.unlock(); |
|
|
@ -118,6 +118,8 @@ u32 GlobalScheduler::SelectThreads() { |
|
|
suggested); |
|
|
suggested); |
|
|
top_threads[candidate_core] = next; |
|
|
top_threads[candidate_core] = next; |
|
|
break; |
|
|
break; |
|
|
|
|
|
} else { |
|
|
|
|
|
suggested = nullptr; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -590,7 +592,7 @@ void Scheduler::OnThreadStart() { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void Scheduler::SwitchContextStep2() { |
|
|
void Scheduler::SwitchContextStep2() { |
|
|
Thread* previous_thread = current_thread.get(); |
|
|
|
|
|
|
|
|
Thread* previous_thread = current_thread_prev.get(); |
|
|
Thread* new_thread = selected_thread.get(); |
|
|
Thread* new_thread = selected_thread.get(); |
|
|
|
|
|
|
|
|
// Load context of new thread
|
|
|
// Load context of new thread
|
|
|
@ -606,8 +608,6 @@ void Scheduler::SwitchContextStep2() { |
|
|
"Thread must be ready to become running."); |
|
|
"Thread must be ready to become running."); |
|
|
|
|
|
|
|
|
// Cancel any outstanding wakeup events for this thread
|
|
|
// Cancel any outstanding wakeup events for this thread
|
|
|
current_thread = SharedFrom(new_thread); |
|
|
|
|
|
new_thread->SetStatus(ThreadStatus::Running); |
|
|
|
|
|
new_thread->SetIsRunning(true); |
|
|
new_thread->SetIsRunning(true); |
|
|
|
|
|
|
|
|
auto* const thread_owner_process = current_thread->GetOwnerProcess(); |
|
|
auto* const thread_owner_process = current_thread->GetOwnerProcess(); |
|
|
@ -622,21 +622,21 @@ void Scheduler::SwitchContextStep2() { |
|
|
cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); |
|
|
cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); |
|
|
cpu_core.ClearExclusiveState(); |
|
|
cpu_core.ClearExclusiveState(); |
|
|
} |
|
|
} |
|
|
} else { |
|
|
|
|
|
current_thread = nullptr; |
|
|
|
|
|
// Note: We do not reset the current process and current page table when idling because
|
|
|
|
|
|
// technically we haven't changed processes, our threads are just paused.
|
|
|
|
|
|
} |
|
|
} |
|
|
guard.unlock(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TryDoContextSwitch(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
void Scheduler::SwitchContext() { |
|
|
void Scheduler::SwitchContext() { |
|
|
Thread* previous_thread = current_thread.get(); |
|
|
|
|
|
|
|
|
current_thread_prev = current_thread; |
|
|
|
|
|
selected_thread = selected_thread_set; |
|
|
|
|
|
Thread* previous_thread = current_thread_prev.get(); |
|
|
Thread* new_thread = selected_thread.get(); |
|
|
Thread* new_thread = selected_thread.get(); |
|
|
|
|
|
current_thread = selected_thread; |
|
|
|
|
|
|
|
|
is_context_switch_pending = false; |
|
|
is_context_switch_pending = false; |
|
|
|
|
|
guard.unlock(); |
|
|
if (new_thread == previous_thread) { |
|
|
if (new_thread == previous_thread) { |
|
|
guard.unlock(); |
|
|
|
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|