perf_event_open/sample/auxiliary/
mod.rs

1use std::fs::File;
2use std::io::Result;
3use std::sync::atomic::AtomicU64;
4
5use iter::{CowIter, Iter};
6use rb::Rb;
7
8use super::arena::Arena;
9use crate::ffi::Metadata;
10
11pub mod iter;
12mod rb;
13
14/// AUX tracer.
15///
16/// AUX tracer is used to export high bandwidth data streams to userspace,
17/// such as instruction flow traces. Not all hardware supports this feature.
18///
19/// # Examples
20///
21/// ```rust
22/// use std::fs::read_to_string;
23/// use std::sync::mpsc::channel;
24/// use std::thread;
25/// use std::time::Duration;
26///
27/// use perf_event_open::config::{Cpu, Opts, Proc};
28/// use perf_event_open::count::Counter;
29/// use perf_event_open::event::dp::DynamicPmu;
30///
31/// let (tid_tx, tid_rx) = channel();
32/// thread::spawn(move || {
33///     tid_tx.send(unsafe { libc::gettid() }).unwrap();
34///     loop {
35///         std::hint::spin_loop();
36///     }
37/// });
38///
39/// // Intel PT
40/// let ty = read_to_string("/sys/bus/event_source/devices/intel_pt/type");
41/// # if ty.is_err() {
42/// #     return;
43/// # }
44///
45/// let event = DynamicPmu {
46///     ty: ty.unwrap().lines().next().unwrap().parse().unwrap(),
47///     config: 0,
48///     config1: 0,
49///     config2: 0,
50///     config3: 0,
51/// };
52/// let target = (Proc(tid_rx.recv().unwrap() as _), Cpu::ALL);
53/// let opts = Opts::default();
54///
55/// let counter  = Counter::new(event, target, opts).unwrap();
56/// let sampler = counter.sampler(10).unwrap();
57/// let aux = sampler.aux_tracer(10).unwrap();
58///
59/// counter.enable().unwrap();
60/// thread::sleep(Duration::from_millis(1));
61/// counter.disable().unwrap();
62///
63/// for it in sampler.iter() {
64///     println!("{:-?}", it);
65/// }
66/// while let Some(it) = aux.iter().next(None) {
67///     let bytes = it.len();
68///     println!("{:.2} KB", bytes as f64 / 1000.0);
69/// }
70/// ```
71///
72/// Since `linux-4.1`: <https://github.com/torvalds/linux/commit/45bfb2e50471abbbfd83d40d28c986078b0d24ff>
73pub struct AuxTracer<'a> {
74    tail: &'a AtomicU64,
75    head: &'a AtomicU64,
76    arena: Arena,
77    perf: &'a File,
78}
79
80impl<'a> AuxTracer<'a> {
81    #[cfg(feature = "linux-4.1")]
82    pub(crate) fn new(perf: &'a File, metadata: &'a mut Metadata, exp: u8) -> Result<Self> {
83        metadata.aux_size = (2_usize.pow(exp as _) * *crate::ffi::PAGE_SIZE) as _;
84        metadata.aux_offset = metadata.data_offset + metadata.data_size;
85
86        let arena = Arena::new(perf, metadata.aux_size as _, metadata.aux_offset as _)?;
87        let tail = unsafe { AtomicU64::from_ptr(&mut metadata.aux_tail as _) };
88        let head = unsafe { AtomicU64::from_ptr(&mut metadata.aux_head as _) };
89
90        Ok(Self {
91            tail,
92            head,
93            arena,
94            perf,
95        })
96    }
97
98    #[cfg(not(feature = "linux-4.1"))]
99    pub(crate) fn new(_: &File, _: &'a mut Metadata, _: u8) -> Result<Self> {
100        crate::config::unsupported!()
101    }
102
103    /// Get an iterator of the AUX area.
104    pub fn iter(&self) -> Iter<'_> {
105        Iter(CowIter {
106            rb: Rb::new(self.arena.as_slice(), self.tail, self.head),
107            perf: self.perf,
108        })
109    }
110}