cpu_instructions_reader/
lib.rs1#![deny(clippy::all, clippy::pedantic)]
19#![warn(clippy::nursery, clippy::cargo)]
20#![allow(clippy::missing_panics_doc, clippy::module_name_repetitions)]
21#![cfg(any(target_os = "linux", target_os = "android"))]
22mod error;
23pub mod ffi;
24mod instant;
25mod instruction_number;
26
27use std::ptr;
28
29use ffi::InstructionNumberReaderRaw;
30use libc::{c_int, pid_t};
31
32pub use error::{Error, Result};
33pub use instant::InstructionNumberInstant;
34pub use instruction_number::InstructionNumber;
35
36#[derive(Debug)]
37pub struct InstructionNumberReader {
38 raw_ptr: *mut InstructionNumberReaderRaw,
39}
40
41impl Drop for InstructionNumberReader {
42 fn drop(&mut self) {
43 unsafe {
44 ffi::disableInstructionNumberReader(self.raw_ptr);
45 ffi::destroyInstructionNumberReader(self.raw_ptr);
46 }
47 self.raw_ptr = ptr::null_mut();
48 }
49}
50
51impl InstructionNumberReader {
52 pub fn new(pid: Option<pid_t>) -> Result<Self> {
58 let cpus = c_int::try_from(num_cpus::get_physical())?;
59 let cpus: Vec<_> = (0..cpus).collect();
60 let cpus_ptr = cpus.as_ptr();
61
62 let raw_ptr =
63 unsafe { ffi::createInstructionNumberReader(cpus_ptr, cpus.len(), pid.unwrap_or(-1)) };
64
65 if raw_ptr.is_null() {
66 return Err(Error::FailedToCreate);
67 }
68
69 unsafe { ffi::enableInstructionNumberReader(raw_ptr) };
70
71 Ok(Self { raw_ptr })
72 }
73
74 pub fn instant(&self, cpu: c_int) -> Result<InstructionNumberInstant> {
78 let raw = unsafe { ffi::readInstructionNumberReader(self.raw_ptr, cpu) };
79
80 if raw == -1 {
81 Err(Error::FailedToRead)
82 } else {
83 let instructions = InstructionNumber::new(raw);
84 let instant = InstructionNumberInstant::new(cpu, instructions);
85 Ok(instant)
86 }
87 }
88}