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}