Add a multi-level feedback queue (MLFQ) scheduler - #1117
Open
mutehimself wants to merge 1 commit into
Open
Conversation
Closes theseus-os#1096. Adds kernel/scheduler_mlfq alongside the existing round-robin/priority/epoch schedulers, selectable via `THESEUS_CONFIG=mlfq_scheduler`. - 8 priority levels; new tasks start at level 0 (highest priority), so short-lived/interactive tasks run promptly without ever being demoted. - Quanta grow linearly with level depth, so tasks that prove themselves CPU-bound are scheduled less often but for longer stretches, amortizing context-switch overhead for exactly the workload that doesn't need low latency. - Demotion is based on CPU time actually measured at dispatch (an Instant recorded when a task is picked, charged against it the next time `next` runs), not on counting yields, so a task can't dodge demotion by chunking CPU-bound work into pieces smaller than its quantum. - A task that's no longer runnable when charged (it blocked rather than exhausting its quantum) is never demoted — this is the actual mechanism that makes MLFQ favor interactive/I/O-bound tasks over CPU-bound ones, with no static classification required. - A periodic priority boost resets every task to level 0, bounding worst-case wait time and preventing starvation of long-demoted tasks. - Implements `PriorityScheduler`, so `scheduler::inherit_priority` (used by `sync_block` to prevent unbounded priority inversion when a higher-priority task blocks on a lock held by a lower-priority one) keeps working correctly when this policy is selected. Also updates `ps` to show the priority/level column under `mlfq_scheduler`, matching its existing behavior for the epoch/priority schedulers. Benchmarked against round-robin via the `scheduler_eval -m` mode added in the following commit: under a mix of 4 CPU-bound and 16 interactive tasks pinned to one CPU, MLFQ roughly halves average interactive-task completion latency (406ms vs. 772ms) relative to round-robin, while also lowering CPU-bound latency and overall makespan.
mutehimself
pushed a commit
to mutehimself/MuteOS
that referenced
this pull request
Aug 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #1096. Adds
kernel/scheduler_mlfq, a new scheduler policy alongside the existing round-robin/priority/epoch schedulers, selectable viaTHESEUS_CONFIG=mlfq_scheduler.PriorityScheduler, soscheduler::inherit_priority(used bysync_blockto prevent unbounded priority inversion) keeps working correctly under this policy — without it, a lock holder could sit at a low MLFQ level while higher-priority waiters starved behind it.Also updates
psto show the priority/level column undermlfq_scheduler, matching its existing behavior for the epoch/priority schedulers.Benchmark (addresses #758)
scheduler_eval's only mode measured aggregate time for N identical tasks to yield, which can't distinguish a scheduler that favors interactive tasks from one that doesn't, since every task behaves the same way. Added a-m/--mixedmode that spawns a configurable mix of CPU-bound tasks (busy loop, never yields) and interactive tasks (short work bursts, yields between each), and reports each group's completion-latency distribution separately.Results, one run each, 4 CPU-bound + 16 interactive tasks pinned to one CPU (run headlessly in QEMU via a
first_applicationswap +isa-debug-exit, same mechanismqemu_testuses):mlfq_schedulerMLFQ roughly halves interactive-task latency relative to round-robin under identical CPU-bound contention, while also lowering CPU-bound latency and overall makespan (plausibly from fewer total context switches, since demoted tasks get longer quanta). Caveat: single run per scheduler under QEMU/TCG software emulation, so absolute numbers aren't representative of real hardware and the makespan difference in particular could partly reflect run-to-run emulation variance — the interactive-vs-CPU-bound ratio within each run is the more trustworthy comparison. Multiple trials and/or real hardware would firm this up further.
Test plan
cargo checkagainst thex86_64-unknown-theseustarget forscheduler_mlfq,spawn/ps(with--cfg mlfq_scheduler), andscheduler_eval.make iso THESEUS_CONFIG=mlfq_schedulerbuild, booted in QEMU: clean SMP bring-up (4 CPUs), memory/ACPI/PCI/PS2/framebuffer init, shell loaded, no panics.scheduler_eval -mrun headlessly under bothmlfq_schedulerand default round-robin for the comparison above.BASE_QUANTUM/BOOST_INTERVAL(currently fixed constants) should be configurable, and on test coverage expectations for a new scheduler policy.