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});