perf_event_open/sample/record/
itrace.rs

1use super::{RecordId, Task};
2
3/// Instruction tracing has started.
4///
5/// Instruction tracing is a hardware feature that identifies every
6/// branch taken by a program so that we can reconstruct the actual
7/// control flow of the program.
8///
9/// Only limited platforms support this feature, such as Intel PT, Intel BTS, and Arm SPE.
10///
11/// # Examples
12///
13/// ```rust
14/// use std::fs::read_to_string;
15/// use std::sync::mpsc::channel;
16/// use std::thread;
17/// use std::time::Duration;
18///
19/// use perf_event_open::config::{Cpu, Opts, Proc};
20/// use perf_event_open::count::Counter;
21/// use perf_event_open::event::dp::DynamicPmu;
22///
23/// let (tid_tx, tid_rx) = channel();
24/// thread::spawn(move || {
25///     tid_tx.send(unsafe { libc::gettid() }).unwrap();
26///     loop {
27///         std::hint::spin_loop();
28///     }
29/// });
30///
31/// // Intel PT
32/// let ty = read_to_string("/sys/bus/event_source/devices/intel_pt/type");
33/// # if ty.is_err() {
34/// #     return;
35/// # }
36///
37/// let event = DynamicPmu {
38///     ty: ty.unwrap().lines().next().unwrap().parse().unwrap(),
39///     config: 0,
40///     config1: 0,
41///     config2: 0,
42///     config3: 0,
43/// };
44/// let target = (Proc(tid_rx.recv().unwrap() as _), Cpu::ALL);
45/// let opts = Opts::default();
46///
47/// let counter = Counter::new(event, target, opts).unwrap();
48/// let sampler = counter.sampler(10).unwrap();
49/// let aux = sampler.aux_tracer(10).unwrap();
50///
51/// counter.enable().unwrap();
52/// thread::sleep(Duration::from_millis(1));
53/// counter.disable().unwrap();
54///
55/// for it in sampler.iter() {
56///     println!("{:-?}", it);
57/// }
58/// while let Some(it) = aux.iter().next(None) {
59///     let bytes = it.len();
60///     println!("{:.2} KB", bytes as f64 / 1000.0);
61/// }
62/// ```
63///
64/// Since `linux-4.1`: <https://github.com/torvalds/linux/commit/ec0d7729bbaed4b9d2d3fada693278e13a3d1368>
65#[derive(Clone)]
66#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
67pub struct ItraceStart {
68    /// Record IDs.
69    pub record_id: Option<RecordId>,
70
71    /// Task info.
72    pub task: Task,
73}
74
75impl ItraceStart {
76    #[cfg(feature = "linux-4.1")]
77    pub(crate) unsafe fn from_ptr(
78        mut ptr: *const u8,
79        sample_id_all: Option<super::SampleType>,
80    ) -> Self {
81        use crate::ffi::deref_offset;
82
83        // https://github.com/torvalds/linux/blob/v6.13/include/uapi/linux/perf_event.h#L1093
84        // struct {
85        //     struct perf_event_header header;
86        //     u32 pid;
87        //     u32 tid;
88        //     struct sample_id sample_id;
89        // };
90
91        let task = Task {
92            pid: deref_offset(&mut ptr),
93            tid: deref_offset(&mut ptr),
94        };
95        let record_id = sample_id_all.map(|super::SampleType(ty)| RecordId::from_ptr(ptr, ty));
96
97        Self { record_id, task }
98    }
99}
100
101super::from!(ItraceStart);
102
103super::debug!(ItraceStart {
104    {record_id?},
105    {task},
106});