diff --git a/adk-rust/crates/awatch-agent-rs/Cargo.toml b/adk-rust/crates/awatch-agent-rs/Cargo.toml index cd8054e..8a7dd3b 100644 --- a/adk-rust/crates/awatch-agent-rs/Cargo.toml +++ b/adk-rust/crates/awatch-agent-rs/Cargo.toml @@ -22,4 +22,5 @@ tempfile.workspace = true [features] default = [] +asm-lowlevel = [] legacy-powershell = [] diff --git a/adk-rust/crates/awatch-agent-rs/src/lowlevel/cpu.rs b/adk-rust/crates/awatch-agent-rs/src/lowlevel/cpu.rs new file mode 100644 index 0000000..ed264cd --- /dev/null +++ b/adk-rust/crates/awatch-agent-rs/src/lowlevel/cpu.rs @@ -0,0 +1,75 @@ +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct CpuFeatures { + pub architecture: String, + pub backend: &'static str, + pub features: Vec, +} + +pub fn get_cpu_features() -> CpuFeatures { + let mut features = Vec::new(); + collect_cpu_features(&mut features); + features.sort(); + features.dedup(); + + CpuFeatures { + architecture: std::env::consts::ARCH.to_string(), + backend: super::LOWLEVEL_BACKEND, + features, + } +} + +#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] +fn collect_cpu_features(features: &mut Vec) { + for (name, detected) in [ + ("sse2", std::is_x86_feature_detected!("sse2")), + ("sse4.2", std::is_x86_feature_detected!("sse4.2")), + ("avx", std::is_x86_feature_detected!("avx")), + ("avx2", std::is_x86_feature_detected!("avx2")), + ("aes", std::is_x86_feature_detected!("aes")), + ] { + if detected { + features.push(name.to_string()); + } + } +} + +#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] +fn collect_cpu_features(features: &mut Vec) { + for name in compile_time_features() { + features.push(name.to_string()); + } +} + +#[cfg(all( + not(any(target_arch = "x86", target_arch = "x86_64")), + target_arch = "aarch64" +))] +fn compile_time_features() -> &'static [&'static str] { + &[ + #[cfg(target_feature = "aes")] + "aes", + #[cfg(target_feature = "neon")] + "neon", + ] +} + +#[cfg(all( + not(any(target_arch = "x86", target_arch = "x86_64")), + not(target_arch = "aarch64") +))] +fn compile_time_features() -> &'static [&'static str] { + &[] +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn cpu_features_have_architecture_and_backend() { + let features = get_cpu_features(); + + assert!(!features.architecture.trim().is_empty()); + assert!(!features.backend.trim().is_empty()); + } +} diff --git a/adk-rust/crates/awatch-agent-rs/src/lowlevel/mod.rs b/adk-rust/crates/awatch-agent-rs/src/lowlevel/mod.rs new file mode 100644 index 0000000..559fb09 --- /dev/null +++ b/adk-rust/crates/awatch-agent-rs/src/lowlevel/mod.rs @@ -0,0 +1,18 @@ +//! Safe low-level extension point for future agent optimizations. +//! +//! The default implementation is pure Rust. The `asm-lowlevel` feature is a +//! reserved integration point for future platform-specific CPU and timing +//! probes implemented through `core::arch`, inline assembly, or native OS +//! calls. Keep any future `unsafe` code isolated inside this module. + +pub mod cpu; +pub mod timing; + +pub use cpu::{CpuFeatures, get_cpu_features}; +pub use timing::{high_precision_time_ns, monotonic_ticks}; + +#[cfg(feature = "asm-lowlevel")] +pub const LOWLEVEL_BACKEND: &str = "asm-lowlevel-ready-rust-fallback"; + +#[cfg(not(feature = "asm-lowlevel"))] +pub const LOWLEVEL_BACKEND: &str = "rust"; diff --git a/adk-rust/crates/awatch-agent-rs/src/lowlevel/timing.rs b/adk-rust/crates/awatch-agent-rs/src/lowlevel/timing.rs new file mode 100644 index 0000000..06ab0bb --- /dev/null +++ b/adk-rust/crates/awatch-agent-rs/src/lowlevel/timing.rs @@ -0,0 +1,36 @@ +use std::sync::OnceLock; +use std::time::{Instant, SystemTime, UNIX_EPOCH}; + +static MONOTONIC_START: OnceLock = OnceLock::new(); + +pub fn monotonic_ticks() -> u128 { + MONOTONIC_START + .get_or_init(Instant::now) + .elapsed() + .as_nanos() +} + +pub fn high_precision_time_ns() -> u128 { + SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap_or_default() + .as_nanos() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn monotonic_ticks_do_not_go_backwards() { + let first = monotonic_ticks(); + let second = monotonic_ticks(); + + assert!(second >= first); + } + + #[test] + fn high_precision_time_is_epoch_based() { + assert!(high_precision_time_ns() > 1_000_000_000); + } +} diff --git a/adk-rust/crates/awatch-agent-rs/src/main.rs b/adk-rust/crates/awatch-agent-rs/src/main.rs index 080a71c..da08c64 100644 --- a/adk-rust/crates/awatch-agent-rs/src/main.rs +++ b/adk-rust/crates/awatch-agent-rs/src/main.rs @@ -1,5 +1,6 @@ mod collectors; mod config; +pub mod lowlevel; mod telemetry; mod transport;