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}