use super::classes_from_processor_records;
use super::records::RELATION_PROCESSOR_CORE;
use crate::topology::types::EfficiencyClass;
use core::mem::size_of;
use std::ffi::c_void;
const MAX_BUFFER_BYTES: usize = 1024 * 1024;
extern "system" {
fn GetLogicalProcessorInformationEx(
relationship_type: u32,
buffer: *mut c_void,
returned_length: *mut u32,
) -> i32;
}
pub(super) fn detect(logical_processors: usize) -> Option<Box<[EfficiencyClass]>> {
classes_from_processor_records(&core_records()?, logical_processors)
}
pub(in crate::topology::cpu) fn core_records() -> Option<Vec<u8>> {
if size_of::<usize>() != 8 {
return None;
}
let mut returned_length = 0u32;
let first_call = unsafe {
GetLogicalProcessorInformationEx(
RELATION_PROCESSOR_CORE,
core::ptr::null_mut(),
core::ptr::addr_of_mut!(returned_length),
)
};
if first_call != 0 {
return None;
}
let buffer_length = usize::try_from(returned_length).ok()?;
if buffer_length == 0 || buffer_length > MAX_BUFFER_BYTES {
return None;
}
let mut buffer = vec![0u8; buffer_length];
let second_call = unsafe {
GetLogicalProcessorInformationEx(
RELATION_PROCESSOR_CORE,
buffer.as_mut_ptr().cast(),
core::ptr::addr_of_mut!(returned_length),
)
};
if second_call == 0 {
return None;
}
let used = usize::try_from(returned_length).ok()?;
buffer.truncate(used.min(buffer.len()));
Some(buffer)
}