1
1
use std:: fs:: File ;
2
2
use std:: os:: raw:: { c_int, c_ulong} ;
3
- use std:: os:: unix:: io:: { AsRawFd , FromRawFd } ;
3
+ use std:: os:: unix:: io:: { AsRawFd , FromRawFd , RawFd } ;
4
4
5
5
use libc:: pid_t;
6
6
7
7
use crate :: events:: Event ;
8
8
use crate :: sys:: bindings:: perf_event_attr;
9
- use crate :: { check_errno_syscall, sys, Counter , Group , SampleFlag } ;
9
+ use crate :: { check_errno_syscall, sys, Counter , SampleFlag } ;
10
10
11
11
/// A builder for [`Counter`]s.
12
12
///
@@ -28,29 +28,17 @@ use crate::{check_errno_syscall, sys, Counter, Group, SampleFlag};
28
28
/// # std::io::Result::Ok(())
29
29
/// ```
30
30
///
31
- /// The [`kind`] method lets you specify what sort of event you want to
32
- /// count. So if you'd rather count branch instructions:
33
- ///
34
- /// ```
35
- /// # use perf_event::Builder;
36
- /// # use perf_event::events::Hardware;
37
- /// #
38
- /// let mut insns = Builder::new(Hardware::BRANCH_INSTRUCTIONS)
39
- /// .build()?;
40
- /// #
41
- /// # std::io::Result::Ok(())
42
- /// ```
43
- ///
44
- /// The [`group`] method lets you gather individual counters into `Group`
45
- /// that can be enabled or disabled atomically:
31
+ /// If you would like to gather individual counters into a [`Group`] you can
32
+ /// use the [`Group::add`] method. A [`Group`] allows you to enable or disable
33
+ /// all the grouped counters atomically.
46
34
///
47
35
/// ```
48
36
/// # use perf_event::{Builder, Group};
49
37
/// # use perf_event::events::Hardware;
50
38
/// #
51
39
/// let mut group = Group::new()?;
52
- /// let cycles = Builder::new(Hardware::CPU_CYCLES).group(&mut group).build( )?;
53
- /// let insns = Builder::new(Hardware::INSTRUCTIONS).group(&mut group).build( )?;
40
+ /// let cycles = group.add(& Builder::new(Hardware::CPU_CYCLES))?;
41
+ /// let insns = group.add(& Builder::new(Hardware::INSTRUCTIONS))?;
54
42
/// #
55
43
/// # std::io::Result::Ok(())
56
44
/// ```
@@ -68,13 +56,12 @@ use crate::{check_errno_syscall, sys, Counter, Group, SampleFlag};
68
56
/// perf_event_attr` type.
69
57
///
70
58
/// [`enable`]: Counter::enable
71
- /// [`kind `]: Builder::kind
72
- /// [`group `]: Builder::group
59
+ /// [`Group `]: crate::Group
60
+ /// [`Group::add `]: crate::Group::add
73
61
pub struct Builder < ' a > {
74
62
attrs : perf_event_attr ,
75
63
who : EventPid < ' a > ,
76
64
cpu : Option < usize > ,
77
- group : Option < & ' a mut Group > ,
78
65
}
79
66
80
67
#[ derive( Debug ) ]
@@ -108,7 +95,7 @@ impl<'a> Builder<'a> {
108
95
/// Return a new `Builder`, with all parameters set to their defaults.
109
96
///
110
97
/// Return a new `Builder` for the specified event.
111
- pub fn new ( event : impl Event ) -> Builder < ' a > {
98
+ pub fn new ( event : impl Event ) -> Self {
112
99
let mut attrs = perf_event_attr:: default ( ) ;
113
100
114
101
// Do the update_attrs bit before we set any of the default state so
@@ -128,24 +115,23 @@ impl<'a> Builder<'a> {
128
115
attrs,
129
116
who : EventPid :: ThisProcess ,
130
117
cpu : None ,
131
- group : None ,
132
118
}
133
119
}
134
120
135
121
/// Include kernel code.
136
- pub fn include_kernel ( mut self ) -> Builder < ' a > {
122
+ pub fn include_kernel ( mut self ) -> Self {
137
123
self . attrs . set_exclude_kernel ( 0 ) ;
138
124
self
139
125
}
140
126
141
127
/// Include hypervisor code.
142
- pub fn include_hv ( mut self ) -> Builder < ' a > {
128
+ pub fn include_hv ( mut self ) -> Self {
143
129
self . attrs . set_exclude_hv ( 0 ) ;
144
130
self
145
131
}
146
132
147
133
/// Observe the calling process. (This is the default.)
148
- pub fn observe_self ( mut self ) -> Builder < ' a > {
134
+ pub fn observe_self ( mut self ) -> Self {
149
135
self . who = EventPid :: ThisProcess ;
150
136
self
151
137
}
@@ -154,7 +140,7 @@ impl<'a> Builder<'a> {
154
140
/// [`CAP_SYS_PTRACE`][man-capabilities] capabilities.
155
141
///
156
142
/// [man-capabilities]: http://man7.org/linux/man-pages/man7/capabilities.7.html
157
- pub fn observe_pid ( mut self , pid : pid_t ) -> Builder < ' a > {
143
+ pub fn observe_pid ( mut self , pid : pid_t ) -> Self {
158
144
self . who = EventPid :: Other ( pid) ;
159
145
self
160
146
}
@@ -174,7 +160,7 @@ impl<'a> Builder<'a> {
174
160
/// [`build`]: Builder::build
175
161
/// [`one_cpu`]: Builder::one_cpu
176
162
/// [cap]: http://man7.org/linux/man-pages/man7/capabilities.7.html
177
- pub fn any_pid ( mut self ) -> Builder < ' a > {
163
+ pub fn any_pid ( mut self ) -> Self {
178
164
self . who = EventPid :: Any ;
179
165
self
180
166
}
@@ -184,13 +170,13 @@ impl<'a> Builder<'a> {
184
170
/// in the cgroupfs filesystem.
185
171
///
186
172
/// [man-cgroups]: http://man7.org/linux/man-pages/man7/cgroups.7.html
187
- pub fn observe_cgroup ( mut self , cgroup : & ' a File ) -> Builder < ' a > {
173
+ pub fn observe_cgroup ( mut self , cgroup : & ' a File ) -> Self {
188
174
self . who = EventPid :: CGroup ( cgroup) ;
189
175
self
190
176
}
191
177
192
178
/// Observe only code running on the given CPU core.
193
- pub fn one_cpu ( mut self , cpu : usize ) -> Builder < ' a > {
179
+ pub fn one_cpu ( mut self , cpu : usize ) -> Self {
194
180
self . cpu = Some ( cpu) ;
195
181
self
196
182
}
@@ -207,7 +193,7 @@ impl<'a> Builder<'a> {
207
193
/// [`observe_self`]: Builder::observe_self
208
194
/// [`observe_pid`]: Builder::observe_pid
209
195
/// [`observe_cgroup`]: Builder::observe_cgroup
210
- pub fn any_cpu ( mut self ) -> Builder < ' a > {
196
+ pub fn any_cpu ( mut self ) -> Self {
211
197
self . cpu = None ;
212
198
self
213
199
}
@@ -223,27 +209,12 @@ impl<'a> Builder<'a> {
223
209
/// This flag cannot be set if the counter belongs to a `Group`. Doing so
224
210
/// will result in an error when the counter is built. This is a kernel
225
211
/// limitation.
226
- pub fn inherit ( mut self , inherit : bool ) -> Builder < ' a > {
212
+ pub fn inherit ( mut self , inherit : bool ) -> Self {
227
213
let flag = if inherit { 1 } else { 0 } ;
228
214
self . attrs . set_inherit ( flag) ;
229
215
self
230
216
}
231
217
232
- /// Place the counter in the given [`Group`]. Groups allow a set of counters
233
- /// to be enabled, disabled, or read as a single atomic operation, so that
234
- /// the counts can be usefully compared.
235
- ///
236
- /// [`Group`]: struct.Group.html
237
- pub fn group ( mut self , group : & ' a mut Group ) -> Builder < ' a > {
238
- self . group = Some ( group) ;
239
-
240
- // man page: "Members of a group are usually initialized with disabled
241
- // set to zero."
242
- self . attrs . set_disabled ( 0 ) ;
243
-
244
- self
245
- }
246
-
247
218
/// Construct a [`Counter`] according to the specifications made on this
248
219
/// `Builder`.
249
220
///
@@ -260,23 +231,27 @@ impl<'a> Builder<'a> {
260
231
///
261
232
/// [`Counter`]: struct.Counter.html
262
233
/// [`enable`]: struct.Counter.html#method.enable
263
- pub fn build ( mut self ) -> std:: io:: Result < Counter > {
234
+ pub fn build ( & self ) -> std:: io:: Result < Counter > {
235
+ self . build_with_group ( None )
236
+ }
237
+
238
+ /// Alternative to `build` but with the group explicitly provided.
239
+ ///
240
+ /// Used within [`Group::add`].
241
+ pub ( crate ) fn build_with_group ( & self , group_fd : Option < RawFd > ) -> std:: io:: Result < Counter > {
264
242
let cpu = match self . cpu {
265
243
Some ( cpu) => cpu as c_int ,
266
244
None => -1 ,
267
245
} ;
246
+
268
247
let ( pid, flags) = self . who . as_args ( ) ;
269
- let group_fd = match self . group {
270
- Some ( ref mut g) => {
271
- g. max_members += 1 ;
272
- g. as_raw_fd ( )
273
- }
274
- None => -1 ,
275
- } ;
248
+ let group_fd = group_fd. unwrap_or ( -1 ) ;
249
+
250
+ let mut attrs = self . attrs ;
276
251
277
252
let file = unsafe {
278
253
File :: from_raw_fd ( check_errno_syscall ( || {
279
- sys:: perf_event_open ( & mut self . attrs , pid, cpu, group_fd, flags as c_ulong )
254
+ sys:: perf_event_open ( & mut attrs, pid, cpu, group_fd, flags as c_ulong )
280
255
} ) ?)
281
256
} ;
282
257
@@ -294,8 +269,8 @@ impl<'a> Builder<'a> {
294
269
/// Indicate additional values to include in the generated sample events.
295
270
///
296
271
/// Note that this method is additive and does not remove previously added
297
- /// sample types. See the documentation of [`Sample `] or the [manpage] for
298
- /// what's available to be collected.
272
+ /// sample types. See the documentation of [`SampleFlag `] or the [manpage]
273
+ /// for what's available to be collected.
299
274
///
300
275
/// # Example
301
276
/// Here we build a sampler that grabs the instruction pointer, process ID,
@@ -313,6 +288,7 @@ impl<'a> Builder<'a> {
313
288
/// # Ok::<_, std::io::Error>(())
314
289
/// ```
315
290
///
291
+ /// [`SampleFlag`]: crate::SampleFlag
316
292
/// [manpage]: http://man7.org/linux/man-pages/man2/perf_event_open.2.html
317
293
pub fn sample ( mut self , sample : SampleFlag ) -> Self {
318
294
self . attrs . sample_type |= sample. bits ( ) ;
0 commit comments