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*/