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}