Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix macOS collection of CPU data #7429

Merged
merged 2 commits into from
Sep 25, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions src/cargo/util/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,13 @@ mod imp {
mod imp {
use std::io;
use std::ptr;
use std::slice;

type host_t = u32;
type mach_port_t = u32;
type vm_map_t = mach_port_t;
type vm_offset_t = usize;
type vm_size_t = usize;
type vm_address_t = vm_offset_t;
type processor_flavor_t = i32;
type natural_t = u32;
type processor_info_array_t = *mut i32;
Expand All @@ -105,8 +108,11 @@ mod imp {
const CPU_STATE_SYSTEM: usize = 1;
const CPU_STATE_IDLE: usize = 2;
const CPU_STATE_NICE: usize = 3;
const CPU_STATE_MAX: usize = 4;

extern "C" {
static mut mach_task_self_: mach_port_t;

fn mach_host_self() -> mach_port_t;
fn host_processor_info(
host: host_t,
Expand All @@ -115,6 +121,11 @@ mod imp {
out_processor_info: *mut processor_info_array_t,
out_processor_infoCnt: *mut mach_msg_type_number_t,
) -> kern_return_t;
fn vm_deallocate(
target_task: vm_map_t,
address: vm_address_t,
size: vm_size_t,
) -> kern_return_t;
}

pub struct State {
Expand All @@ -124,34 +135,45 @@ mod imp {
nice: u64,
}

#[repr(C)]
struct processor_cpu_load_info_data_t {
cpu_ticks: [u32; CPU_STATE_MAX],
}

pub fn current() -> io::Result<State> {
// There's scant little documentation on `host_processor_info`
// throughout the internet, so this is just modeled after what everyone
// else is doing. For now this is modeled largely after libuv.

unsafe {
let mut num_cpus_u = 0;
let mut cpu_info = ptr::null_mut();
let mut cpu_info_cnt = 0;
let mut msg_type = 0;
let err = host_processor_info(
mach_host_self(),
PROESSOR_CPU_LOAD_INFO,
&mut num_cpus_u,
&mut cpu_info,
&mut cpu_info_cnt,
&mut msg_type,
);
if err != 0 {
return Err(io::Error::last_os_error());
}
let cpu_info = slice::from_raw_parts(cpu_info, cpu_info_cnt as usize);
let mut ret = State {
user: 0,
system: 0,
idle: 0,
nice: 0,
};
for chunk in cpu_info.chunks(num_cpus_u as usize) {
ret.user += chunk[CPU_STATE_USER] as u64;
ret.system += chunk[CPU_STATE_SYSTEM] as u64;
ret.idle += chunk[CPU_STATE_IDLE] as u64;
ret.nice += chunk[CPU_STATE_NICE] as u64;
let mut current = cpu_info as *const processor_cpu_load_info_data_t;
for _ in 0..num_cpus_u {
ret.user += (*current).cpu_ticks[CPU_STATE_USER] as u64;
ret.system += (*current).cpu_ticks[CPU_STATE_SYSTEM] as u64;
ret.idle += (*current).cpu_ticks[CPU_STATE_IDLE] as u64;
ret.nice += (*current).cpu_ticks[CPU_STATE_NICE] as u64;
current = current.offset(1);
}
vm_deallocate(mach_task_self_, cpu_info as vm_address_t, msg_type as usize);
Ok(ret)
}
}
Expand Down