scx_rustland: ignore built-in selection logic with --full-user

The option --full-user is provided to delegate *all* scheduling
decisions to the user-space scheduler with no exception, including the
idle selection logic.

Therefore, make this option incompatible with --builtin-idle and
completely bypass the built-in idle selection logic when running in
full-user mode.

Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
This commit is contained in:
Andrea Righi 2024-05-21 23:11:10 +02:00
parent 9e4bea4a1c
commit cca84479f8

View File

@ -28,6 +28,7 @@ use std::path::Path;
use anyhow::Context;
use anyhow::Result;
use anyhow::bail;
use clap::Parser;
use log::info;
use log::warn;
@ -108,6 +109,8 @@ struct Opts {
///
/// By default always dispatch tasks on the first CPU available to increase system
/// responsiveness over throughput, especially when the system is overloaded.
///
/// NOTE: this option cannot be used with --full-user.
#[clap(short = 'i', long, action = clap::ArgAction::SetTrue)]
builtin_idle: bool,
@ -276,6 +279,7 @@ struct Scheduler<'a> {
init_page_faults: u64, // Initial page faults counter
builtin_idle: bool, // Use sched-ext built-in idle selection logic
no_preemption: bool, // Disable task preemption
full_user: bool, // Run all tasks through the user-space scheduler
}
impl<'a> Scheduler<'a> {
@ -284,6 +288,10 @@ impl<'a> Scheduler<'a> {
let topo = Topology::new().expect("Failed to build host topology");
let topo_map = TopologyMap::new(topo).expect("Failed to generate topology map");
if opts.full_user && opts.builtin_idle {
bail!("--full-user cannot be used together with --builtin-idle");
}
// Save the default time slice (in ns) in the scheduler class.
let slice_ns = opts.slice_us * NSEC_PER_USEC;
@ -296,6 +304,9 @@ impl<'a> Scheduler<'a> {
// Disable task preemption.
let no_preemption = opts.no_preemption;
// Run all tasks through the user-space scheduler.
let full_user = opts.full_user;
// Scheduler task pool to sort tasks by vruntime.
let task_pool = TaskTree::new();
@ -334,6 +345,7 @@ impl<'a> Scheduler<'a> {
init_page_faults,
builtin_idle,
no_preemption,
full_user,
})
}
@ -538,8 +550,9 @@ impl<'a> Scheduler<'a> {
// available.
let mut dispatched_task = DispatchedTask::new(&task.qtask);
// Set special dispatch flags.
if !self.builtin_idle {
// In full-user mode we skip the built-in idle selection logic, so simply
// dispatch all the tasks on the first CPU available.
if self.full_user || !self.builtin_idle {
dispatched_task.set_flag(RL_CPU_ANY);
}
if task.is_interactive && !self.no_preemption {