Skip to content

Commit

Permalink
Fix a panic collecting cpu data on OSX
Browse files Browse the repository at this point in the history
There's very little documentation on `host_processor_info` from what I
can tell, so I'm just cribbing examples I've found elsewhere on the
internet. It appears that I've misinterpreted one of the out parameters
of `host_processor_info` as the number of elements of an array, but it
actually is just something forwarded to `vm_deallocate`.
  • Loading branch information
alexcrichton committed Sep 25, 2019
1 parent e8a9d3a commit 0c812db
Showing 1 changed file with 20 additions and 14 deletions.
34 changes: 20 additions & 14 deletions src/cargo/util/cpu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ mod imp {
mod imp {
use std::io;
use std::ptr;
use std::slice;

type host_t = u32;
type mach_port_t = u32;
Expand All @@ -109,6 +108,7 @@ 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;
Expand All @@ -135,39 +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 = 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_slice.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,
cpu_info_cnt as usize,
);
vm_deallocate(mach_task_self_, cpu_info as vm_address_t, msg_type as usize);
Ok(ret)
}
}
Expand Down

0 comments on commit 0c812db

Please sign in to comment.