perf_event_open/count/
stat.rs1use crate::ffi::{bindings as b, deref_offset};
2use crate::sample::record::debug;
3
4#[derive(Clone)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10pub struct Stat {
11 pub count: u64,
13
14 pub id: Option<u64>,
16
17 pub time_enabled: Option<u64>,
22
23 pub time_running: Option<u64>,
27
28 pub lost_records: Option<u64>,
35
36 pub siblings: Vec<SiblingStat>,
38}
39
40impl Stat {
41 pub(crate) unsafe fn from_ptr_offset(ptr: &mut *const u8, read_format: u64) -> Self {
62 macro_rules! when {
63 ($flag:ident, $ty:ty) => {
64 (read_format & (b::$flag as u64) > 0).then(|| deref_offset::<$ty>(ptr))
65 };
66 }
67
68 if read_format & b::PERF_FORMAT_GROUP as u64 == 0 {
69 let count = deref_offset(ptr);
70 let time_enabled = when!(PERF_FORMAT_TOTAL_TIME_ENABLED, u64);
71 let time_running = when!(PERF_FORMAT_TOTAL_TIME_RUNNING, u64);
72 let id = when!(PERF_FORMAT_ID, u64);
73 #[cfg(feature = "linux-6.0")]
74 let lost_records = when!(PERF_FORMAT_LOST, u64);
75 #[cfg(not(feature = "linux-6.0"))]
76 let lost_records = None;
77
78 Self {
79 count,
80 id,
81 time_enabled,
82 time_running,
83 lost_records,
84 siblings: vec![],
85 }
86 } else {
87 let nr: u64 = deref_offset(ptr);
88 let time_enabled = when!(PERF_FORMAT_TOTAL_TIME_ENABLED, u64);
89 let time_running = when!(PERF_FORMAT_TOTAL_TIME_RUNNING, u64);
90
91 let count = deref_offset(ptr);
92 let id = when!(PERF_FORMAT_ID, u64);
93 #[cfg(feature = "linux-6.0")]
94 let lost_records = when!(PERF_FORMAT_LOST, u64);
95 #[cfg(not(feature = "linux-6.0"))]
96 let lost_records = None;
97
98 let siblings = (1..nr)
99 .map(|_| {
100 let count = deref_offset(ptr);
101 let id = when!(PERF_FORMAT_ID, u64);
102 #[cfg(feature = "linux-6.0")]
103 let lost_records = when!(PERF_FORMAT_LOST, u64);
104 #[cfg(not(feature = "linux-6.0"))]
105 let lost_records = None;
106
107 SiblingStat {
108 count,
109 id,
110 lost_records,
111 }
112 })
113 .collect();
114
115 Self {
116 count,
117 id,
118 time_enabled,
119 time_running,
120 lost_records,
121 siblings,
122 }
123 }
124 }
125
126 pub(crate) unsafe fn from_ptr(mut ptr: *const u8, read_format: u64) -> Self {
127 Self::from_ptr_offset(&mut ptr, read_format)
128 }
129
130 pub(crate) fn read_buf_size(group_size: usize, read_format: u64) -> usize {
131 let mut size = size_of::<u64>();
132
133 macro_rules! when {
134 ($flag:ident, $size:expr) => {
135 if read_format & b::$flag as u64 > 0 {
136 size += $size;
137 }
138 };
139 }
140
141 when!(PERF_FORMAT_TOTAL_TIME_ENABLED, size_of::<u64>());
142 when!(PERF_FORMAT_TOTAL_TIME_RUNNING, size_of::<u64>());
143 when!(PERF_FORMAT_GROUP, group_size * size_of::<u64>());
144 when!(PERF_FORMAT_ID, group_size * size_of::<u64>());
145 #[cfg(feature = "linux-6.0")]
146 when!(PERF_FORMAT_LOST, group_size * size_of::<u64>());
147
148 size
149 }
150}
151
152debug!(Stat {
153 {count},
154 {id?},
155 {time_enabled?},
156 {time_running?},
157 {lost_records?},
158 {siblings},
159});
160
161#[derive(Clone)]
163#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
164pub struct SiblingStat {
165 pub count: u64,
167
168 pub id: Option<u64>,
170
171 pub lost_records: Option<u64>,
178}
179
180debug!(SiblingStat {
181 {count},
182 {id?},
183 {lost_records?},
184});