#![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 instruction_number;
mod error;
pub mod ffi;
mod instant;
use std::ptr;
use ffi::InstructionNumberReaderRaw;
use libc::{c_int, pid_t};
pub use instruction_number::InstructionNumber;
pub use error::{Error, Result};
pub use instant::InstructionNumberInstant;
#[derive(Debug)]
pub struct InstructionNumberReader {
raw_ptr: *mut InstructionNumberReaderRaw,
}
impl Drop for InstructionNumberReader {
fn drop(&mut self) {
unsafe {
ffi::disableInstructionNumberReader(self.raw_ptr);
ffi::destroyInstructionNumberReader(self.raw_ptr);
}
self.raw_ptr = ptr::null_mut();
}
}
impl InstructionNumberReader {
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::createInstructionNumberReader(cpus_ptr, cpus.len(), pid.unwrap_or(-1));
ffi::enableInstructionNumberReader(ptr);
ptr
};
if raw_ptr.is_null() {
return Err(Error::FailedToCreate);
}
Ok(Self { raw_ptr })
}
pub fn instant_of_spec(&self, cpu: c_int) -> Result<InstructionNumberInstant> {
let raw = unsafe { ffi::readInstructionNumberReaderSpec(self.raw_ptr, cpu) };
if raw == -1 {
Err(Error::FailedToRead)
} else {
let instructions = InstructionNumber::new(raw);
let instant = InstructionNumberInstant::new(cpu, instructions);
Ok(instant)
}
}
pub fn instant_of_all(&self) -> Result<InstructionNumberInstant> {
let raw = unsafe { ffi::readInstructionNumberReaderAll(self.raw_ptr) };
if raw == -1 {
Err(Error::FailedToRead)
} else {
let instructions = InstructionNumber::new(raw);
let instant = InstructionNumberInstant::new(-1, instructions);
Ok(instant)
}
}
}