#![allow(non_snake_case)]
#![allow(dead_code)]
use crate::ported::linux::linuxmachine::CPUData;
#[cfg(target_os = "linux")]
use std::sync::atomic::{AtomicBool, Ordering};
#[cfg(target_os = "linux")]
use libmedium::{
parse_hwmons,
sensors::sync_sensors::{temp::TempSensor, SyncSensor},
};
#[cfg(target_os = "linux")]
static SENSORS_INITIALIZED: AtomicBool = AtomicBool::new(false);
pub fn LibSensors_init() -> i32 {
#[cfg(target_os = "linux")]
{
match parse_hwmons() {
Ok(_) => {
SENSORS_INITIALIZED.store(true, Ordering::Relaxed);
0
}
Err(_) => -1,
}
}
#[cfg(not(target_os = "linux"))]
{
-1
}
}
pub fn LibSensors_cleanup() {
#[cfg(target_os = "linux")]
{
SENSORS_INITIALIZED.store(false, Ordering::Relaxed);
}
}
pub fn LibSensors_reload() -> i32 {
#[cfg(target_os = "linux")]
{
if !SENSORS_INITIALIZED.load(Ordering::Relaxed) {
return -1;
}
match parse_hwmons() {
Ok(_) => 0,
Err(_) => -1,
}
}
#[cfg(not(target_os = "linux"))]
{
-1
}
}
fn tempDriverPriority(prefix: &str) -> i32 {
const TEMP_DRIVERS: &[(&str, i32)] = &[
("coretemp", 0),
("via_cputemp", 0),
("cpu_thermal", 0),
("k10temp", 0),
("zenpower", 0),
("littlecore_thermal", 0),
("bigcore0_thermal", 0),
("bigcore1_thermal", 0),
("bigcore2_thermal", 0),
("soc_thermal", 0),
("cpu0_thermal", 0),
("cpu1_thermal", 0),
("cpu2_thermal", 0),
("cpu3_thermal", 0),
("cpu4_thermal", 0),
("cpu5_thermal", 0),
("cpu6_thermal", 0),
("cpu7_thermal", 0),
("scpi_sensors", 0),
("cpu0_1_thermal", 0),
("cpu2_3_thermal", 0),
("acpitz", 1),
];
for &(p, priority) in TEMP_DRIVERS {
if prefix == p {
return priority;
}
}
-1
}
pub fn LibSensors_countCCDs() -> i32 {
#[cfg(target_os = "linux")]
{
if !SENSORS_INITIALIZED.load(Ordering::Relaxed) {
return 0;
}
let hwmons = match parse_hwmons() {
Ok(h) => h,
Err(_) => return 0,
};
let mut ccds = 0;
for hwmon in hwmons.iter() {
for (_tempID, sensor) in hwmon.temps() {
if sensor.name().starts_with("Tccd") {
ccds += 1;
}
}
}
ccds
}
#[cfg(not(target_os = "linux"))]
{
0
}
}
fn LibSensors_stringToID(str: &str) -> i32 {
let bytes = str.as_bytes();
let len = bytes.len();
let mut i = 0;
while i < len && bytes[i].is_ascii_whitespace() {
i += 1;
}
let mut negate = false;
if i < len && (bytes[i] == b'+' || bytes[i] == b'-') {
negate = bytes[i] == b'-';
i += 1;
}
let digitStart = i;
let mut parsedID: u64 = 0;
while i < len && bytes[i].is_ascii_digit() {
parsedID = parsedID
.saturating_mul(10)
.saturating_add((bytes[i] - b'0') as u64);
i += 1;
}
let endptr = if i == digitStart { 0 } else { i };
let value = if negate {
0u64.wrapping_sub(parsedID)
} else {
parsedID
};
if value >= i32::MAX as u64 || endptr < len {
return -1;
}
value as i32
}
pub fn LibSensors_getCPUTemperatures(cpus: &mut [CPUData], existingCPUs: u32, activeCPUs: u32) {
debug_assert!(existingCPUs > 0 && existingCPUs < 16384);
let existing = existingCPUs as usize;
#[allow(unused_mut)]
let mut data = vec![f64::NAN; existing + 1];
#[cfg(target_os = "linux")]
{
let active = activeCPUs as usize;
if SENSORS_INITIALIZED.load(Ordering::Relaxed) {
if let Ok(hwmons) = parse_hwmons() {
let mut coreTempCount: usize = 0;
let mut topPriority: i32 = 99;
let mut ccdID: i32 = 0;
for hwmon in hwmons.iter() {
let prefix = hwmon.name();
let priority = tempDriverPriority(prefix);
if priority < 0 {
continue;
}
if priority > topPriority {
continue;
}
if priority < topPriority {
for d in data.iter_mut() {
*d = f64::NAN;
}
}
topPriority = priority;
let mut physicalID: i32 = 0;
for (&tempIDraw, sensor) in hwmon.temps() {
if tempIDraw == 0 {
continue;
}
let tempID = (tempIDraw - 1) as usize;
let temp = match sensor.read_input() {
Ok(t) => t.as_degrees_celsius(),
Err(_) => continue,
};
if existing == 8 {
let pb = prefix.as_bytes();
if prefix.starts_with("cpu")
&& pb.len() > 3
&& pb[3] >= b'0'
&& pb[3] <= b'7'
&& &prefix[4..] == "_thermal"
{
data[1 + (pb[3] - b'0') as usize] = temp;
coreTempCount += 1;
continue;
}
if prefix == "littlecore_thermal" {
data[1] = temp;
data[2] = temp;
data[3] = temp;
data[4] = temp;
coreTempCount += 4;
continue;
}
if prefix == "bigcore0_thermal" {
data[5] = temp;
data[6] = temp;
coreTempCount += 2;
continue;
}
if prefix == "bigcore1_thermal" || prefix == "bigcore2_thermal" {
data[7] = temp;
data[8] = temp;
coreTempCount += 2;
continue;
}
}
if existing == 4 && prefix == "soc_thermal" {
data[1] = temp;
data[2] = temp;
data[3] = temp;
data[4] = temp;
coreTempCount += 4;
continue;
}
if existing == 4 {
if prefix == "cpu0_1_thermal" {
data[1] = temp;
data[2] = temp;
coreTempCount += 2;
continue;
}
if prefix == "cpu2_3_thermal" {
data[3] = temp;
data[4] = temp;
coreTempCount += 2;
continue;
}
}
if prefix == "scpi_sensors" {
for d in data.iter_mut() {
*d = temp;
}
coreTempCount = existing;
continue;
}
let label = sensor.name();
{
let mut skip = true;
if let Some(rest) = label.strip_prefix("Package id ") {
let id = LibSensors_stringToID(rest);
if id != -1 {
physicalID = id;
}
} else if let Some(rest) = label.strip_prefix("Physical id ") {
let id = LibSensors_stringToID(rest);
if id != -1 {
physicalID = id;
}
} else if let Some(rest) = label.strip_prefix("Core ") {
let id = LibSensors_stringToID(rest);
if id != -1 {
for i in 1..=existing {
if cpus[i].physicalID == physicalID && cpus[i].coreID == id
{
data[i] = temp;
coreTempCount += 1;
}
}
}
}
else if label.starts_with("Tccd") {
for i in 1..=existing {
if cpus[i].ccdID == ccdID {
data[i] = temp;
coreTempCount += 1;
}
}
ccdID += 1;
}
else if label == "Tctl" {
for i in 0..=existing {
if data[i].is_nan() {
data[i] = temp;
if i > 0 {
coreTempCount += 1;
}
}
}
} else {
skip = false;
}
if skip {
continue;
}
}
if tempID > existing {
continue;
}
if data[tempID].is_nan() {
data[tempID] = temp;
if tempID > 0 {
coreTempCount += 1;
}
} else {
data[tempID] = data[tempID].max(temp);
}
}
}
'adjust: {
if coreTempCount + 1 == active || coreTempCount + 1 == active / 2 {
data.copy_within(0..existing, 1);
data[0] = f64::NAN;
coreTempCount += 1;
}
if coreTempCount == 0 && !data[0].is_nan() {
for i in 1..=existing {
data[i] = data[0];
}
break 'adjust;
}
if coreTempCount > 0 && data[0].is_nan() {
let mut maxTemp = f64::NEG_INFINITY;
for i in 1..=existing {
if data[i] > maxTemp {
maxTemp = data[i];
data[0] = data[i];
}
}
}
if coreTempCount == 1 && !data[1].is_nan() {
for i in 2..=existing {
data[i] = data[1];
}
break 'adjust;
}
let delta = active / 2;
if coreTempCount == delta && delta > 0 {
data.copy_within(1..1 + delta, delta + 1);
break 'adjust;
}
}
}
}
}
#[cfg(not(target_os = "linux"))]
{
let _ = activeCPUs;
}
for i in 0..=existing {
cpus[i].temperature = data[i];
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn LibSensors_stringToID_parses_plain_decimal() {
assert_eq!(LibSensors_stringToID("0"), 0);
assert_eq!(LibSensors_stringToID("7"), 7);
assert_eq!(LibSensors_stringToID("12"), 12);
}
#[test]
fn LibSensors_stringToID_rejects_trailing_garbage() {
assert_eq!(LibSensors_stringToID("12abc"), -1);
assert_eq!(LibSensors_stringToID("1 "), -1);
assert_eq!(LibSensors_stringToID("abc"), -1);
}
#[test]
fn LibSensors_stringToID_rejects_at_or_above_int_max() {
assert_eq!(LibSensors_stringToID(&i32::MAX.to_string()), -1);
assert_eq!(
LibSensors_stringToID(&(i32::MAX as i64 - 1).to_string()),
i32::MAX - 1
);
assert_eq!(LibSensors_stringToID("999999999999999999999999"), -1);
}
#[test]
fn LibSensors_stringToID_empty_string_is_zero() {
assert_eq!(LibSensors_stringToID(""), 0);
}
#[test]
fn LibSensors_stringToID_negative_is_rejected() {
assert_eq!(LibSensors_stringToID("-5"), -1);
}
}