hle: kernel: k_scheduler: Use atomics for current_thread, etc.

This commit is contained in:
bunnei 2021-01-21 11:26:00 -08:00
parent f6b10fad63
commit 37f74d8741
2 changed files with 28 additions and 26 deletions

View file

@ -80,7 +80,7 @@ u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) {
} }
state.highest_priority_thread = highest_thread; state.highest_priority_thread = highest_thread;
state.needs_scheduling = true; state.needs_scheduling.store(true);
return (1ULL << core_id); return (1ULL << core_id);
} else { } else {
return 0; return 0;
@ -609,7 +609,7 @@ void KScheduler::YieldToAnyThread(KernelCore& kernel) {
KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core_id(core_id) { KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core_id(core_id) {
switch_fiber = std::make_shared<Common::Fiber>(OnSwitch, this); switch_fiber = std::make_shared<Common::Fiber>(OnSwitch, this);
state.needs_scheduling = true; state.needs_scheduling.store(true);
state.interrupt_task_thread_runnable = false; state.interrupt_task_thread_runnable = false;
state.should_count_idle = false; state.should_count_idle = false;
state.idle_count = 0; state.idle_count = 0;
@ -620,10 +620,10 @@ KScheduler::KScheduler(Core::System& system, s32 core_id) : system(system), core
KScheduler::~KScheduler() = default; KScheduler::~KScheduler() = default;
KThread* KScheduler::GetCurrentThread() const { KThread* KScheduler::GetCurrentThread() const {
if (current_thread) { if (auto result = current_thread.load(); result) {
return current_thread; return result;
} }
return idle_thread; return idle_thread.get();
} }
u64 KScheduler::GetLastContextSwitchTicks() const { u64 KScheduler::GetLastContextSwitchTicks() const {
@ -638,7 +638,7 @@ void KScheduler::RescheduleCurrentCore() {
phys_core.ClearInterrupt(); phys_core.ClearInterrupt();
} }
guard.lock(); guard.lock();
if (state.needs_scheduling) { if (state.needs_scheduling.load()) {
Schedule(); Schedule();
} else { } else {
guard.unlock(); guard.unlock();
@ -695,29 +695,29 @@ void KScheduler::Reload(KThread* thread) {
void KScheduler::SwitchContextStep2() { void KScheduler::SwitchContextStep2() {
// Load context of new thread // Load context of new thread
Reload(current_thread); Reload(current_thread.load());
RescheduleCurrentCore(); RescheduleCurrentCore();
} }
void KScheduler::ScheduleImpl() { void KScheduler::ScheduleImpl() {
KThread* previous_thread = current_thread; KThread* previous_thread = current_thread.load();
KThread* next_thread = state.highest_priority_thread; KThread* next_thread = state.highest_priority_thread;
state.needs_scheduling = false; state.needs_scheduling = false;
// We never want to schedule a null thread, so use the idle thread if we don't have a next. // We never want to schedule a null thread, so use the idle thread if we don't have a next.
if (next_thread == nullptr) { if (next_thread == nullptr) {
next_thread = idle_thread; next_thread = idle_thread.get();
} }
// If we're not actually switching thread, there's nothing to do. // If we're not actually switching thread, there's nothing to do.
if (next_thread == current_thread) { if (next_thread == current_thread.load()) {
guard.unlock(); guard.unlock();
return; return;
} }
current_thread = next_thread; current_thread.store(next_thread);
Process* const previous_process = system.Kernel().CurrentProcess(); Process* const previous_process = system.Kernel().CurrentProcess();
@ -749,28 +749,29 @@ void KScheduler::SwitchToCurrent() {
while (true) { while (true) {
{ {
std::scoped_lock lock{guard}; std::scoped_lock lock{guard};
current_thread = state.highest_priority_thread; current_thread.store(state.highest_priority_thread);
state.needs_scheduling = false; state.needs_scheduling.store(false);
} }
const auto is_switch_pending = [this] { const auto is_switch_pending = [this] {
std::scoped_lock lock{guard}; std::scoped_lock lock{guard};
return state.needs_scheduling.load(std::memory_order_relaxed); return state.needs_scheduling.load();
}; };
do { do {
if (current_thread != nullptr) { auto next_thread = current_thread.load();
current_thread->context_guard.lock(); if (next_thread != nullptr) {
if (current_thread->GetRawState() != ThreadState::Runnable) { next_thread->context_guard.lock();
current_thread->context_guard.unlock(); if (next_thread->GetRawState() != ThreadState::Runnable) {
next_thread->context_guard.unlock();
break; break;
} }
if (current_thread->GetActiveCore() != core_id) { if (next_thread->GetActiveCore() != core_id) {
current_thread->context_guard.unlock(); next_thread->context_guard.unlock();
break; break;
} }
} }
std::shared_ptr<Common::Fiber>* next_context; std::shared_ptr<Common::Fiber>* next_context;
if (current_thread != nullptr) { if (next_thread != nullptr) {
next_context = &current_thread->GetHostContext(); next_context = &next_thread->GetHostContext();
} else { } else {
next_context = &idle_thread->GetHostContext(); next_context = &idle_thread->GetHostContext();
} }
@ -802,7 +803,7 @@ void KScheduler::Initialize() {
auto thread_res = KThread::Create(system, ThreadType::Main, name, 0, auto thread_res = KThread::Create(system, ThreadType::Main, name, 0,
KThread::IdleThreadPriority, 0, static_cast<u32>(core_id), 0, KThread::IdleThreadPriority, 0, static_cast<u32>(core_id), 0,
nullptr, std::move(init_func), init_func_parameter); nullptr, std::move(init_func), init_func_parameter);
idle_thread = thread_res.Unwrap().get(); idle_thread = thread_res.Unwrap();
} }
KScopedSchedulerLock::KScopedSchedulerLock(KernelCore& kernel) KScopedSchedulerLock::KScopedSchedulerLock(KernelCore& kernel)

View file

@ -54,7 +54,7 @@ public:
/// Returns true if the scheduler is idle /// Returns true if the scheduler is idle
[[nodiscard]] bool IsIdle() const { [[nodiscard]] bool IsIdle() const {
return GetCurrentThread() == idle_thread; return GetCurrentThread() == idle_thread.get();
} }
/// Gets the timestamp for the last context switch in ticks. /// Gets the timestamp for the last context switch in ticks.
@ -174,8 +174,9 @@ private:
void SwitchToCurrent(); void SwitchToCurrent();
KThread* prev_thread{}; KThread* prev_thread{};
KThread* current_thread{}; std::atomic<KThread*> current_thread{};
KThread* idle_thread{};
std::shared_ptr<KThread> idle_thread;
std::shared_ptr<Common::Fiber> switch_fiber{}; std::shared_ptr<Common::Fiber> switch_fiber{};