bcc/perf_event/
perf_map.rs

1use crate::cpuonline;
2use crate::error::BccError;
3use crate::perf_event::open_perf_buffer;
4use crate::perf_event::perf_reader::PerfReader;
5use crate::table::Table;
6use bcc_sys::bccapi::perf_reader;
7use bcc_sys::bccapi::perf_reader_poll;
8use byteorder::NativeEndian;
9use byteorder::WriteBytesExt;
10use std::io::Cursor;
11
12/// A builder type for producing `PerfMap`s
13pub struct PerfMapBuilder<F: Fn() -> Box<dyn FnMut(&[u8]) + Send>> {
14    table: Table,
15    cb: F,
16    page_count: i32,
17}
18
19impl<F: Fn() -> Box<dyn FnMut(&[u8]) + Send>> PerfMapBuilder<F> {
20    /// Create a new builder for a given table and callback function
21    pub fn new(table: Table, cb: F) -> Self {
22        Self {
23            table,
24            cb,
25            page_count: super::BPF_PERF_READER_PAGE_CNT,
26        }
27    }
28
29    /// Set the page count for the ringbuffer
30    pub fn page_count(mut self, page_count: i32) -> Self {
31        self.page_count = page_count;
32        self
33    }
34
35    /// Try constructing a `PerfMap` from the builder
36    pub fn build(mut self) -> Result<PerfMap, BccError> {
37        let key_size = self.table.key_size();
38        let leaf_size = self.table.leaf_size();
39        let leaf = vec![0; leaf_size];
40
41        if key_size != 4 || leaf_size != 4 {
42            return Err(BccError::TableInvalidSize);
43        }
44
45        let mut readers: Vec<PerfReader> = vec![];
46        let mut cur = Cursor::new(leaf);
47
48        let cpus = cpuonline::get()?;
49        for cpu in cpus.iter() {
50            let mut reader = open_perf_buffer(*cpu, (self.cb)(), self.page_count)?;
51            let perf_fd = reader.fd() as u32;
52            readers.push(reader);
53
54            let mut key = vec![];
55            key.write_u32::<NativeEndian>(*cpu as u32)?;
56            cur.write_u32::<NativeEndian>(perf_fd)?;
57            if self.table.set(&mut key, &mut cur.get_mut()).is_ok() {
58                cur.set_position(0);
59            } else {
60                return Err(BccError::InitializePerfMap);
61            }
62        }
63        Ok(PerfMap { readers })
64    }
65}
66
67#[allow(dead_code)]
68pub struct PerfMap {
69    pub(crate) readers: Vec<PerfReader>,
70}
71
72/// Convenience function to initialize a `PerfMap` without using the builder
73/// pattern. Will be deprecated in a future release.
74#[deprecated(
75    since = "0.0.30",
76    note = "Please use PerfMapBuilder to create a new PerfMap instead"
77)]
78pub fn init_perf_map<F>(table: Table, cb: F) -> Result<PerfMap, BccError>
79where
80    F: Fn() -> Box<dyn FnMut(&[u8]) + Send>,
81{
82    PerfMapBuilder::new(table, cb).build()
83}
84
85impl PerfMap {
86    pub fn poll(&mut self, timeout: i32) {
87        unsafe {
88            perf_reader_poll(
89                self.readers.len() as i32,
90                self.readers.as_ptr() as *mut *mut perf_reader,
91                timeout,
92            )
93        };
94    }
95}