use crate::cpuonline;
use bcc_sys::bccapi::*;
use std::fs::File;
use std::hash::{Hash, Hasher};
use std::os::unix::prelude::*;
#[derive(Debug)]
pub struct PerfEvent {
ev_type: u32,
ev_config: u32,
code_fd: File,
p: Vec<i32>,
}
impl PerfEvent {
#[allow(clippy::too_many_arguments)]
pub fn new(
code: File,
ev_type: u32,
ev_config: u32,
sample_period: u64,
sample_freq: u64,
pid: i32,
cpu: Option<usize>,
group_fd: i32,
) -> Result<Self, ()> {
let mut vec: Vec<i32> = vec![];
if let Some(cpu) = cpu {
let ptr = unsafe {
bpf_attach_perf_event(
code.as_raw_fd(),
ev_type,
ev_config,
sample_period,
sample_freq,
pid,
cpu as i32,
group_fd,
)
};
if ptr < 0 {
Self::close_all_events(&mut vec);
return Err(());
}
vec.push(ptr);
} else if let Ok(cpus) = cpuonline::get() {
for i in cpus {
let ptr = unsafe {
bpf_attach_perf_event(
code.as_raw_fd(),
ev_type,
ev_config,
sample_period,
sample_freq,
pid,
i as i32,
group_fd,
)
};
if ptr < 0 {
Self::close_all_events(&mut vec);
return Err(());
}
vec.push(ptr);
}
}
Ok(Self {
ev_type,
ev_config,
p: vec,
code_fd: code,
})
}
fn close_all_events(vec: &mut Vec<i32>) {
vec.retain(|v| {
unsafe {
bpf_close_perf_event_fd(*v);
}
false
});
}
}
impl Drop for PerfEvent {
fn drop(&mut self) {
Self::close_all_events(&mut self.p);
}
}
impl Eq for PerfEvent {}
impl Hash for PerfEvent {
fn hash<H: Hasher>(&self, state: &mut H) {
(self.ev_config, self.ev_type).hash(state);
}
}
impl PartialEq for PerfEvent {
fn eq(&self, other: &Self) -> bool {
self.ev_config == other.ev_config && self.ev_type == other.ev_type
}
}