mirror of
https://github.com/citra-emu/citra.git
synced 2024-12-18 18:10:08 +00:00
Kernel: Removed the priority boost code for starved threads.
After hwtesting and reverse engineering the kernel, it was found that the CTROS scheduler performs no priority boosting for threads like this, although some other forms of scheduling priority-starved threads might take place. For example, it was found that hardware interrupts might cause low-priority threads to run if the CPU is preempted in the middle of an SVC handler that deschedules the current (high priority) thread before scheduling it again.
This commit is contained in:
parent
f20d872643
commit
933df2606a
@ -156,28 +156,6 @@ void ArbitrateAllThreads(u32 address) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Boost low priority threads (temporarily) that have been starved
|
|
||||||
static void PriorityBoostStarvedThreads() {
|
|
||||||
u64 current_ticks = CoreTiming::GetTicks();
|
|
||||||
|
|
||||||
for (auto& thread : thread_list) {
|
|
||||||
// TODO(bunnei): Threads that have been waiting to be scheduled for `boost_ticks` (or
|
|
||||||
// longer) will have their priority temporarily adjusted to 1 higher than the highest
|
|
||||||
// priority thread to prevent thread starvation. This general behavior has been verified
|
|
||||||
// on hardware. However, this is almost certainly not perfect, and the real CTR OS scheduler
|
|
||||||
// should probably be reversed to verify this.
|
|
||||||
|
|
||||||
const u64 boost_timeout = 2000000; // Boost threads that have been ready for > this long
|
|
||||||
|
|
||||||
u64 delta = current_ticks - thread->last_running_ticks;
|
|
||||||
|
|
||||||
if (thread->status == THREADSTATUS_READY && delta > boost_timeout) {
|
|
||||||
const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0);
|
|
||||||
thread->BoostPriority(priority);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switches the CPU's active thread context to that of the specified thread
|
* Switches the CPU's active thread context to that of the specified thread
|
||||||
* @param new_thread The thread to switch to
|
* @param new_thread The thread to switch to
|
||||||
@ -211,9 +189,6 @@ static void SwitchContext(Thread* new_thread) {
|
|||||||
ready_queue.remove(new_thread->current_priority, new_thread);
|
ready_queue.remove(new_thread->current_priority, new_thread);
|
||||||
new_thread->status = THREADSTATUS_RUNNING;
|
new_thread->status = THREADSTATUS_RUNNING;
|
||||||
|
|
||||||
// Restores thread to its nominal priority if it has been temporarily changed
|
|
||||||
new_thread->current_priority = new_thread->nominal_priority;
|
|
||||||
|
|
||||||
Core::CPU().LoadContext(new_thread->context);
|
Core::CPU().LoadContext(new_thread->context);
|
||||||
Core::CPU().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress());
|
Core::CPU().SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress());
|
||||||
} else {
|
} else {
|
||||||
@ -557,8 +532,6 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reschedule() {
|
void Reschedule() {
|
||||||
PriorityBoostStarvedThreads();
|
|
||||||
|
|
||||||
Thread* cur = GetCurrentThread();
|
Thread* cur = GetCurrentThread();
|
||||||
Thread* next = PopNextReadyThread();
|
Thread* next = PopNextReadyThread();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user