Skip to main content

perf_event/
builder.rs

1use std::ffi::c_int;
2use std::ffi::c_ulong;
3use std::fs::File;
4use std::os::fd::AsRawFd;
5use std::os::fd::FromRawFd;
6
7use libc::pid_t;
8use sys::bindings::perf_event_attr;
9
10use crate::check_errno_syscall;
11use crate::events;
12use crate::events::Event;
13use crate::flags::ReadFormat;
14use crate::sys;
15use crate::Clock;
16use crate::Counter;
17use crate::Group;
18use crate::SampleBranchFlag;
19use crate::SampleSkid;
20
21/// A builder for [`Counter`]s.
22///
23/// There are dozens of parameters that influence a `Counter`'s behavior.
24/// `Builder` lets you construct a `Counter` by specifying only those parameters
25/// for which you don't want the default value.
26///
27/// A freshly built `Counter` is disabled. To begin counting events, you must
28/// call [`enable`] on the `Counter` or the `Group` to which it belongs.
29///
30/// For example, if you want a `Counter` for instructions retired by the current
31/// process, those are `Builder`'s defaults, so you need only write:
32///
33///     # use perf_event::Builder;
34///     # fn main() -> std::io::Result<()> {
35///     let mut insns = Builder::new().build()?;
36///     # Ok(()) }
37///
38/// The [`kind`] method lets you specify what sort of event you want to
39/// count. So if you'd rather count branch instructions:
40///
41///     # use perf_event::Builder;
42///     # use perf_event::events::Hardware;
43///     # fn main() -> std::io::Result<()> {
44///     let mut insns = Builder::new()
45///         .kind(Hardware::BRANCH_INSTRUCTIONS)
46///         .build()?;
47///     # Ok(()) }
48///
49/// The [`group`] method lets you gather individual counters into `Group`
50/// that can be enabled or disabled atomically:
51///
52///     # use perf_event::{Builder, Group};
53///     # use perf_event::events::Hardware;
54///     # fn main() -> std::io::Result<()> {
55///     let mut group = Group::new()?;
56///     let cycles = Builder::new().group(&mut group).kind(Hardware::CPU_CYCLES).build()?;
57///     let insns = Builder::new().group(&mut group).kind(Hardware::INSTRUCTIONS).build()?;
58///     # Ok(()) }
59///
60/// Other methods let you select:
61///
62/// -   specific processes or cgroups to observe
63/// -   specific CPU cores to observe
64///
65/// `Builder` supports only a fraction of the many knobs and dials Linux offers,
66/// but hopefully it will acquire methods to support more of them as time goes
67/// on.
68///
69/// Internally, a `Builder` is just a wrapper around the kernel's `struct
70/// perf_event_attr` type.
71///
72/// [`enable`]: Counter::enable
73/// [`kind`]: Builder::kind
74/// [`group`]: Builder::group
75pub struct Builder<'a> {
76    attrs: perf_event_attr,
77    who: EventPid<'a>,
78    cpu: Option<usize>,
79    group: Option<&'a mut Group>,
80}
81
82impl<'a> Default for Builder<'a> {
83    fn default() -> Builder<'a> {
84        let mut attrs = perf_event_attr {
85            // Setting `size` accurately will not prevent the code from working
86            // on older kernels. The module comments for `perf_event_open_sys`
87            // explain why in far too much detail.
88            size: std::mem::size_of::<perf_event_attr>() as u32,
89            ..perf_event_attr::default()
90        };
91
92        attrs.set_disabled(1);
93        attrs.set_exclude_kernel(1); // don't count time in kernel
94        attrs.set_exclude_hv(1); // don't count time in hypervisor
95
96        // Request data for `time_enabled` and `time_running`.
97        attrs.read_format |= sys::bindings::PERF_FORMAT_TOTAL_TIME_ENABLED as u64
98            | sys::bindings::PERF_FORMAT_TOTAL_TIME_RUNNING as u64;
99
100        let kind = Event::Hardware(events::Hardware::INSTRUCTIONS);
101        kind.update_attrs(&mut attrs);
102
103        Builder {
104            attrs,
105            who: EventPid::ThisProcess,
106            cpu: None,
107            group: None,
108        }
109    }
110}
111
112// Methods that actually do work on the builder and aren't just setting
113// config values.
114impl<'a> Builder<'a> {
115    /// Return a new `Builder`, with all parameters set to their defaults.
116    pub fn new() -> Builder<'a> {
117        Builder::default()
118    }
119
120    /// Count events of the given kind. This accepts an [`Event`] value,
121    /// or any type that can be converted to one, so you can pass [`Hardware`],
122    /// [`Software`] and [`Cache`] values directly.
123    ///
124    /// The default is to count retired instructions, or
125    /// `Hardware::INSTRUCTIONS` events.
126    ///
127    /// For example, to count level 1 data cache references and misses, pass the
128    /// appropriate `events::Cache` values:
129    ///
130    ///     # fn main() -> std::io::Result<()> {
131    ///     use perf_event::{Builder, Group};
132    ///     use perf_event::events::{Cache, CacheOp, CacheResult, WhichCache};
133    ///
134    ///     const ACCESS: Cache = Cache {
135    ///         which: WhichCache::L1D,
136    ///         operation: CacheOp::READ,
137    ///         result: CacheResult::ACCESS,
138    ///     };
139    ///     const MISS: Cache = Cache { result: CacheResult::MISS, ..ACCESS };
140    ///
141    ///     let mut group = Group::new()?;
142    ///     let access_counter = Builder::new().group(&mut group).kind(ACCESS).build()?;
143    ///     let miss_counter = Builder::new().group(&mut group).kind(MISS).build()?;
144    ///     # Ok(()) }
145    ///
146    /// [`Hardware`]: events::Hardware
147    /// [`Software`]: events::Software
148    /// [`Cache`]: events::Cache
149    pub fn kind<K: Into<Event>>(mut self, kind: K) -> Builder<'a> {
150        let kind = kind.into();
151        kind.update_attrs(&mut self.attrs);
152        self
153    }
154
155    /// Construct a [`Counter`] according to the specifications made on this
156    /// `Builder`.
157    ///
158    /// A freshly built `Counter` is disabled. To begin counting events, you
159    /// must call [`enable`] on the `Counter` or the `Group` to which it belongs.
160    ///
161    /// If the `Builder` requests features that the running kernel does not
162    /// support, it returns `Err(e)` where `e.kind() == ErrorKind::Other` and
163    /// `e.raw_os_error() == Some(libc::E2BIG)`.
164    ///
165    /// Unfortunately, problems in counter configuration are detected at this
166    /// point, by the kernel, not earlier when the offending request is made on
167    /// the `Builder`. The kernel's returned errors are not always helpful.
168    ///
169    /// [`Counter`]: struct.Counter.html
170    /// [`enable`]: struct.Counter.html#method.enable
171    pub fn build(mut self) -> std::io::Result<Counter> {
172        let cpu = match self.cpu {
173            Some(cpu) => cpu as c_int,
174            None => -1,
175        };
176        let (pid, flags) = self.who.as_args();
177        let group_fd = match self.group {
178            Some(ref mut g) => {
179                g.max_members += 1;
180                g.file.as_raw_fd() as c_int
181            }
182            None => -1,
183        };
184
185        let file = unsafe {
186            File::from_raw_fd(check_errno_syscall(|| {
187                sys::perf_event_open(&mut self.attrs, pid, cpu, group_fd, flags as c_ulong)
188            })?)
189        };
190
191        // If we're going to be part of a Group, retrieve the ID the kernel
192        // assigned us, so we can find our results in a Counts structure. Even
193        // if we're not part of a group, we'll use it in `Debug` output.
194        let mut id = 0_u64;
195        check_errno_syscall(|| unsafe { sys::ioctls::ID(file.as_raw_fd(), &mut id) })?;
196
197        Ok(Counter::new(file, id))
198    }
199}
200
201impl<'a> Builder<'a> {
202    /// Directly access the [`perf_event_attr`] within this builder.
203    pub fn attrs(&self) -> &perf_event_attr {
204        &self.attrs
205    }
206
207    /// Directly access the [`perf_event_attr`] within this builder.
208    pub fn attrs_mut(&mut self) -> &mut perf_event_attr {
209        &mut self.attrs
210    }
211
212    /// Observe the calling process. (This is the default.)
213    pub fn observe_self(mut self) -> Builder<'a> {
214        self.who = EventPid::ThisProcess;
215        self
216    }
217
218    /// Observe the process with the given process id. This requires
219    /// [`CAP_SYS_PTRACE`][man-capabilities] capabilities.
220    ///
221    /// [man-capabilities]: http://man7.org/linux/man-pages/man7/capabilities.7.html
222    pub fn observe_pid(mut self, pid: pid_t) -> Builder<'a> {
223        self.who = EventPid::Other(pid);
224        self
225    }
226
227    /// Observe all processes.
228    ///
229    /// Linux does not support observing all processes on all CPUs without
230    /// restriction, so combining `any_pid` with [`any_cpu`] will cause the
231    /// final [`build`] to return an error. This must be used together with
232    /// [`one_cpu`], to select a specific CPU to observe.
233    ///
234    /// This requires [`CAP_PERFMON`][cap] or [`CAP_SYS_ADMIN`][cap]
235    /// capabilities, or a `/proc/sys/kernel/perf_event_paranoid` value of less
236    /// than 1.
237    ///
238    /// [`any_cpu`]: Builder::any_cpu
239    /// [`build`]: Builder::build
240    /// [`one_cpu`]: Builder::one_cpu
241    /// [cap]: http://man7.org/linux/man-pages/man7/capabilities.7.html
242    pub fn any_pid(mut self) -> Builder<'a> {
243        self.who = EventPid::Any;
244        self
245    }
246
247    /// Observe code running in the given [cgroup][man-cgroups] (container). The
248    /// `cgroup` argument should be a `File` referring to the cgroup's directory
249    /// in the cgroupfs filesystem.
250    ///
251    /// [man-cgroups]: http://man7.org/linux/man-pages/man7/cgroups.7.html
252    pub fn observe_cgroup(mut self, cgroup: &'a File) -> Builder<'a> {
253        self.who = EventPid::CGroup(cgroup);
254        self
255    }
256
257    /// Observe only code running on the given CPU core.
258    pub fn one_cpu(mut self, cpu: usize) -> Builder<'a> {
259        self.cpu = Some(cpu);
260        self
261    }
262
263    /// Observe code running on any CPU core. (This is the default.)
264    ///
265    /// Linux does not support observing all processes on all CPUs without
266    /// restriction, so combining `any_cpu` with [`any_pid`] will cause
267    /// [`build`] to return an error. This must be used with [`observe_self`]
268    /// (the default), [`observe_pid`], or [`observe_cgroup`].
269    ///
270    /// [`any_pid`]: Builder::any_pid
271    /// [`build`]: Builder::build
272    /// [`observe_self`]: Builder::observe_self
273    /// [`observe_pid`]: Builder::observe_pid
274    /// [`observe_cgroup`]: Builder::observe_cgroup
275    pub fn any_cpu(mut self) -> Builder<'a> {
276        self.cpu = None;
277        self
278    }
279
280    /// Place the counter in the given [`Group`]. Groups allow a set of counters
281    /// to be enabled, disabled, or read as a single atomic operation, so that
282    /// the counts can be usefully compared.
283    ///
284    /// [`Group`]: struct.Group.html
285    pub fn group(mut self, group: &'a mut Group) -> Builder<'a> {
286        self.group = Some(group);
287
288        // man page: "Members of a group are usually initialized with disabled
289        // set to zero."
290        self.attrs.set_disabled(0);
291
292        self
293    }
294
295    /// Set the fields to include when reading from the counter.
296    ///
297    /// Note that this method is _not_ additive, unlike [`sample`].
298    ///
299    /// The implementation of this library will silently mask out certain flags
300    /// if they would be invalid. For example, we will not allow you to set
301    /// [`ReadFormat::GROUP`] when building a single counter.
302    ///
303    /// [`sample`]: Builder::sample
304    pub fn read_format(&mut self, mut read_format: ReadFormat) -> &mut Self {
305        if read_format.contains(ReadFormat::GROUP) {
306            read_format |= ReadFormat::ID;
307        }
308
309        self.attrs.read_format = read_format.bits();
310        self
311    }
312}
313
314// Section for methods which directly modify attrs. These should correspond
315// roughly 1-to-1 with the entries as documented in the manpage.
316impl<'a> Builder<'a> {
317    /// Whether this counter should start off enabled.
318    ///
319    /// When this is set, the counter will immediately start being recorded as
320    /// soon as it is created.
321    ///
322    /// By default, this is false.
323    pub fn enabled(&mut self, enabled: bool) -> &mut Self {
324        self.attrs.set_disabled((!enabled).into());
325        self
326    }
327
328    /// Set whether this counter is inherited by new threads.
329    ///
330    /// When this flag is set, this counter observes activity in new threads
331    /// created by any thread already being observed.
332    ///
333    /// By default, the flag is unset: counters are not inherited, and observe
334    /// only the threads specified when they are created.
335    ///
336    /// This flag cannot be set if the counter belongs to a `Group`. Doing so
337    /// will result in an error when the counter is built. This is a kernel
338    /// limitation.
339    pub fn inherit(&mut self, inherit: bool) -> &mut Self {
340        self.attrs.set_inherit(inherit.into());
341        self
342    }
343
344    /// Set whether the counter is pinned to the PMU.
345    ///
346    /// If this flag is set, the kernel will attempt to keep the counter on
347    /// always on the CPU if at all possible. If it fails to do so, the counter
348    /// will enter an error state where reading it will always return EOF. For
349    /// this crate, that would result in [`Counter::read`] returning an error
350    /// with kind [`ErrorKind::UnexpectedEof`].
351    ///
352    /// This option only applies to hardware counters and group leaders. At
353    /// this time this crate provides no way to configure group leaders so this
354    /// option will only work when the resulting counter is not in a group.
355    ///
356    /// This is false by default.
357    ///
358    /// [`ErrorKind::UnexpectedEof`]: std::io::ErrorKind::UnexpectedEof
359    pub fn pinned(&mut self, pinned: bool) -> &mut Self {
360        self.attrs.set_pinned(pinned.into());
361        self
362    }
363
364    /// Controls whether the counter or group can be scheduled onto a CPU
365    /// alongside other counters or groups.
366    ///
367    /// This is false by default.
368    pub fn exclusive(&mut self, exclusive: bool) -> &mut Self {
369        self.attrs.set_exclusive(exclusive.into());
370        self
371    }
372
373    /// Whether we should exclude events that occur in user space.
374    ///
375    /// This is false by default.
376    pub fn exclude_user(&mut self, exclude_user: bool) -> &mut Self {
377        self.attrs.set_exclude_user(exclude_user.into());
378        self
379    }
380
381    /// Whether we should exclude events that occur in kernel space.
382    ///
383    /// Note that setting this to false may result in permission errors if
384    /// the current `perf_event_paranoid` value is greater than 1.
385    ///
386    /// This is true by default.
387    pub fn exclude_kernel(&mut self, exclude_kernel: bool) -> &mut Self {
388        self.attrs.set_exclude_kernel(exclude_kernel.into());
389        self
390    }
391
392    /// Include kernel code.
393    ///
394    /// See [`exclude_kernel`](Builder::exclude_kernel).
395    pub fn include_kernel(&mut self) -> &mut Self {
396        self.exclude_kernel(false)
397    }
398
399    /// Whether we should exclude events that happen in the hypervisor.
400    ///
401    /// This is not supported on all architectures as it required built-in
402    /// support within the CPU itself.
403    ///
404    /// Note that setting this to false may result in permission errors if
405    /// the current `perf_event_paranoid` value is greater than 1.
406    ///
407    /// This is true by default
408    pub fn exclude_hv(&mut self, exclude_hv: bool) -> &mut Self {
409        self.attrs.set_exclude_hv(exclude_hv.into());
410        self
411    }
412
413    /// Include hypervisor code.
414    ///
415    /// See [`exclude_hv`](Builder::exclude_hv).
416    pub fn include_hv(&mut self) -> &mut Self {
417        self.exclude_hv(false)
418    }
419
420    /// Whether to exclude events that occur when running the idle task.
421    ///
422    /// Note that this only has an effect for software events.
423    pub fn exclude_idle(&mut self, exclude_idle: bool) -> &mut Self {
424        self.attrs.set_exclude_idle(exclude_idle.into());
425        self
426    }
427
428    /// Enable the generation of MMAP records for executable memory maps.
429    ///
430    /// MMAP records are emitted when the process/thread that is being
431    /// observed creates a new executable memory mapping.
432    pub fn mmap(&mut self, mmap: bool) -> &mut Self {
433        self.attrs.set_mmap(mmap.into());
434        self
435    }
436
437    /// Enable the tracking of process command name changes.
438    ///
439    /// This can happen when a process calls `execve(2)`, `prctl(PR_SET_NAME)`,
440    /// or writes to `/proc/self/comm`.
441    ///
442    /// If you also set the [`comm_exec`](Builder::comm_exec) flag, then the
443    /// kernel will indicate which of these process name changes were due to
444    /// calls to `execve(2)`.
445    pub fn comm(&mut self, comm: bool) -> &mut Self {
446        self.attrs.set_comm(comm.into());
447        self
448    }
449
450    /// Set the period at which the kernel will generate sample events.
451    ///
452    /// As an example, if the event is `Hardware::INSTRUCTIONS` and `period`
453    /// is 100_000 then every 100_000 instructions the kernel will generate an
454    /// event.
455    ///
456    /// Note that the actual precision at which the sample corresponds to the
457    /// instant and location at which Nth event occurred is controlled by the
458    /// [`precise_ip`] option.
459    ///
460    /// This setting is mutually exclusive with [`sample_frequency`].
461    ///
462    /// [`precise_ip`]: Builder::precise_ip
463    /// [`sample_frequency`]: Builder::sample_frequency
464    pub fn sample_period(&mut self, period: u64) -> &mut Self {
465        self.attrs.set_freq(0);
466        self.attrs.sample_period = period;
467        self
468    }
469
470    /// Set the frequency at which the kernel will generate sample events
471    /// (in Hz).
472    ///
473    /// Note that this is not guaranteed to be exact. The kernel will adjust
474    /// the period to attempt to keep the desired frequency but the rate at
475    /// which events occur varies drastically then samples may not occur at
476    /// the specified frequency.
477    ///
478    /// The amount to which samples correspond to the instant and location at
479    /// which an event occurred is controlled by the [`precise_ip`] option.
480    ///
481    /// This setting is mutually exclusive with [`sample_period`].
482    ///
483    /// [`precise_ip`]: Builder::precise_ip
484    /// [`sample_period`]: Builder::sample_period
485    pub fn sample_frequency(&mut self, frequency: u64) -> &mut Self {
486        self.attrs.set_freq(1);
487        self.attrs.sample_freq = frequency;
488        self
489    }
490
491    /// Save event counts on context switch for inherited tasks.
492    ///
493    /// This option is only meaningful if [`inherit`] is also enabled.
494    ///
495    /// [`inherit`]: Builder::inherit
496    pub fn inherit_stat(&mut self, inherit_stat: bool) -> &mut Self {
497        self.attrs.set_inherit_stat(inherit_stat.into());
498        self
499    }
500
501    /// Enable the counter automatically after a call to `execve(2)`.
502    pub fn enable_on_exec(&mut self, enable_on_exec: bool) -> &mut Self {
503        self.attrs.set_enable_on_exec(enable_on_exec.into());
504        self
505    }
506
507    /// If set, then the kernel will generate fork and exit records.
508    pub fn task(&mut self, task: bool) -> &mut Self {
509        self.attrs.set_task(task.into());
510        self
511    }
512
513    /// Set how many bytes will be written before the kernel sends an overflow
514    /// notification.
515    ///
516    /// This controls how much data will be emitted before
517    /// [`Sampler::next_blocking`] will wake up once blocked.
518    ///
519    /// This setting is mutually exclusive with [`wakeup_events`].
520    ///
521    /// [`wakeup_events`]: Self::wakeup_events
522    /// [`Sampler::next_blocking`]: crate::Sampler::next_blocking
523    pub fn wakeup_watermark(&mut self, watermark: usize) -> &mut Self {
524        self.attrs.set_watermark(1);
525        self.attrs.wakeup_watermark = watermark as _;
526        self
527    }
528
529    /// Set how many samples will be written before the kernel sends an
530    /// overflow notification.
531    ///
532    /// This controls how much data will be emitted before
533    /// [`Sampler::next_blocking`] will wake up once blocked. Note that only
534    /// sample records (`PERF_RECORD_SAMPLE`) count towards the event count.
535    ///
536    /// Some caveats apply, see the [manpage] for the full documentation.
537    ///
538    /// This method is mutually exclusive with [`wakeup_watermark`].
539    ///
540    /// [manpage]: https://www.mankier.com/2/perf_event_open
541    /// [`wakeup_watermark`]: Builder::wakeup_watermark
542    /// [`Sampler::next_blocking`]: crate::Sampler::next_blocking
543    pub fn wakeup_events(&mut self, events: usize) -> &mut Self {
544        self.attrs.set_watermark(0);
545        self.attrs.wakeup_events = events as _;
546        self
547    }
548
549    /// Control how much skid is permitted when recording events.
550    ///
551    /// Skid is the number of instructions that occur between an event occuring
552    /// and a sample being gathered by the kernel. Less skid is better but
553    /// there are hardware limitations around how small the skid can be.
554    ///
555    /// Also see [`SampleSkid`].
556    pub fn precise_ip(&mut self, skid: SampleSkid) -> &mut Self {
557        self.attrs.set_precise_ip(skid as _);
558        self
559    }
560
561    /// Enable the generation of MMAP records for non-executable memory maps.
562    ///
563    /// This is the data counterpart of [`mmap`](Builder::mmap).
564    pub fn mmap_data(&mut self, mmap_data: bool) -> &mut Self {
565        self.attrs.set_mmap_data(mmap_data.into());
566        self
567    }
568
569    /// If enabled, then a subset of the sample fields will additionally be
570    /// included in most non-`PERF_RECORD_SAMPLE` samples.
571    ///
572    /// See the [manpage] for the exact fields that are included and which
573    /// records include the trailer.
574    ///
575    /// [manpage]: https://www.mankier.com/2/perf_event_open
576    pub fn sample_id_all(&mut self, sample_id_all: bool) -> &mut Self {
577        self.attrs.set_sample_id_all(sample_id_all.into());
578        self
579    }
580
581    /// Only collect measurements for events occurring inside a VM instance.
582    ///
583    /// This is only meaningful when profiling from outside the VM instance.
584    ///
585    /// See the [manpage] for more documentation.
586    ///
587    /// [manpage]: https://www.mankier.com/2/perf_event_open
588    pub fn exclude_host(&mut self, exclude_host: bool) -> &mut Self {
589        self.attrs.set_exclude_host(exclude_host.into());
590        self
591    }
592
593    /// Don't collect measurements for events occurring inside a VM instance.
594    ///
595    /// This is only meaningful when profiling from outside the VM instance.
596    ///
597    /// See the [manpage] for more documentation.
598    ///
599    /// [manpage]: https://www.mankier.com/2/perf_event_open
600    pub fn exclude_guest(&mut self, exclude_guest: bool) -> &mut Self {
601        self.attrs.set_exclude_guest(exclude_guest.into());
602        self
603    }
604
605    /// Do not include stack frames in the kernel when gathering callchains as
606    /// a part of recording a sample.
607    pub fn exclude_callchain_kernel(&mut self, exclude_kernel: bool) -> &mut Self {
608        self.attrs
609            .set_exclude_callchain_kernel(exclude_kernel.into());
610        self
611    }
612
613    /// Do not include stack frames from userspace when gathering a callchain
614    /// as a part of recording a sample.
615    pub fn exclude_callchain_user(&mut self, exclude_user: bool) -> &mut Self {
616        self.attrs.set_exclude_callchain_user(exclude_user.into());
617        self
618    }
619
620    /// Generate an extended executable mmap record.
621    ///
622    /// This record has enough info to uniquely identify which instance of a
623    /// shared map it corresponds to. Note that you also need to set the `mmap`
624    /// option for this to work.
625    pub fn mmap2(&mut self, mmap2: bool) -> &mut Self {
626        self.attrs.set_mmap2(mmap2.into());
627        self
628    }
629
630    /// Check whether the kernel will annotate COMM records with the COMM_EXEC
631    /// bit when they occur due to an `execve(2)` call.
632    ///
633    /// This option doesn't actually change the behaviour of the kernel.
634    /// Instead, it is useful for feature detection.
635    pub fn comm_exec(&mut self, comm_exec: bool) -> &mut Self {
636        self.attrs.set_comm_exec(comm_exec.into());
637        self
638    }
639
640    /// Select which linux clock to use for timestamps.
641    ///
642    /// If `clockid` is `None` then the kernel will use an internal timer. This
643    /// timer may not be any of the options for clockid.
644    ///
645    /// See [`Clock`] and the [`clock_getttime(2)`][0] manpage for
646    /// documentation on what the different clock values mean.
647    ///
648    /// [0]: https://www.mankier.com/2/clock_gettime
649    pub fn clockid(&mut self, clockid: impl Into<Option<Clock>>) -> &mut Self {
650        let clockid = clockid.into();
651        self.attrs.set_use_clockid(clockid.is_some().into());
652        self.attrs.clockid = clockid.map(Clock::into_raw).unwrap_or(0);
653        self
654    }
655
656    /// Generate `SWITCH` records when a context switch occurs.
657    ///
658    /// Also enables the generation of `SWITCH_CPU_WIDE` records if profiling
659    /// in cpu-wide mode.
660    pub fn context_switch(&mut self, context_switch: bool) -> &mut Self {
661        self.attrs.set_context_switch(context_switch.into());
662        self
663    }
664
665    /// Generate `NAMESPACES` records when a task enters a new namespace.
666    pub fn namespaces(&mut self, namespaces: bool) -> &mut Self {
667        self.attrs.set_namespaces(namespaces.into());
668        self
669    }
670
671    /// Generate `KSYMBOL` records when kernel symbols are registered or
672    /// unregistered.
673    pub fn ksymbol(&mut self, ksymbol: bool) -> &mut Self {
674        self.attrs.set_ksymbol(ksymbol.into());
675        self
676    }
677
678    /// Generate `BPF_EVENT` records when eBPF programs are loaded or unloaded.
679    pub fn bpf_event(&mut self, bpf_event: bool) -> &mut Self {
680        self.attrs.set_bpf_event(bpf_event.into());
681        self
682    }
683
684    /// Output data for non-aux events to the aux buffer, if supported by the
685    /// hardware.
686    pub fn aux_output(&mut self, aux_output: bool) -> &mut Self {
687        self.attrs.set_aux_output(aux_output.into());
688        self
689    }
690
691    /// Generate `CGROUP` records when a new cgroup is created.
692    pub fn cgroup(&mut self, cgroup: bool) -> &mut Self {
693        self.attrs.set_cgroup(cgroup.into());
694        self
695    }
696
697    /// Generate `TEXT_POKE` records when the kernel text (i.e. code) is
698    /// modified.
699    pub fn text_poke(&mut self, text_poke: bool) -> &mut Self {
700        self.attrs.set_text_poke(text_poke.into());
701        self
702    }
703
704    /// Whether to include the build id in `MMAP2` events.
705    pub fn build_id(&mut self, build_id: bool) -> &mut Self {
706        self.attrs.set_build_id(build_id.into());
707        self
708    }
709
710    /// Only inherit the counter to new threads in the same process, not to
711    /// other processes.
712    pub fn inherit_thread(&mut self, inherit_thread: bool) -> &mut Self {
713        self.attrs.set_inherit_thread(inherit_thread.into());
714        self
715    }
716
717    /// Disable this counter when it successfully calls `execve(2)`.
718    pub fn remove_on_exec(&mut self, remove_on_exec: bool) -> &mut Self {
719        self.attrs.set_remove_on_exec(remove_on_exec.into());
720        self
721    }
722
723    /// Synchronously send `SIGTRAP` to the process that created the counter
724    /// when the sampled events overflow.
725    pub fn sigtrap(&mut self, sigtrap: bool) -> &mut Self {
726        self.attrs.set_sigtrap(sigtrap.into());
727        self
728    }
729
730    /// Copy data to the user's signal handler (via `si_perf` in `siginfo_t`).
731    ///
732    /// This can be used to figure out which event caused the signal to be sent.
733    /// It does nothing unless [`sigtrap`](Self::sigtrap) is also set to `true`.
734    pub fn sig_data(&mut self, sig_data: u64) -> &mut Self {
735        self.attrs.sig_data = sig_data;
736        self
737    }
738
739    /// Specify which branches to include in the branch record.
740    ///
741    /// This does nothing unless [`SampleFlag::BRANCH_STACK`] is specified in
742    /// the sample flags.
743    pub fn branch_sample_type(&mut self, flags: SampleBranchFlag) -> &mut Self {
744        self.attrs.branch_sample_type = flags.bits();
745        self
746    }
747
748    /// Specify which CPU registers to dump in a sample.
749    ///
750    /// This does nothing unless [`SampleFlag::REGS_USER`] is part of the
751    /// specified [`sample`](Builder::sample) flags.
752    ///
753    /// The actual layout of the register mask is architecture specific.
754    /// You will generally want the `PERF_REG_<arch>` constants in
755    /// [`perf_event_open_sys`]. (e.g. `PERF_REG_X86_SP`).
756    pub fn sample_regs_user(&mut self, regs: u64) -> &mut Self {
757        self.attrs.sample_regs_user = regs;
758        self
759    }
760
761    /// Specify which CPU registers to dump in a sample.
762    ///
763    /// This does nothing unless [`SampleFlag::REGS_INTR`] is part of the
764    /// specified [`sample`](Builder::sample) flags.
765    ///
766    /// The actual layout of the register mask is architecture specific.
767    /// You will generally want the `PERF_REG_<arch>` constants in
768    /// [`perf_event_open_sys`]. (e.g. `PERF_REG_X86_SP`).
769    pub fn sample_regs_intr(&mut self, regs: u64) -> &mut Self {
770        self.attrs.sample_regs_user = regs;
771        self
772    }
773
774    /// Specify the maximum size of the user stack to dump.
775    ///
776    /// This option does nothing unless [`SampleFlag::STACK_USER`] is set in the
777    /// sample flags.
778    ///
779    /// Note that the size of the array allocated within the sample record will
780    /// always be exactly this size, even if the actual collected stack data is
781    /// much smaller. The allocated sample buffer (when constructing a
782    /// [`Sampler`]) will need to be large enough to accommodate the chosen
783    /// stack size or else samples will be lost.
784    ///
785    /// [`Sampler`]: crate::Sampler
786    pub fn sample_stack_user(&mut self, stack: u32) -> &mut Self {
787        self.attrs.sample_stack_user = stack;
788        self
789    }
790
791    /// Specify the maximum number of stack frames to include when unwinding the
792    /// user stack.
793    ///
794    /// This does nothing unless [`SampleFlag::CALLCHAIN`] is set in the sample
795    /// flags.
796    ///
797    /// Note that the kernel has a user configurable limit specified at
798    /// `/proc/sys/kernel/perf_event_max_stack`. Setting `sample_max_stack` to
799    /// larger than that limit will result in an `EOVERFLOW` error when building
800    /// the counter.
801    pub fn sample_max_stack(&mut self, max_stack: u16) -> &mut Self {
802        self.attrs.sample_max_stack = max_stack;
803        self
804    }
805
806    /// Specify how much data is required before the kernel emits an AUX record.
807    pub fn aux_watermark(&mut self, watermark: u32) -> &mut Self {
808        self.attrs.aux_watermark = watermark;
809        self
810    }
811
812    /// Specify the desired size of AUX data.
813    ///
814    /// This does nothing unless [`SampleFlag::AUX`] is set in the sample flags.
815    /// Note that the emitted aux data can be smaller than the requested size.
816    pub fn aux_sample_size(&mut self, sample_size: u32) -> &mut Self {
817        self.attrs.aux_sample_size = sample_size;
818        self
819    }
820}
821
822#[derive(Debug)]
823enum EventPid<'a> {
824    /// Monitor the calling process.
825    ThisProcess,
826
827    /// Monitor the given pid.
828    Other(pid_t),
829
830    /// Monitor members of the given cgroup.
831    CGroup(&'a File),
832
833    /// Monitor any process on some given CPU.
834    Any,
835}
836
837impl<'a> EventPid<'a> {
838    // Return the `pid` arg and the `flags` bits representing `self`.
839    fn as_args(&self) -> (pid_t, u32) {
840        match self {
841            EventPid::Any => (-1, 0),
842            EventPid::ThisProcess => (0, 0),
843            EventPid::Other(pid) => (*pid, 0),
844            EventPid::CGroup(file) => (file.as_raw_fd(), sys::bindings::PERF_FLAG_PID_CGROUP),
845        }
846    }
847}