ax-task 0.7.1

OS-independent IRQ-safe SMP task scheduling core
Documentation
use super::*;

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) enum FairBalanceTimer {
    Idle,
    Armed(MonotonicDeadline),
    Pending,
}

#[derive(Debug)]
pub(crate) struct OwnerDispatchState {
    pub(crate) fair_balance_interval_ns: u64,
    pub(crate) fair_balance_timer: FairBalanceTimer,
    pub(crate) switch_handoff: Option<SwitchHandoff>,
    idle_pull_pending: bool,
    idle_pull_visited: CpuSet,
}

impl OwnerDispatchState {
    pub(crate) fn new(config: TaskSystemConfig) -> Self {
        Self {
            fair_balance_interval_ns: config.balance_interval_ns().max(1),
            fair_balance_timer: FairBalanceTimer::Idle,
            switch_handoff: None,
            idle_pull_pending: true,
            idle_pull_visited: CpuSet::empty(config.cpu_count()),
        }
    }

    pub(crate) fn publish_fair_balance_due(&mut self, now: MonotonicInstant) -> bool {
        match self.fair_balance_timer {
            FairBalanceTimer::Pending => true,
            FairBalanceTimer::Armed(deadline) if now.reached(deadline) => {
                self.fair_balance_timer = FairBalanceTimer::Pending;
                true
            }
            FairBalanceTimer::Idle | FairBalanceTimer::Armed(_) => false,
        }
    }

    pub(crate) fn defer_fair_balance(&mut self, now: MonotonicInstant, interval_ns: u64) {
        self.fair_balance_timer = FairBalanceTimer::Armed(
            now.deadline_after(core::time::Duration::from_nanos(interval_ns.max(1))),
        );
    }

    pub(crate) const fn fair_balance_deadline(&self) -> Option<MonotonicDeadline> {
        match self.fair_balance_timer {
            FairBalanceTimer::Armed(deadline) => Some(deadline),
            FairBalanceTimer::Idle | FairBalanceTimer::Pending => None,
        }
    }

    pub(crate) const fn fair_balance_pending(&self) -> bool {
        matches!(self.fair_balance_timer, FairBalanceTimer::Pending)
    }

    pub(crate) fn clear_fair_balance(&mut self) {
        self.fair_balance_timer = FairBalanceTimer::Idle;
    }

    pub(crate) fn arm_idle_pull(&mut self) {
        self.idle_pull_pending = true;
        self.idle_pull_visited.clear();
    }

    pub(crate) const fn idle_pull_pending(&self) -> bool {
        self.idle_pull_pending
    }

    pub(crate) fn take_idle_pull_pending(&mut self) -> bool {
        core::mem::replace(&mut self.idle_pull_pending, false)
    }

    pub(crate) const fn idle_pull_visited(&self) -> &CpuSet {
        &self.idle_pull_visited
    }

    pub(crate) fn mark_idle_pull_source(&mut self, source: CpuId) {
        assert!(
            self.idle_pull_visited.insert(source),
            "one idle-pull scan cannot visit the same source twice"
        );
    }

    pub(crate) fn reset_idle_pull_scan(&mut self) {
        self.idle_pull_visited.clear();
    }
}