#![deny(clippy::all, clippy::pedantic)]
#![warn(clippy::nursery, clippy::cargo)]
#![allow(clippy::missing_panics_doc, clippy::module_name_repetitions)]
#![cfg(any(target_os = "linux", target_os = "android"))]
mod cycles;
mod error;
pub mod ffi;
mod instant;
use std::ptr;
use ffi::CyclesReaderRaw;
use libc::{c_int, pid_t};
pub use cycles::Cycles;
pub use error::{Error, Result};
pub use instant::CyclesInstant;
#[derive(Debug)]
pub struct CyclesReader {
raw_ptr: *mut CyclesReaderRaw,
}
impl Drop for CyclesReader {
fn drop(&mut self) {
unsafe {
ffi::disableCyclesReader(self.raw_ptr);
ffi::destroyCyclesReader(self.raw_ptr);
}
self.raw_ptr = ptr::null_mut();
}
}
impl CyclesReader {
pub fn new(pid: Option<pid_t>) -> Result<Self> {
let cpus = c_int::try_from(num_cpus::get_physical())?;
let cpus: Vec<_> = (0..cpus).collect();
let cpus_ptr = cpus.as_ptr();
let raw_ptr = unsafe {
let ptr = ffi::createCyclesReader(cpus_ptr, cpus.len(), pid.unwrap_or(-1));
ffi::enableCyclesReader(ptr);
ptr
};
if raw_ptr.is_null() {
return Err(Error::FailedToCreate);
}
Ok(Self { raw_ptr })
}
pub fn instant(&self, cpu: c_int) -> Result<CyclesInstant> {
let raw = unsafe { ffi::readCyclesReader(self.raw_ptr, cpu) };
if raw == -1 {
Err(Error::FailedToRead)
} else {
let cycles = Cycles::new(raw);
let instant = CyclesInstant::new(cpu, cycles);
Ok(instant)
}
}
}