hardware 0.0.9

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
use core::sync::atomic::{AtomicU64, Ordering};

use crate::runtime::resources;

static IDLE_TIMEOUT_NS: AtomicU64 = AtomicU64::new(30_000_000_000);

pub fn set_idle_timeout_ns(ns: u64) {
    IDLE_TIMEOUT_NS.store(ns, Ordering::Release);
}

pub fn idle_timeout_ns() -> u64 {
    IDLE_TIMEOUT_NS.load(Ordering::Acquire)
}

pub struct ReapResult {
    pub dma_reaped: bool,
    pub mem_reaped: bool,
    pub irq_reaped: bool,
    pub swap_reaped: bool,
    pub cpu_reaped: bool,
    pub workers_killed: usize,
}

pub fn reap_idle() -> ReapResult {
    let timeout = IDLE_TIMEOUT_NS.load(Ordering::Acquire);
    let now = crate::sys::monotonic_ns();

    let mut result = ReapResult {
        dma_reaped: false,
        mem_reaped: false,
        irq_reaped: false,
        swap_reaped: false,
        cpu_reaped: false,
        workers_killed: 0,
    };

    if timeout == 0 {
        return result;
    }

    if resources::dma_allocated() > 0 && is_stale(resources::last_activity_dma(), now, timeout) {
        resources::force_reset_dma();
        result.dma_reaped = true;
    }

    if resources::memory_allocated() > 0 && is_stale(resources::last_activity_mem(), now, timeout) {
        resources::force_reset_mem();
        result.mem_reaped = true;
    }

    if resources::irq_registered() > 0 && is_stale(resources::last_activity_irq(), now, timeout) {
        resources::force_reset_irq();
        result.irq_reaped = true;
    }

    if resources::swap_allocated() > 0 && is_stale(resources::last_activity_swap(), now, timeout) {
        resources::force_reset_swap();
        result.swap_reaped = true;
    }

    if resources::cpu_threads() > 0 && is_stale(resources::last_activity_cpu(), now, timeout) {
        let workers = crate::runtime::worker::worker_count();
        crate::runtime::worker::stop_workers();
        resources::force_reset_cpu();
        result.cpu_reaped = true;
        result.workers_killed = workers;
    }

    result
}

fn is_stale(last: u64, now: u64, timeout: u64) -> bool {
    if last == 0 {
        return false;
    }
    now.saturating_sub(last) >= timeout
}