perf_event/
flags.rs

1use bitflags::bitflags;
2
3use crate::sys::bindings;
4use crate::{Builder, ReadFormat, SampleFlag};
5
6used_in_docs!(Builder);
7used_in_docs!(SampleFlag);
8
9pub(crate) trait ReadFormatExt: Sized {
10    const MAX_NON_GROUP_SIZE: usize;
11    fn prefix_len(&self) -> usize;
12    fn element_len(&self) -> usize;
13}
14
15impl ReadFormatExt for ReadFormat {
16    const MAX_NON_GROUP_SIZE: usize = Self::all() //
17        .difference(Self::GROUP)
18        .bits()
19        .count_ones() as usize
20        + 1;
21
22    // The format of a read from a group is like this
23    // struct read_format {
24    //     u64 nr;            /* The number of events */
25    //     u64 time_enabled;  /* if PERF_FORMAT_TOTAL_TIME_ENABLED */
26    //     u64 time_running;  /* if PERF_FORMAT_TOTAL_TIME_RUNNING */
27    //     struct {
28    //         u64 value;     /* The value of the event */
29    //         u64 id;        /* if PERF_FORMAT_ID */
30    //         u64 lost;      /* if PERF_FORMAT_LOST */
31    //     } values[nr];
32    // };
33
34    /// The size of the common prefix when reading a group.
35    fn prefix_len(&self) -> usize {
36        1 + (*self & (Self::TOTAL_TIME_ENABLED | Self::TOTAL_TIME_RUNNING))
37            .bits()
38            .count_ones() as usize
39    }
40
41    /// The size of each element when reading a group
42    fn element_len(&self) -> usize {
43        1 + (*self & (Self::ID | Self::LOST)).bits().count_ones() as usize
44    }
45}
46
47/// Configuration of how much skid is allowed when gathering samples.
48///
49/// Skid is the number of instructions that occur between an event occuring and
50/// a sample being gathered by the kernel. Less skid is better but there are
51/// hardware limitations around how small the skid can be.
52///
53/// Also see [`Builder::precise_ip`].
54#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
55pub enum SampleSkid {
56    /// There may be an arbitrary number of instructions between the event and
57    /// the recorded instruction pointer.
58    Arbitrary = 0,
59
60    /// There may be a constant number of instructions between the event and
61    /// and the recorded instruction pointer.
62    Constant = 1,
63
64    /// We've requested that there be 0 skid. This does not guarantee that
65    /// samples will actually have 0 skid.
66    RequestZero = 2,
67
68    /// Skid must be 0. If skid is 0 then the generated sample records will
69    /// have the `PERF_RECORD_MISC_EXACT_IP` bit set.
70    RequireZero = 3,
71}
72
73/// Supported linux clocks that can be used within a perf_event instance.
74///
75/// See the [`clock_gettime(2)`][0] manpage for the full documentation on what
76/// each clock value actually means.
77///
78/// [0]: https://www.mankier.com/2/clock_gettime
79#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
80#[repr(transparent)]
81pub struct Clock(libc::clockid_t);
82
83impl Clock {
84    /// A clock following International Atomic Time.
85    pub const TAI: Self = Self::new(libc::CLOCK_TAI);
86
87    /// A clock that measures wall-clock time.
88    pub const REALTIME: Self = Self::new(libc::CLOCK_REALTIME);
89
90    /// A clock that is identical to `MONOTONIC` except it also includes any
91    /// time during which the systems was suspended.
92    pub const BOOTTIME: Self = Self::new(libc::CLOCK_BOOTTIME);
93
94    /// A clock that (roughly) corresponds to the time that the system has been
95    /// running since it was booted. (On Linux, at least).
96    pub const MONOTONIC: Self = Self::new(libc::CLOCK_MONOTONIC);
97
98    /// Similar to `MONOTONIC` but does not include NTP adjustments.
99    pub const MONOTONIC_RAW: Self = Self::new(libc::CLOCK_MONOTONIC_RAW);
100}
101
102impl Clock {
103    /// Construct a new `Clock` from the libc clockid value.
104    pub const fn new(clockid: libc::clockid_t) -> Self {
105        Self(clockid)
106    }
107
108    /// Extract the libc clockid value.
109    pub const fn into_raw(self) -> libc::clockid_t {
110        self.0
111    }
112}
113
114bitflags! {
115    /// Specify what branches to include in a branch record.
116    ///
117    /// This is used by the builder in combination with setting
118    /// [`SampleFlag::BRANCH_STACK`].
119    ///
120    /// The first part of the value is the privilege level, which is a
121    /// combination of `USER`, `BRANCH`, or `HV`. `PLM_ALL` is a convenience
122    /// value with all 3 ORed together. If none of the privilege levels are set
123    /// then the kernel will use the privilege level of the event.
124    ///
125    /// The second part specifies which branch types are to be included in the
126    /// branch stack. At least one of these bits must be set.
127    pub struct SampleBranchFlag: u64 {
128        /// The branch target is in user space.
129        const USER = bindings::PERF_SAMPLE_BRANCH_USER as _;
130
131        /// The branch target is in kernel space.
132        const KERNEL = bindings::PERF_SAMPLE_BRANCH_KERNEL as _;
133
134        /// The branch target is in the hypervisor.
135        const HV = bindings::PERF_SAMPLE_BRANCH_HV as _;
136
137        /// Include any branch type.
138        const ANY = bindings::PERF_SAMPLE_BRANCH_ANY as _;
139
140        /// Include any call branch.
141        ///
142        /// This includes direct calls, indirect calls, and far jumps.
143        const ANY_CALL = bindings::PERF_SAMPLE_BRANCH_ANY_CALL as _;
144
145        /// Include indirect calls.
146        const IND_CALL = bindings::PERF_SAMPLE_BRANCH_IND_CALL as _;
147
148        /// Include direct calls.
149        const CALL = bindings::PERF_SAMPLE_BRANCH_CALL as _;
150
151        /// Include any return branch.
152        const ANY_RETURN = bindings::PERF_SAMPLE_BRANCH_ANY_RETURN as _;
153
154        /// Include indirect jumps.
155        const IND_JUMP = bindings::PERF_SAMPLE_BRANCH_IND_JUMP as _;
156
157        /// Include conditional branches.
158        const COND = bindings::PERF_SAMPLE_BRANCH_COND as _;
159
160        /// Include transactional memory aborts.
161        const ABORT_TX = bindings::PERF_SAMPLE_BRANCH_ABORT_TX as _;
162
163        /// Include branches in a transactional memory transaction.
164        const IN_TX = bindings::PERF_SAMPLE_BRANCH_IN_TX as _;
165
166        /// Include branches not in a transactional memory transaction.
167        const NO_TX = bindings::PERF_SAMPLE_BRANCH_NO_TX as _;
168
169        /// Include branches that are part of a hardware-generated call stack.
170        ///
171        /// Note that this requires hardware support. See the [manpage][0] for
172        /// platforms which support this.
173        ///
174        /// [0]: https://www.mankier.com/2/perf_event_open
175        const CALL_STACK = bindings::PERF_SAMPLE_BRANCH_CALL_STACK as _;
176    }
177}
178
179impl SampleBranchFlag {
180    /// All privilege levels (`USER`, `KERNEL`, and `HV`) ORed together.
181    pub const PLM_ALL: Self = Self::USER.union(Self::KERNEL).union(Self::HV);
182}