use crate::api::{HostBudget, HostMemory};
pub const STALL_ENTER: u32 = 500;
pub const STALL_LEAVE: u32 = 100;
const MARGIN_MIN: u64 = 2 << 30;
const MARGIN_SHARE: u64 = 16;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Remembered {
pub short: bool,
pub stalled: bool,
}
pub fn margin(total: u64, short: bool) -> u64 {
let margin = MARGIN_MIN.max(total / MARGIN_SHARE);
if short {
margin.saturating_add(margin / 2)
} else {
margin
}
}
pub fn stalls(memory: &HostMemory, before: bool) -> bool {
let full = memory.full.map_or(0, |full| full.avg10);
let stalling = full >= STALL_ENTER || (before && full >= STALL_LEAVE);
stalling && memory.available < margin(memory.total, false).saturating_mul(2)
}
pub fn budget(memory: HostMemory, reserved: u64, remembered: Remembered) -> HostBudget {
let stalled = stalls(&memory, remembered.stalled);
let limit = memory
.slice
.saturating_add(memory.available)
.saturating_sub(margin(memory.total, remembered.short || stalled));
HostBudget {
memory,
limit,
spare: if stalled {
0
} else {
limit.saturating_sub(reserved)
},
stalled,
}
}