summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp18
-rw-r--r--src/core/hle/kernel/k_thread.h1
2 files changed, 16 insertions, 3 deletions
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 5bdbd9a9b..e99122f4c 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -668,6 +668,7 @@ void KScheduler::Unload(KThread* thread) {
} else {
prev_thread = nullptr;
}
+ thread->context_guard.unlock();
}
}
@@ -700,15 +701,23 @@ void KScheduler::SwitchContextStep2() {
void KScheduler::ScheduleImpl() {
KThread* previous_thread = current_thread;
- current_thread = state.highest_priority_thread;
+ KThread* next_thread = state.highest_priority_thread;
state.needs_scheduling = false;
- if (current_thread == previous_thread) {
+ // We never want to schedule a null thread, so use the idle thread if we don't have a next.
+ if (next_thread == nullptr) {
+ next_thread = idle_thread;
+ }
+
+ // If we're not actually switching thread, there's nothing to do.
+ if (next_thread == current_thread) {
guard.unlock();
return;
}
+ current_thread = next_thread;
+
Process* const previous_process = system.Kernel().CurrentProcess();
UpdateLastContextSwitchTime(previous_thread, previous_process);
@@ -748,10 +757,13 @@ void KScheduler::SwitchToCurrent() {
};
do {
if (current_thread != nullptr) {
+ current_thread->context_guard.lock();
if (current_thread->GetRawState() != ThreadState::Runnable) {
+ current_thread->context_guard.unlock();
break;
}
- if (static_cast<u32>(current_thread->GetActiveCore()) != core_id) {
+ if (current_thread->GetActiveCore() != core_id) {
+ current_thread->context_guard.unlock();
break;
}
}
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 7845821ba..eeddf5a65 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -712,6 +712,7 @@ private:
s8 priority_inheritance_count{};
bool resource_limit_release_hint{};
StackParameters stack_parameters{};
+ Common::SpinLock context_guard{};
// For emulation
std::shared_ptr<Common::Fiber> host_context{};