3
3
#include <stdio.h>
4
4
#include <unistd.h>
5
5
#include <string.h>
6
+ #include <fcntl.h>
6
7
#include <sys/syscall.h>
7
8
#include <sys/sysinfo.h>
8
9
#include <linux/perf_event.h>
13
14
#include "profile.h"
14
15
#include "blazesym.h"
15
16
17
+ /*
18
+ * This function is from libbpf, but it is not a public API and can only be
19
+ * used for demonstration. We can use this here because we statically link
20
+ * against the libbpf built from submodule during build.
21
+ */
22
+ extern int parse_cpu_mask_file (const char * fcpu , bool * * mask , int * mask_sz );
23
+
16
24
static long perf_event_open (struct perf_event_attr * hw_event , pid_t pid ,
17
25
int cpu , int group_fd , unsigned long flags )
18
26
{
@@ -115,14 +123,16 @@ static void show_help(const char *progname)
115
123
116
124
int main (int argc , char * const argv [])
117
125
{
126
+ const char * online_cpus_file = "/sys/devices/system/cpu/online" ;
118
127
int freq = 1 , pid = -1 , cpu ;
119
128
struct profile_bpf * skel = NULL ;
120
129
struct perf_event_attr attr ;
121
130
struct bpf_link * * links = NULL ;
122
131
struct ring_buffer * ring_buf = NULL ;
123
- int num_cpus ;
132
+ int num_cpus , num_online_cpus ;
124
133
int * pefds = NULL , pefd ;
125
134
int argp , i , err = 0 ;
135
+ bool * online_mask = NULL ;
126
136
127
137
while ((argp = getopt (argc , argv , "hf:" )) != -1 ) {
128
138
switch (argp ) {
@@ -139,16 +149,24 @@ int main(int argc, char * const argv[])
139
149
}
140
150
}
141
151
152
+ err = parse_cpu_mask_file (online_cpus_file , & online_mask , & num_online_cpus );
153
+ if (err ) {
154
+ fprintf (stderr , "Fail to get online CPU numbers: %d\n" , err );
155
+ goto cleanup ;
156
+ }
157
+
142
158
num_cpus = libbpf_num_possible_cpus ();
143
159
if (num_cpus <= 0 ) {
144
160
fprintf (stderr , "Fail to get the number of processors\n" );
145
- return 1 ;
161
+ err = -1 ;
162
+ goto cleanup ;
146
163
}
147
164
148
165
skel = profile_bpf__open_and_load ();
149
166
if (!skel ) {
150
167
fprintf (stderr , "Fail to open and load BPF skeleton\n" );
151
- return 1 ;
168
+ err = -1 ;
169
+ goto cleanup ;
152
170
}
153
171
154
172
symbolizer = blazesym_new ();
@@ -166,8 +184,9 @@ int main(int argc, char * const argv[])
166
184
}
167
185
168
186
pefds = malloc (num_cpus * sizeof (int ));
169
- for (i = 0 ; i < num_cpus ; i ++ )
187
+ for (i = 0 ; i < num_cpus ; i ++ ) {
170
188
pefds [i ] = -1 ;
189
+ }
171
190
172
191
links = calloc (num_cpus , sizeof (struct bpf_link * ));
173
192
@@ -179,10 +198,15 @@ int main(int argc, char * const argv[])
179
198
attr .freq = 1 ;
180
199
181
200
for (cpu = 0 ; cpu < num_cpus ; cpu ++ ) {
201
+ /* skip offline/not present CPUs */
202
+ if (cpu >= num_online_cpus || !online_mask [cpu ])
203
+ continue ;
204
+
182
205
/* Set up performance monitoring on a CPU/Core */
183
206
pefd = perf_event_open (& attr , pid , cpu , -1 , PERF_FLAG_FD_CLOEXEC );
184
207
if (pefd < 0 ) {
185
208
fprintf (stderr , "Fail to set up performance monitor on a CPU/Core\n" );
209
+ err = -1 ;
186
210
goto cleanup ;
187
211
}
188
212
pefds [cpu ] = pefd ;
@@ -194,7 +218,7 @@ int main(int argc, char * const argv[])
194
218
goto cleanup ;
195
219
}
196
220
}
197
-
221
+
198
222
/* Wait and receive stack traces */
199
223
while (ring_buffer__poll (ring_buf , -1 ) >= 0 ) {
200
224
}
@@ -215,5 +239,6 @@ int main(int argc, char * const argv[])
215
239
ring_buffer__free (ring_buf );
216
240
profile_bpf__destroy (skel );
217
241
blazesym_free (symbolizer );
242
+ free (online_mask );
218
243
return - err ;
219
244
}
0 commit comments