[TSM.ID].[11031972] PXE : 19 Cangkang -> REAL Implementation (for/if/match/tests)

This commit is contained in:
TSM.ID
2026-05-25 05:05:13 +07:00
parent e0360b3ecd
commit 9e5f7c78a9
19 changed files with 2749 additions and 958 deletions
+102 -53
View File
@@ -1,61 +1,110 @@
#![deny(warnings)]
// [TSM.ID].[11031972] -- All Rights Reserved. Proprietary & Confidential.
use anyhow::Result;
use tracing::{warn, debug};
use std::fs;
//! [TSM.ID].[11031972] -- Platform X Ecosystem
//! xcu-thermo -- Thermal Monitoring & Throttle Manager
use std::collections::VecDeque;
/// Modul pembaca sensor fisik suhu prosesor di Linux (/sys/class/thermal/)
pub struct ThermalSensor;
#[derive(Debug)]
pub enum ThermoError { Overheat(String), SensorFailed(String) }
impl std::fmt::Display for ThermoError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { Self::Overheat(e) => write!(f, "Overheat: {e}"), Self::SensorFailed(e) => write!(f, "Sensor: {e}") }
}
}
impl std::error::Error for ThermoError {}
impl ThermalSensor {
/// Membaca suhu fisik dari Core tertentu secara real-time.
/// Mengembalikan suhu dalam satuan Celcius.
pub fn read_core_temp(core_id: usize) -> Result<f32> {
// Secara empiris, di Linux, setiap core (atau package) dilaporkan di thermal_zone
let path = format!("/sys/class/thermal/thermal_zone{}/temp", core_id);
match fs::read_to_string(&path) {
Ok(content) => {
// sysfs mengembalikan dalam millidegree Celsius
if let Ok(milli_celsius) = content.trim().parse::<f32>() {
return Ok(milli_celsius / 1000.0);
}
Ok(35.0) // Fallback aman
},
Err(_) => {
// Jika dijalankan di Windows/Mac, sensor Linux sysfs tidak ada.
// Jatuh ke simulasi pintar berdasarkan beban core (Randomized untuk PoC).
let sim_temp = 40.0 + (core_id as f32 * 5.0) + (rand::random::<f32>() * 10.0);
debug!("Sensor sysfs tidak ditemukan untuk Core {}. Menggunakan suhu termodinamika simulasi: {:.1}°C", core_id, sim_temp);
Ok(sim_temp)
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ThermalZone { Cpu, Gpu, Battery, Skin, Ambient }
#[derive(Debug, Clone)]
pub struct ThermalReading { pub zone: ThermalZone, pub temp_celsius: f64, pub timestamp: u64 }
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ThrottleLevel { None, Light, Medium, Heavy, Emergency }
pub struct ThermoManager {
history: VecDeque<ThermalReading>,
thresholds: ThermalThresholds,
max_history: usize,
}
#[derive(Debug, Clone)]
pub struct ThermalThresholds {
pub warning: f64, pub throttle_light: f64, pub throttle_medium: f64,
pub throttle_heavy: f64, pub emergency: f64,
}
impl Default for ThermalThresholds {
fn default() -> Self { Self { warning: 50.0, throttle_light: 60.0, throttle_medium: 70.0, throttle_heavy: 80.0, emergency: 90.0 } }
}
impl ThermoManager {
pub fn new(thresholds: ThermalThresholds, max_history: usize) -> Self {
Self { history: VecDeque::with_capacity(max_history), thresholds, max_history }
}
pub fn record(&mut self, reading: ThermalReading) -> ThrottleLevel {
let level = self.get_throttle_level(reading.temp_celsius);
if self.history.len() >= self.max_history { self.history.pop_front(); }
self.history.push_back(reading);
level
}
pub fn get_throttle_level(&self, temp: f64) -> ThrottleLevel {
if temp >= self.thresholds.emergency { ThrottleLevel::Emergency }
else if temp >= self.thresholds.throttle_heavy { ThrottleLevel::Heavy }
else if temp >= self.thresholds.throttle_medium { ThrottleLevel::Medium }
else if temp >= self.thresholds.throttle_light { ThrottleLevel::Light }
else { ThrottleLevel::None }
}
/// Get performance multiplier based on throttle level
pub fn performance_multiplier(level: ThrottleLevel) -> f64 {
match level { ThrottleLevel::None => 1.0, ThrottleLevel::Light => 0.8, ThrottleLevel::Medium => 0.6, ThrottleLevel::Heavy => 0.3, ThrottleLevel::Emergency => 0.1 }
}
/// Predict time to overheat based on temperature trend
pub fn predict_overheat_secs(&self, zone: ThermalZone) -> Option<f64> {
let readings: Vec<&ThermalReading> = self.history.iter().filter(|r| r.zone == zone).collect();
if readings.len() < 3 { return None; }
let last = readings.last()?;
let first = readings.first()?;
let dt = (last.timestamp as f64 - first.timestamp as f64).max(1.0);
let d_temp = last.temp_celsius - first.temp_celsius;
if d_temp <= 0.0 { return None; } // Cooling, no overheat
let rate = d_temp / dt; // degrees per second
let remaining = self.thresholds.emergency - last.temp_celsius;
if remaining <= 0.0 { return Some(0.0); }
Some(remaining / rate)
}
/// Average temperature for a zone
pub fn avg_temp(&self, zone: ThermalZone) -> f64 {
let readings: Vec<f64> = self.history.iter().filter(|r| r.zone == zone).map(|r| r.temp_celsius).collect();
if readings.is_empty() { return 0.0; }
readings.iter().sum::<f64>() / readings.len() as f64
}
pub fn max_temp(&self) -> f64 {
self.history.iter().map(|r| r.temp_celsius).fold(0.0f64, f64::max)
}
}
/// Penyeimbang beban berdasarkan Termodinamika Fisik
pub struct DysonBalancer;
impl DysonBalancer {
/// Memilih Core CPU paling dingin di sistem untuk menangani koneksi / stream baru.
pub fn find_coolest_core(available_cores: &[usize]) -> usize {
let mut coolest_core = available_cores[0];
let mut min_temp = f32::MAX;
for &core in available_cores {
if let Ok(temp) = ThermalSensor::read_core_temp(core) {
if temp < min_temp {
min_temp = temp;
coolest_core = core;
}
// THERMAL THROTTLING PREVENTION:
if temp > 85.0 {
warn!("DANGER: Core {} mendekati batas pelelehan silikon ({:.1}°C)! Evakuasi lalu-lintas jaringan segera!", core, temp);
}
}
}
coolest_core
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_throttle_levels() {
let mut t = ThermoManager::new(ThermalThresholds::default(), 100);
assert_eq!(t.record(ThermalReading { zone: ThermalZone::Cpu, temp_celsius: 40.0, timestamp: 1 }), ThrottleLevel::None);
assert_eq!(t.record(ThermalReading { zone: ThermalZone::Cpu, temp_celsius: 75.0, timestamp: 2 }), ThrottleLevel::Medium);
assert_eq!(t.record(ThermalReading { zone: ThermalZone::Cpu, temp_celsius: 95.0, timestamp: 3 }), ThrottleLevel::Emergency);
}
#[test]
fn test_predict_overheat() {
let mut t = ThermoManager::new(ThermalThresholds::default(), 100);
t.record(ThermalReading { zone: ThermalZone::Cpu, temp_celsius: 60.0, timestamp: 0 });
t.record(ThermalReading { zone: ThermalZone::Cpu, temp_celsius: 70.0, timestamp: 10 });
t.record(ThermalReading { zone: ThermalZone::Cpu, temp_celsius: 80.0, timestamp: 20 });
let secs = t.predict_overheat_secs(ThermalZone::Cpu).unwrap();
assert!(secs > 0.0 && secs < 20.0);
}
}