scx_rusty: fix "subtract with overflow" error

It seems that under certain conditions, the difference between the
current and the previous procfs::CpuStat values may become negative,
triggering the following crash/trace:

thread 'main' panicked at /build/rustc-VvCkKl/rustc-1.73.0+dfsg0ubuntu1/library/core/src/ops/arith.rs:217:1:
attempt to subtract with overflow
stack backtrace:
...
  19:     0x590d8481909e - scx_rusty::calc_util::h46f2af9c512c2ecd
                               at /home/arighi/src/scx/scheds/rust-user/scx_rusty/src/main.rs:217:31
  20:     0x590d8481c794 - scx_rusty::Tuner::step::h2e51076f043a8593
                               at /home/arighi/src/scx/scheds/rust-user/scx_rusty/src/main.rs:444:38
  21:     0x590d84828270 - scx_rusty::Scheduler::run::hb5483f1e585f52fe
                               at /home/arighi/src/scx/scheds/rust-user/scx_rusty/src/main.rs:1198:17
  22:     0x590d848289e9 - scx_rusty::main::h9ba8c62ad33aeee1
...

Prevent this by introducing a sub_or_zero() helper function that returns
zero if the difference is negative.

Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
This commit is contained in:
Andrea Righi 2023-12-09 10:20:02 +01:00
parent 330e104eae
commit c5d1bc3577

View File

@ -187,6 +187,15 @@ fn read_total_cpu(reader: &procfs::ProcReader) -> Result<procfs::CpuStat> {
.ok_or_else(|| anyhow!("Could not read total cpu stat in proc"))
}
fn sub_or_zero(curr: &u64, prev: &u64) -> u64
{
if let Some(res) = curr.checked_sub(*prev) {
res
} else {
0
}
}
fn calc_util(curr: &procfs::CpuStat, prev: &procfs::CpuStat) -> Result<f64> {
match (curr, prev) {
(
@ -213,14 +222,14 @@ fn calc_util(curr: &procfs::CpuStat, prev: &procfs::CpuStat) -> Result<f64> {
..
},
) => {
let idle_usec = curr_idle - prev_idle;
let iowait_usec = curr_iowait - prev_iowait;
let user_usec = curr_user - prev_user;
let system_usec = curr_system - prev_system;
let nice_usec = curr_nice - prev_nice;
let irq_usec = curr_irq - prev_irq;
let softirq_usec = curr_softirq - prev_softirq;
let stolen_usec = curr_stolen - prev_stolen;
let idle_usec = sub_or_zero(curr_idle, prev_idle);
let iowait_usec = sub_or_zero(curr_iowait, prev_iowait);
let user_usec = sub_or_zero(curr_user, prev_user);
let system_usec = sub_or_zero(curr_system, prev_system);
let nice_usec = sub_or_zero(curr_nice, prev_nice);
let irq_usec = sub_or_zero(curr_irq, prev_irq);
let softirq_usec = sub_or_zero(curr_softirq, prev_softirq);
let stolen_usec = sub_or_zero(curr_stolen, prev_stolen);
let busy_usec =
user_usec + system_usec + nice_usec + irq_usec + softirq_usec + stolen_usec;
@ -994,14 +1003,14 @@ impl<'a> Scheduler<'a> {
guest_nice_usec: _,
},
) => {
let idle_usec = curr_idle - prev_idle;
let iowait_usec = curr_iowait - prev_iowait;
let user_usec = curr_user - prev_user;
let system_usec = curr_system - prev_system;
let nice_usec = curr_nice - prev_nice;
let irq_usec = curr_irq - prev_irq;
let softirq_usec = curr_softirq - prev_softirq;
let stolen_usec = curr_stolen - prev_stolen;
let idle_usec = sub_or_zero(curr_idle, prev_idle);
let iowait_usec = sub_or_zero(curr_iowait, prev_iowait);
let user_usec = sub_or_zero(curr_user, prev_user);
let system_usec = sub_or_zero(curr_system, prev_system);
let nice_usec = sub_or_zero(curr_nice, prev_nice);
let irq_usec = sub_or_zero(curr_irq, prev_irq);
let softirq_usec = sub_or_zero(curr_softirq, prev_softirq);
let stolen_usec = sub_or_zero(curr_stolen, prev_stolen);
let busy_usec =
user_usec + system_usec + nice_usec + irq_usec + softirq_usec + stolen_usec;