perf_event_open/config/mod.rs
1use std::io::Result;
2
3use crate::ffi::bindings as b;
4
5pub(super) mod attr;
6pub mod sibling;
7mod target;
8
9pub use target::*;
10
11/// This macro will not be used under the `latest` feature, as all syscall
12/// features are supported.
13#[allow(unused_macros)]
14macro_rules! unsupported {
15 () => {
16 Err(std::io::ErrorKind::Unsupported)?
17 };
18 ($bool:expr) => {
19 if $bool {
20 Err(std::io::ErrorKind::Unsupported)?
21 }
22 };
23}
24#[allow(unused_imports)]
25pub(super) use unsupported;
26
27/// Event options.
28#[derive(Clone, Debug, Default)]
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30pub struct Opts {
31 /// Exclude events with privilege levels.
32 ///
33 /// For example, if we set [`Priv::user`] to `true` here,
34 /// events that happen in user space will not be counted.
35 pub exclude: Priv,
36
37 /// This group should be the only group on the CPU.
38 ///
39 /// This means that when this counter group is on a CPU,
40 /// it should be the only group using the CPU counters.
41 ///
42 /// This allows monitoring programs with PMU that need to run alone so that
43 /// they do not disrupt other hardware counters.
44 pub only_group: bool,
45
46 /// The counter should always be on the CPU if at all possible.
47 ///
48 /// If a pinned counter cannot be put onto the CPU (e.g., because there are not enough
49 /// hardware counters or because of a conflict with some other event), then the counter
50 /// goes into an "error" state, where [stat][crate::count::Counter::stat] return EOF.
51 pub pin_on_pmu: bool,
52
53 // `mmap` will fail if this option is used with all CPUs:
54 // https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L6575
55 /// Controls the inherit behavior.
56 ///
57 /// This is incompatible with monitoring all CPUs in sampling mode.
58 pub inherit: Option<Inherit>,
59
60 /// Counter behavior when calling [`execve`](https://man7.org/linux/man-pages/man2/execve.2.html).
61 pub on_execve: Option<OnExecve>,
62
63 /// Controls the format of [`Stat`][crate::count::Stat].
64 pub stat_format: StatFormat,
65
66 /// Enable counter immediately after the counter is created.
67 pub enable: bool,
68
69 /// Controls when to generate a [sample record][crate::sample::record::sample::Sample].
70 pub sample_on: SampleOn,
71
72 /// Controls the amount of sample skid.
73 pub sample_skid: SampleSkid,
74
75 /// Controls the format of [sample record][crate::sample::record::sample::Sample].
76 pub sample_format: SampleFormat,
77
78 /// Generate extra record types.
79 pub extra_record: ExtraRecord,
80
81 /// Contains [`RecordId`][crate::sample::record::RecordId] in all non-sample [record][crate::sample::record] types.
82 pub record_id_all: bool,
83
84 /// Controls the format of [`RecordId`][crate::sample::record::RecordId].
85 pub record_id_format: RecordIdFormat,
86
87 /// Wake up options for asynchronous iterators.
88 pub wake_up: WakeUp,
89
90 // Must be used together with `remove_on_exec`:
91 // https://github.com/torvalds/linux/blob/2408a807bfc3f738850ef5ad5e3fd59d66168996/kernel/events/core.c#L12582
92 /// Enables synchronous signal delivery of `SIGTRAP` to the target
93 /// process on event overflow.
94 ///
95 /// Must be used together with [`OnExecve::Remove`].
96 ///
97 /// # Examples
98 ///
99 /// ```rust
100 /// # #[cfg(not(feature = "linux-5.13"))]
101 /// # return;
102 /// #
103 /// use std::mem::{transmute, MaybeUninit};
104 /// use std::ptr::null_mut;
105 /// use std::sync::atomic::{AtomicBool, Ordering};
106 /// use std::sync::mpsc::channel;
107 /// use std::thread;
108 ///
109 /// use perf_event_open::config::{Cpu, OnExecve, Opts, Proc, SampleOn, SigData};
110 /// use perf_event_open::count::Counter;
111 /// use perf_event_open::event::sw::Software;
112 ///
113 /// const SIG_DATA: u64 = 123456; // Data sent on SIGTRAP.
114 ///
115 /// let (pid_tx, pid_rx) = channel();
116 /// let handle = thread::spawn(move || {
117 /// # // Fork to avoid signal handler conflicts.
118 /// unsafe {
119 /// let child = libc::fork();
120 /// if child > 0 {
121 /// pid_tx.send(child).unwrap();
122 /// let mut code = 0;
123 /// libc::waitpid(child, &mut code as _, 0);
124 /// assert_eq!(code, 0);
125 /// return;
126 /// }
127 /// }
128 ///
129 /// unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL) };
130 ///
131 /// let result = std::panic::catch_unwind(|| {
132 ///
133 /// static SPIN: AtomicBool = AtomicBool::new(true);
134 ///
135 /// fn handler(num: i32, info: *const libc::siginfo_t) {
136 /// assert_eq!(num, libc::SIGTRAP);
137 /// let sig_data = unsafe { transmute::<libc::siginfo_t, [u64; 16]>(*info) }[3];
138 /// assert_eq!(sig_data, SIG_DATA);
139 /// SPIN.store(false, Ordering::Relaxed);
140 /// }
141 ///
142 /// let act = libc::sigaction {
143 /// sa_sigaction: handler as _,
144 /// sa_mask: unsafe { MaybeUninit::zeroed().assume_init() },
145 /// sa_flags: libc::SA_SIGINFO,
146 /// sa_restorer: None,
147 /// };
148 /// unsafe { libc::sigaction(libc::SIGTRAP, &act as _, null_mut()) };
149 ///
150 /// while SPIN.load(Ordering::Relaxed) {
151 /// // Busy wait to ensure the task clock increments.
152 /// std::hint::spin_loop();
153 /// }
154 /// });
155 /// if result.is_err() {
156 /// unsafe { libc::abort() };
157 /// }
158 ///
159 /// unsafe { libc::exit(0) };
160 /// });
161 ///
162 /// let event = Software::TaskClock;
163 /// let target = (Proc(pid_rx.recv().unwrap() as _), Cpu::ALL);
164 ///
165 /// let mut opts = Opts::default();
166 /// opts.sample_on = SampleOn::Freq(1000);
167 /// opts.sigtrap_on_sample = Some(SigData(SIG_DATA)); // Send SIGTRAP to the target when sampling.
168 /// opts.on_execve = Some(OnExecve::Remove); // Must be used together with `sigtrap_on_sample`.
169 ///
170 /// let counter = Counter::new(event, target, opts).unwrap();
171 /// counter.sampler(5).unwrap();
172 /// counter.enable().unwrap();
173 ///
174 /// handle.join().unwrap();
175 /// ```
176 ///
177 /// NOTE: Child process monitoring itself seems buggy,
178 /// panic in the signal handler may get the child process stuck.
179 ///
180 /// Since `linux-5.13`: <https://github.com/torvalds/linux/commit/97ba62b278674293762c3d91f724f1bb922f04e0>
181 pub sigtrap_on_sample: Option<SigData>,
182
183 /// Selects which internal Linux timer to use for [timestamps][crate::sample::record::RecordId::time].
184 ///
185 /// This can make it easier to correlate perf sample times with timestamps generated by other tools.
186 ///
187 /// Since `linux-4.1`: <https://github.com/torvalds/linux/commit/34f439278cef7b1177f8ce24f9fc81dfc6221d3b>
188 pub timer: Option<Clock>,
189
190 /// Pauses the newly created [AUX tracer][crate::sample::auxiliary::AuxTracer].
191 ///
192 /// Since `linux-6.13`: <https://github.com/torvalds/linux/commit/18d92bb57c39504d9da11c6ef604f58eb1d5a117>
193 pub pause_aux: bool,
194}
195
196/// Privilege levels.
197#[derive(Clone, Debug, Default)]
198#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
199pub struct Priv {
200 /// User space.
201 pub user: bool,
202
203 /// Kernel space.
204 pub kernel: bool,
205
206 /// Hypervisor.
207 pub hv: bool,
208
209 /// Host mode.
210 pub host: bool,
211
212 /// Guest mode.
213 pub guest: bool,
214
215 /// Idle task.
216 pub idle: bool,
217}
218
219/// Controls the inherit behavior.
220#[derive(Clone, Debug)]
221#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
222pub enum Inherit {
223 /// New child tasks will inherit the counter.
224 ///
225 /// This indicates if the process we monitoring creates new tasks
226 /// (child process or thread), the counter will count events that
227 /// happens in these tasks.
228 ///
229 /// This applies only to new children, not to any existing children at the time
230 /// the counter is created (nor to any new children of existing children).
231 NewChild,
232
233 /// Same as [`NewChild`][Self::NewChild], but only new threads will inherit the counter.
234 ///
235 /// Since `linux-5.13`: <https://github.com/torvalds/linux/commit/2b26f0aa004995f49f7b6f4100dd0e4c39a9ed5f>
236 NewThread,
237}
238
239// https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L12535
240/// Counter behavior when calling [`execve`](https://man7.org/linux/man-pages/man2/execve.2.html).
241#[derive(Clone, Debug)]
242#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
243pub enum OnExecve {
244 /// Enable counter.
245 Enable,
246
247 /// Remove counter.
248 ///
249 /// Since `linux-5.13`: <https://github.com/torvalds/linux/commit/2e498d0a74e5b88a6689ae1b811f247f91ff188e>
250 Remove,
251}
252
253/// Controls the format of [`Stat`][crate::count::Stat].
254#[derive(Clone, Debug, Default)]
255#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
256pub struct StatFormat {
257 /// Contains the [event ID][crate::count::SiblingStat::id].
258 pub id: bool,
259
260 /// Contains the [enabled time][crate::count::Stat::time_enabled] of the counter.
261 pub time_enabled: bool,
262
263 /// Contains the [running time][crate::count::Stat::time_running] of the counter.
264 pub time_running: bool,
265
266 /// Contains the [number of lost records][crate::count::SiblingStat::lost_records].
267 ///
268 /// Since `linux-6.0`: <https://github.com/torvalds/linux/commit/119a784c81270eb88e573174ed2209225d646656>
269 pub lost_records: bool,
270
271 /// Contains [sibling event counts][crate::count::Stat::siblings].
272 pub siblings: bool,
273}
274
275impl StatFormat {
276 pub(crate) fn as_read_format(&self) -> Result<u64> {
277 let mut val = 0;
278 macro_rules! when {
279 ($field:ident, $flag:ident) => {
280 if self.$field {
281 val |= b::$flag;
282 }
283 };
284 }
285 when!(id, PERF_FORMAT_ID);
286 when!(time_enabled, PERF_FORMAT_TOTAL_TIME_ENABLED);
287 when!(time_running, PERF_FORMAT_TOTAL_TIME_RUNNING);
288 #[cfg(feature = "linux-6.0")]
289 when!(lost_records, PERF_FORMAT_LOST);
290 #[cfg(not(feature = "linux-6.0"))]
291 unsupported!(self.lost_records);
292 when!(siblings, PERF_FORMAT_GROUP);
293 Ok(val as _)
294 }
295}
296
297// Details about overflow:
298// https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L9958
299// https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L5944
300// https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L10036
301/// Controls when to generate a [sample record][crate::sample::record::sample::Sample].
302///
303/// Defaults to `Count(0)` (no sample mode in `perf record` command),
304/// set it to the desired rate to generate sample records.
305///
306/// The maximum sample rate is specified in `/proc/sys/kernel/perf_event_max_sample_rate`,
307/// [`Throttle`][crate::sample::record::throttle::Throttle] record will be generated if
308/// the limit has been reached.
309///
310/// Meanwhile, `/proc/sys/kernel/perf_cpu_time_max_percent` limits the CPU time allowed
311/// to handle sampling (0 means unlimited). Sampling also will be throttled if this limit
312/// has been reached.
313///
314/// # Event overflow
315///
316/// The kernel maintains an unsigned counter with an appropriate negative initial value,
317/// which will finally overflows since every event increase it by one. Then sampling will
318/// be triggered and that counter will be reset to prepare for the next overflow. This is
319/// what this option actually controls.
320///
321/// In addition to asynchronous iterators with [wake up][WakeUp] option, overflow can
322/// also be captured by enabling I/O signaling from the perf event fd, which indicates
323/// `POLL_IN` on each overflow.
324///
325/// Here is an example:
326///
327/// ```rust
328/// // Fork to avoid signal handler conflicts.
329/// # unsafe {
330/// # let child = libc::fork();
331/// # if child > 0 {
332/// # let mut code = 0;
333/// # libc::waitpid(child, &mut code as _, 0);
334/// # assert_eq!(code, 0);
335/// # return;
336/// # }
337/// # }
338/// #
339/// # unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGKILL) };
340/// #
341/// # let result = std::panic::catch_unwind(|| {
342/// use std::mem::MaybeUninit;
343/// use std::os::fd::AsRawFd;
344/// use std::ptr::null_mut;
345/// use std::sync::atomic::AtomicBool;
346/// use std::sync::atomic::Ordering;
347///
348/// use perf_event_open::config::{Cpu, Opts, Proc, SampleOn};
349/// use perf_event_open::count::Counter;
350/// use perf_event_open::event::sw::Software;
351///
352/// static IN: AtomicBool = AtomicBool::new(false);
353///
354/// let event = Software::TaskClock;
355/// let target = (Proc::CURRENT, Cpu::ALL);
356/// let mut opts = Opts::default();
357/// opts.sample_on = SampleOn::Count(1_000_000); // 1ms
358///
359/// let counter = Counter::new(event, target, opts).unwrap();
360///
361/// // Enable I/O signals from perf event fd to the current process.
362/// let fd = counter.file().as_raw_fd();
363/// unsafe {
364/// libc::fcntl(fd, libc::F_SETFL, libc::O_ASYNC);
365/// // The value of `F_SETSIG` is 10, and libc crate does not have
366/// // that binding (same as `POLL_IN` below).
367/// libc::fcntl(fd, 10, libc::SIGIO);
368/// libc::fcntl(fd, libc::F_SETOWN, libc::getpid());
369/// }
370///
371/// fn handler(num: i32, info: *const libc::siginfo_t) {
372/// assert_eq!(num, libc::SIGIO);
373/// let si_code = unsafe { *info }.si_code;
374/// assert_eq!(si_code, 1); // POLL_IN
375/// IN.store(true, Ordering::Relaxed);
376/// }
377/// let act = libc::sigaction {
378/// sa_sigaction: handler as _,
379/// sa_mask: unsafe { MaybeUninit::zeroed().assume_init() },
380/// sa_flags: libc::SA_SIGINFO,
381/// sa_restorer: None,
382/// };
383/// unsafe { libc::sigaction(libc::SIGIO, &act as _, null_mut()) };
384///
385/// let sampler = counter.sampler(5).unwrap();
386/// counter.enable().unwrap();
387///
388/// while !IN.load(Ordering::Relaxed) {
389/// std::hint::spin_loop();
390/// }
391///
392/// println!("{:-?}", sampler.iter().next());
393/// # });
394/// # if result.is_err() {
395/// # unsafe { libc::abort() };
396/// # }
397///
398/// # unsafe { libc::exit(0) };
399/// ```
400///
401/// For more information on I/O signals, see also
402/// [`Sampler::enable_counter_with`][crate::sample::Sampler::enable_counter_with].
403#[derive(Clone, Debug)]
404#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
405pub enum SampleOn {
406 /// Sample on frequency (Hz).
407 ///
408 /// The kernel will adjust the sampling period to try and achieve the desired rate.
409 ///
410 /// `Freq(0)` means no overflow, i.e., sample records will never be generated.
411 Freq(u64),
412
413 /// Sample on every N event counts.
414 ///
415 /// It is referred to sample period.
416 ///
417 /// `Count(0)` is the default value for `SampleOn`, it has the same meaning as `Freq(0)`.
418 Count(u64),
419}
420
421impl Default for SampleOn {
422 fn default() -> Self {
423 Self::Freq(0)
424 }
425}
426
427/// Controls the amount of sample skid.
428///
429/// Skid is how many instructions execute between an event of interest happening and
430/// the kernel being able to stop and record the event.
431///
432/// Smaller skid is better and allows more accurate reporting of which events correspond
433/// to which instructions, but hardware is often limited with how small this can be.
434///
435/// This affects the precision of [`code_addr`][crate::sample::record::sample::Sample::code_addr].
436#[derive(Clone, Debug)]
437#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
438pub enum SampleSkid {
439 /// Can have arbitrary skid.
440 Arbitrary,
441 /// Must have constant skid.
442 Const,
443 /// Requested to have 0 skid.
444 ReqZero,
445 /// Must have 0 skid.
446 Zero,
447}
448
449impl SampleSkid {
450 pub(crate) fn as_precise_ip(&self) -> u8 {
451 match self {
452 Self::Arbitrary => 0,
453 Self::Const => 1,
454 Self::ReqZero => 2,
455 Self::Zero => 3,
456 }
457 }
458}
459
460impl Default for SampleSkid {
461 fn default() -> Self {
462 Self::Arbitrary
463 }
464}
465
466/// Controls the format of [sample record][crate::sample::record::sample::Sample].
467#[derive(Clone, Debug, Default)]
468#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
469pub struct SampleFormat {
470 // PERF_SAMPLE_READ
471 /// Contains [counter statistics][crate::sample::record::sample::Sample::stat].
472 pub stat: bool,
473 // PERF_SAMPLE_PERIOD
474 /// Contains [sample period][crate::sample::record::sample::Sample::period].
475 pub period: bool,
476 // PERF_SAMPLE_CGROUP
477 /// Contains [cgroup info][crate::sample::record::sample::Sample::cgroup].
478 ///
479 /// Since `linux-5.7`: <https://github.com/torvalds/linux/commit/6546b19f95acc986807de981402bbac6b3a94b0f>
480 pub cgroup: bool,
481 // PERF_SAMPLE_CALLCHAIN
482 /// Contains [call chain][crate::sample::record::sample::Sample::call_chain].
483 pub call_chain: Option<CallChain>,
484 // PERF_SAMPLE_STACK_USER
485 /// Contains [user stack][crate::sample::record::sample::Sample::user_stack].
486 pub user_stack: Option<Size>,
487
488 // PERF_SAMPLE_ADDR
489 /// Contains [data address][crate::sample::record::sample::Sample::data_addr].
490 pub data_addr: bool,
491 // PERF_SAMPLE_PHYS_ADDR
492 /// Contains [physical data address][crate::sample::record::sample::Sample::data_phys_addr].
493 ///
494 /// Since `linux-4.14`: <https://github.com/torvalds/linux/commit/fc7ce9c74c3ad232b084d80148654f926d01ece7>
495 pub data_phys_addr: bool,
496 // PERF_SAMPLE_DATA_PAGE_SIZE
497 /// Contains [data page size][crate::sample::record::sample::Sample::data_page_size].
498 ///
499 /// Since `linux-5.11`: <https://github.com/torvalds/linux/commit/8d97e71811aaafe4abf611dc24822fd6e73df1a1>
500 pub data_page_size: bool,
501 // PERF_SAMPLE_DATA_SRC
502 /// Contains [data source][crate::sample::record::sample::Sample::data_source].
503 pub data_source: bool,
504
505 // PERF_SAMPLE_IP
506 /// Contains [code address][crate::sample::record::sample::Sample::code_addr].
507 pub code_addr: bool,
508 // PERF_SAMPLE_CODE_PAGE_SIZE
509 /// Contains [code page size][crate::sample::record::sample::Sample::code_page_size].
510 ///
511 /// Since `linux-5.11`: <https://github.com/torvalds/linux/commit/995f088efebe1eba0282a6ffa12411b37f8990c2>
512 pub code_page_size: bool,
513
514 // PERF_SAMPLE_REGS_USER
515 /// Contains [user level registers][crate::sample::record::sample::Sample::user_regs].
516 pub user_regs: Option<RegsMask>,
517 // PERF_SAMPLE_REGS_INTR
518 /// Contains [registers on interrupt][crate::sample::record::sample::Sample::intr_regs].
519 pub intr_regs: Option<RegsMask>,
520
521 // PERF_SAMPLE_RAW
522 /// Contains [raw data][crate::sample::record::sample::Sample::raw].
523 pub raw: bool,
524 // PERF_SAMPLE_BRANCH_STACK
525 /// Contains [LBR data][crate::sample::record::sample::Sample::lbr].
526 pub lbr: Option<Lbr>,
527 // PERF_SAMPLE_AUX
528 /// Contains [AUX area snapshot][crate::sample::record::sample::Sample::aux].
529 ///
530 /// Since `linux-5.5`: <https://github.com/torvalds/linux/commit/a4faf00d994c40e64f656805ac375c65e324eefb>
531 pub aux: Option<Size>,
532 // PERF_SAMPLE_TRANSACTION
533 /// Contains [the sources of any transactional memory aborts][crate::sample::record::sample::Sample::txn].
534 pub txn: bool,
535 // PERF_SAMPLE_WEIGHT / PERF_SAMPLE_WEIGHT_STRUCT
536 /// Contains [sample weight][crate::sample::record::sample::Sample::weight].
537 pub weight: Option<Repr>,
538}
539
540/// LBR options.
541#[derive(Clone, Debug, Default)]
542#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
543pub struct Lbr {
544 // Inherit exclude_{kernel, user, hv} from attr if not set:
545 // https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L12473
546 /// Specifies which branches of target privileges can be included in the branch record.
547 ///
548 /// If the user does not set privilege level explicitly,
549 /// the kernel will inherit event's privilege level
550 /// (e.g., compatible options from [`Opts::exclude`]).
551 pub target_priv: Option<TargetPriv>,
552
553 /// Specifies which branches of types can be included in the branch record.
554 pub branch_type: BranchType,
555
556 // PERF_SAMPLE_BRANCH_HW_INDEX
557 /// Save [hardware index][crate::sample::record::sample::Lbr::hw_index].
558 ///
559 /// Since `linux-5.7`: <https://github.com/torvalds/linux/commit/bbfd5e4fab63703375eafaf241a0c696024a59e1>
560 pub hw_index: bool,
561
562 /// Controls the format of [LBR entry][crate::sample::record::sample::Entry].
563 pub entry_format: EntryFormat,
564}
565
566/// Branch target privilege levels.
567#[derive(Clone, Debug)]
568#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
569pub struct TargetPriv {
570 // PERF_SAMPLE_BRANCH_USER
571 /// Branch target is in user space.
572 pub user: bool,
573
574 // PERF_SAMPLE_BRANCH_KERNEL
575 /// Branch target is in kernel space.
576 pub kernel: bool,
577
578 // PERF_SAMPLE_BRANCH_HV
579 /// Branch target is in hypervisor.
580 pub hv: bool,
581}
582
583impl TargetPriv {
584 pub(crate) fn as_branch_sample_type(&self) -> u64 {
585 let mut flags = 0;
586 if self.user {
587 flags |= b::PERF_SAMPLE_BRANCH_USER;
588 }
589 if self.kernel {
590 flags |= b::PERF_SAMPLE_BRANCH_KERNEL;
591 };
592 if self.hv {
593 flags |= b::PERF_SAMPLE_BRANCH_HV;
594 }
595 flags as _
596 }
597}
598
599/// Branch types.
600#[derive(Clone, Debug, Default)]
601#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
602pub struct BranchType {
603 // PERF_SAMPLE_BRANCH_ANY
604 /// Any branch type.
605 pub any: bool,
606 // PERF_SAMPLE_BRANCH_ANY_RETURN
607 /// Any return branch.
608 pub any_return: bool,
609 // PERF_SAMPLE_BRANCH_COND
610 /// Conditional branches.
611 pub cond: bool,
612 // PERF_SAMPLE_BRANCH_IND_JUMP
613 /// Indirect jumps.
614 ///
615 /// Since `linux-4.2`: <https://github.com/torvalds/linux/commit/c9fdfa14c3792c0160849c484e83aa57afd80ccc>
616 pub ind_jump: bool,
617 // PERF_SAMPLE_BRANCH_CALL_STACK
618 /// Branch is part of a hardware-generated call stack.
619 ///
620 /// Since `linux-4.1`: <https://github.com/torvalds/linux/commit/2c44b1936bb3b135a3fac8b3493394d42e51cf70>
621 pub call_stack: bool,
622
623 // PERF_SAMPLE_BRANCH_CALL
624 /// Direct calls.
625 ///
626 /// Since `linux-4.4`: <https://github.com/torvalds/linux/commit/c229bf9dc179d2023e185c0f705bdf68484c1e73>
627 pub call: bool,
628 // PERF_SAMPLE_BRANCH_IND_CALL
629 /// Indirect calls.
630 pub ind_call: bool,
631 // PERF_SAMPLE_BRANCH_ANY_CALL
632 /// Any call branch (includes direct calls, indirect calls, and far jumps).
633 pub any_call: bool,
634
635 // PERF_SAMPLE_BRANCH_IN_TX
636 /// Branch in transactional memory transaction.
637 pub in_tx: bool,
638 // PERF_SAMPLE_BRANCH_NO_TX
639 /// Branch not in transactional memory transaction.
640 pub no_tx: bool,
641 // PERF_SAMPLE_BRANCH_ABORT_TX
642 /// Transactional memory aborts.
643 pub abort_tx: bool,
644}
645
646/// Controls the format of [LBR entry][crate::sample::record::sample::Entry].
647#[derive(Clone, Debug, Default)]
648#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
649pub struct EntryFormat {
650 // PERF_SAMPLE_BRANCH_NO_FLAGS
651 /// Contains flags (e.g., [`mis`][crate::sample::record::sample::Entry::mis],
652 /// [`pred`][crate::sample::record::sample::Entry::pred],
653 /// [`in_tx`][crate::sample::record::sample::Entry::in_tx] and
654 /// [`abort`][crate::sample::record::sample::Entry::in_tx]).
655 ///
656 /// Must be enabled before `linux-4.5`:
657 /// <https://github.com/torvalds/linux/commit/b16a5b52eb90d92b597257778e51e1fdc6423e64>
658 pub flags: bool,
659 // PERF_SAMPLE_BRANCH_NO_CYCLES
660 /// Contains [cycles][crate::sample::record::sample::Entry::cycles].
661 ///
662 /// Must be enabled before `linux-4.5`:
663 /// <https://github.com/torvalds/linux/commit/b16a5b52eb90d92b597257778e51e1fdc6423e64>
664 pub cycles: bool,
665 // PERF_SAMPLE_BRANCH_COUNTERS
666 /// Contains [counter][crate::sample::record::sample::Entry::counter].
667 ///
668 /// Since `linux-6.8`: <https://github.com/torvalds/linux/commit/571d91dcadfa3cef499010b4eddb9b58b0da4d24>
669 pub counter: bool,
670
671 // PERF_SAMPLE_BRANCH_TYPE_SAVE
672 /// Contains [branch type][crate::sample::record::sample::Entry::branch_type].
673 ///
674 /// Disassemble the branch instruction and record the branch type.
675 ///
676 /// Since `linux-4.14`: <https://github.com/torvalds/linux/commit/eb0baf8a0d9259d168523b8e7c436b55ade7c546>
677 pub branch_type: bool,
678 // PERF_SAMPLE_BRANCH_PRIV_SAVE
679 /// Contains [branch privilege level][crate::sample::record::sample::Entry::branch_priv].
680 ///
681 /// Since `linux-6.1`: <https://github.com/torvalds/linux/commit/5402d25aa5710d240040f73fb13d7d5c303ef071>
682 pub branch_priv: bool,
683}
684
685/// Semantic wrapper for options that require a size (in bytes).
686#[derive(Clone, Debug)]
687#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
688pub struct Size(pub u32);
689
690/// Controls how weight values are represented.
691#[derive(Clone, Debug)]
692#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
693pub enum Repr {
694 // PERF_SAMPLE_WEIGHT
695 /// Represent weight value as [`Full`][crate::sample::record::sample::Weight::Full].
696 Full,
697
698 // PERF_SAMPLE_WEIGHT_STRUCT
699 /// Represent weight value as [`Vars`][crate::sample::record::sample::Weight::Vars].
700 ///
701 /// Since`linux-5.12`: <https://github.com/torvalds/linux/commit/2a6c6b7d7ad346f0679d0963cb19b3f0ea7ef32c>
702 Vars,
703}
704
705/// Call chain options.
706#[derive(Clone, Debug)]
707#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
708pub struct CallChain {
709 /// Exclude user call chains.
710 pub exclude_user: bool,
711
712 /// Exclude kernel call chains.
713 pub exclude_kernel: bool,
714
715 /// How many stack frames to report when generating the call chain.
716 ///
717 /// The maximum frames is specified in `/proc/sys/kernel/perf_event_max_stack`.
718 ///
719 /// Since `linux-4.8`: <https://github.com/torvalds/linux/commit/97c79a38cd454602645f0470ffb444b3b75ce574>
720 pub max_stack_frames: u16,
721}
722
723/// Register mask that defines the set of CPU registers to dump on samples.
724///
725/// The layout of the register mask is architecture-specific and is described
726/// in the kernel header file `arch/<arch>/include/uapi/asm/perf_regs.h`.
727#[derive(Clone, Debug)]
728#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
729pub struct RegsMask(pub u64);
730
731/// Generate extra record types.
732#[derive(Clone, Debug, Default)]
733#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
734pub struct ExtraRecord {
735 /// Generate [`Fork`][crate::sample::record::task::Fork]
736 /// and [`Exit`][crate::sample::record::task::Exit] records.
737 pub task: bool,
738
739 /// Generate [`Read`][crate::sample::record::read::Read] records.
740 ///
741 /// Only meaningful if [`inherit`][Opts::inherit] is enabled.
742 pub read: bool,
743
744 // This also enables `task`:
745 // https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L8389
746 /// Generate [`Comm`][crate::sample::record::comm::Comm] records.
747 ///
748 /// This also enables [`Self::task`].
749 pub comm: bool,
750
751 /// [`Mmap`][crate::sample::record::mmap::Mmap] record options.
752 pub mmap: Mmap,
753
754 /// Generate [`Cgroup`][crate::sample::record::cgroup::Cgroup] records.
755 ///
756 /// Since `linux-5.7`: <https://github.com/torvalds/linux/commit/96aaab686505c449e24d76e76507290dcc30e008>
757 pub cgroup: bool,
758
759 /// Generate [`Ksymbol`][crate::sample::record::ksymbol::Ksymbol] records.
760 ///
761 /// Since `linux-5.1`: <https://github.com/torvalds/linux/commit/76193a94522f1d4edf2447a536f3f796ce56343b>
762 pub ksymbol: bool,
763
764 /// Generate [`BpfEvent`][crate::sample::record::bpf::BpfEvent] records.
765 ///
766 /// Since `linux-5.1`: <https://github.com/torvalds/linux/commit/6ee52e2a3fe4ea35520720736e6791df1fb67106>
767 pub bpf_event: bool,
768
769 /// Generate [`TextPoke`][crate::sample::record::text_poke::TextPoke] records.
770 ///
771 /// Since `linux-5.9`: <https://github.com/torvalds/linux/commit/e17d43b93e544f5016c0251d2074c15568d5d963>
772 pub text_poke: bool,
773
774 /// Generate [`CtxSwitch`][crate::sample::record::ctx::CtxSwitch] records.
775 ///
776 /// Since `linux-4.3`: <https://github.com/torvalds/linux/commit/45ac1403f564f411c6a383a2448688ba8dd705a4>
777 pub ctx_switch: bool,
778
779 /// Generate [`Namespaces`][crate::sample::record::ns::Namespaces] records.
780 ///
781 /// Since `linux-4.12`: <https://github.com/torvalds/linux/commit/e422267322cd319e2695a535e47c5b1feeac45eb>
782 pub namespaces: bool,
783}
784
785/// Controls the format of [`RecordId`][crate::sample::record::RecordId].
786#[derive(Clone, Debug, Default)]
787#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
788pub struct RecordIdFormat {
789 // PERF_SAMPLE_ID
790 /// Contains [event ID][crate::sample::record::RecordId::id].
791 pub id: bool,
792
793 // PERF_SAMPLE_STREAM_ID
794 /// Contains [event stream ID][crate::sample::record::RecordId::stream_id].
795 pub stream_id: bool,
796
797 // PERF_SAMPLE_CPU
798 /// Contains [CPU number][crate::sample::record::RecordId::cpu].
799 pub cpu: bool,
800
801 // PERF_SAMPLE_TID
802 /// Contains [task info][crate::sample::record::RecordId::task].
803 pub task: bool,
804
805 // PERF_SAMPLE_TIME
806 /// Contains [timestamp][crate::sample::record::RecordId::time].
807 pub time: bool,
808}
809
810/// Wake up options for asynchronous iterators.
811#[derive(Clone, Debug, Default)]
812#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
813pub struct WakeUp {
814 /// When to wake up asynchronous iterators.
815 pub on: WakeUpOn,
816
817 /// Wake up asynchronous iterators on every N bytes available in the AUX area.
818 ///
819 /// `0` means never wake up.
820 ///
821 /// Since `linux-4.1`: <https://github.com/torvalds/linux/commit/1a5941312414c71dece6717da9a0fa1303127afa>
822 pub on_aux_bytes: u32,
823}
824
825/// When to wake up asynchronous iterators.
826///
827/// "wake up" means notifying the async runtime to schedule the
828/// asynchronous iterator's future to be pulled in the next round.
829///
830/// For performance reasons, we may not want to wake up asynchronous
831/// iterators as soon as data is available. With this option we can
832/// configure the number of bytes or samples that triggers the wake
833/// up.
834///
835/// If we specify the [`Proc`] instead of [`All`], asynchronous iterators
836/// will be woken up when the target process exits.
837///
838/// # Examples
839///
840/// ```rust
841/// # tokio_test::block_on(async {
842/// use perf_event_open::config::{Cpu, Opts, Proc, SampleOn, WakeUpOn};
843/// use perf_event_open::count::Counter;
844/// use perf_event_open::event::sw::Software;
845///
846/// let event = Software::TaskClock;
847/// let target = (Proc::ALL, Cpu(0));
848///
849/// let mut opts = Opts::default();
850/// opts.sample_on = SampleOn::Freq(1000);
851/// // Wake up asynchronous iterators on every sample.
852/// opts.wake_up.on = WakeUpOn::Samples(1);
853///
854/// let counter = Counter::new(event, target, opts).unwrap();
855/// let sampler = counter.sampler(5).unwrap();
856///
857/// counter.enable().unwrap();
858///
859/// let mut iter = sampler.iter().into_async().unwrap();
860/// println!("{:-?}", iter.next().await);
861/// # });
862/// ```
863#[derive(Clone, Debug)]
864#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
865pub enum WakeUpOn {
866 /// Wake up on every N bytes available.
867 ///
868 /// `Bytes(0)` means never wake up.
869 Bytes(u64),
870
871 /// Wake up on every N samples available.
872 ///
873 /// `Samples(0)` means never wake up.
874 Samples(u64),
875}
876
877impl Default for WakeUpOn {
878 fn default() -> Self {
879 Self::Samples(0)
880 }
881}
882
883/// Semantic wrapper for signal data to pass.
884///
885/// This data will be copied to user's signal handler (through `si_perf`
886/// in the `siginfo_t`) to disambiguate which event triggered the signal.
887///
888/// Since `linux-5.13`: <https://github.com/torvalds/linux/commit/97ba62b278674293762c3d91f724f1bb922f04e0>
889#[derive(Clone, Debug)]
890#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
891pub struct SigData(pub u64);
892
893/// Available internal Linux timers.
894#[derive(Clone, Debug)]
895#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
896pub enum Clock {
897 // CLOCK_TAI
898 /// A nonsettable system-wide clock derived from wall-clock time but ignoring leap seconds.
899 ///
900 /// This clock does not experience discontinuities and backwards jumps caused by
901 /// NTP inserting leap seconds as [`RealTime`][Self::RealTime] does.
902 ///
903 /// This is International Atomic Time (TAI).
904 Tai,
905
906 // CLOCK_REALTIME
907 /// A settable system-wide clock that measures real (i.e., wall-clock) time.
908 ///
909 /// This clock is affected by discontinuous jumps in the system time
910 /// (e.g., if the system administrator manually changes the clock),
911 /// and by the incremental adjustments performed by
912 /// [`adjtime`](https://www.man7.org/linux/man-pages/man3/adjtime.3.html) and NTP.
913 RealTime,
914
915 // CLOCK_BOOTTIME
916 /// Similar to [`Monotonic`][Self::Monotonic], but it also includes
917 /// any time that the system is suspended.
918 BootTime,
919
920 // CLOCK_MONOTONIC
921 /// A nonsettable system-wide clock that represents monotonic time since
922 /// the system booted.
923 ///
924 /// This clock is not affected by discontinuous jumps in the system time
925 /// (e.g., if the system administrator manually changes the clock), but
926 /// is affected by the incremental adjustments performed by
927 /// [`adjtime`](https://www.man7.org/linux/man-pages/man3/adjtime.3.html) and NTP.
928 ///
929 /// This time never go backwards, but successive calls may return identical
930 /// (not-increased) time values.
931 ///
932 /// This clock does not count time that the system is suspended.
933 Monotonic,
934
935 // CLOCK_MONOTONIC_RAW
936 /// Similar to [`Monotonic`][Self::Monotonic], but provides access to a
937 /// raw hardware-based time that is not subject to NTP adjustments or the
938 /// incremental adjustments performed by [`adjtime`](https://www.man7.org/linux/man-pages/man3/adjtime.3.html).
939 MonotonicRaw,
940}
941
942/// [`Mmap`][crate::sample::record::mmap::Mmap] record options.
943#[derive(Clone, Debug, Default)]
944#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
945pub struct Mmap {
946 // This also enables `task`:
947 // https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L8389
948 /// Generate [`Mmap`] record when mmap is executable (with `PROT_EXEC`).
949 ///
950 /// This also enables [`ExtraRecord::task`].
951 pub code: bool,
952
953 // This also enables `task`:
954 // https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L8389
955 /// Generate [`Mmap`] record when mmap is non-executable (without `PROT_EXEC`).
956 ///
957 /// This also enables [`ExtraRecord::task`].
958 pub data: bool,
959
960 // This also enables `task`:
961 // https://github.com/torvalds/linux/blob/v6.13/kernel/events/core.c#L8389
962 /// Enable [extension fields][crate::sample::record::mmap::Mmap::ext].
963 ///
964 /// This also enables [`Self::code`] and [`ExtraRecord::task`].
965 pub ext: Option<UseBuildId>,
966}
967
968/// Carry [`BuildId`][crate::sample::record::mmap::Info::BuildId] instead of
969/// [`Device`][crate::sample::record::mmap::Info::Device] in [`Mmap`][crate::sample::record::mmap::Mmap] records
970/// if possible.
971///
972/// The Build ID is carried if memory is mapped to an ELF file containing
973/// a Build ID. Otherwise, device info is used as a fallback.
974///
975/// Since `linux-5.12`: <https://github.com/torvalds/linux/commit/88a16a1309333e43d328621ece3e9fa37027e8eb>
976#[derive(Clone, Debug, Default)]
977#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
978pub struct UseBuildId(pub bool);
979
980/*
981EventConifg::ty u32 type_
982size_of::<Attr> u32 size
983EventConifg::config u64 config
984SampleOn u64 __bindgen_anon_1 sample method union
985{Sample, RecordId}Format u64 sample_type
986Opts::stat_format u64 read_format
987- ZST _bitfield_align_1
988(See below) u64 _bitfield_1 option bits
989WakeUpOn u32 __bindgen_anon_2 wakeup on union
990Breakpoint::ty u32 bp_type
991EventConifg::config1 u64 __bindgen_anon_3 config1 union
992EventConifg::config2 u64 __bindgen_anon_4 config2 union
993Lbr u64 branch_sample_type
994SampleFormat::user_regs u64 sample_regs_user
995SampleFormat::user_stack u32 sample_stack_user
996Clock i32 clockid
997SampleFormat::intr_regs u64 sample_regs_intr
998WakeUp::on_aux_bytes u32 aux_watermark
999SampleFormat::call_chain u16 sample_max_stack
1000- u16 __reserved_2
1001SampleFormat::aux u32 aux_sample_size
1002(See below) u32 __bindgen_anon_5 aux action bits
1003SigData u64 sig_data
1004EventConfig::config3 u64 config3
1005*/
1006
1007/*
1008Opts::auto_start 1 disabled off by default
1009Opts::inherit 1 inherit children inherit it
1010Opts::pin_on_pmu 1 pinned must always be on PMU
1011Opts::only_group 1 exclusive only group on PMU
1012Priv::user 1 exclude_user don't count user
1013Priv::kernel 1 exclude_kernel ditto kernel
1014Priv::hv 1 exclude_hv ditto hypervisor
1015Priv::idle 1 exclude_idle don't count when idle
1016ExtraRecord::mmap 1 mmap include mmap data
1017ExtraRecord::comm 1 comm include comm data
1018SampleOn::Freq 1 freq use freq, not period
1019ExtraRecord::read 1 inherit_stat per task counts
1020Opts::on_execve 1 enable_on_exec next exec enables
1021ExtraRecord::task 1 task trace fork/exit
1022WakeUpOn 1 watermark wakeup_watermark
1023IpSkid 2 precise_ip skid constraint
1024ExtraRecord::mmap 1 mmap_data non-exec mmap data
1025Opts::record_id_all 1 sample_id_all sample_type all events
1026Priv::host 1 exclude_host don't count in host
1027Priv::guest 1 exclude_guest don't count in guest
1028SampleFormat::call_chain 1 exclude_callchain_kernel exclude kernel callchains
1029SampleFormat::call_chain 1 exclude_callchain_user exclude user callchains
1030ExtraRecord::mmap 1 mmap2 include mmap with inode data
1031false 1 comm_exec flag comm events that are due to an exec
1032Opts::clock_time 1 use_clockid use @clockid for time fields
1033ExtraRecord::ctx_switch 1 context_switch context switch data
1034false 1 write_backward Write ring-buffer from end to beginning
1035ExtraRecord::namespaces 1 namespaces include namespaces data
1036ExtraRecord::ksymbol 1 ksymbol include ksymbol events
1037ExtraRecord::bpf_event 1 bpf_event include bpf events
1038sibling::Opts::aux_output 1 aux_output generate AUX records instead of events
1039ExtraRecord::cgroup 1 cgroup include cgroup events
1040ExtraRecord::text_poke 1 text_poke include text poke events
1041ExtraRecord::mmap 1 build_id use build id in mmap2 events
1042Inherit 1 inherit_thread children only inherit if cloned with CLONE_THREAD
1043Opts::on_execve 1 remove_on_exec event is removed from task on exec
1044Opts::sigtrap_on_sample 1 sigtrap send synchronous SIGTRAP on event
1045- 26 __reserved_1
1046*/
1047
1048/*
1049Opts::pause_aux 1 aux_start_paused start AUX area tracing paused
1050sibling::AuxTracer 1 aux_pause on overflow, pause AUX area tracing
1051sibling::AuxTracer 1 aux_resume on overflow, resume AUX area tracing
1052- 29 __reserved_3
1053*/