Skip to content

Commit 6ee3b62

Browse files
tzssangglassanakryiko
authored andcommitted
Avoid profiling offline or not present CPUs
Running example/c/profile on a virtual machine results in libbpf_num_possible_cpus calculating the wrong number of CPUs, causing the program to fail to set up performance monitor on a CPU/Core and throw an error. In contrast, the Rust implementation ignores this error and continues to execute. This fix only applies to the C implementation. Signed-off-by: ZhengSong Tu <[email protected]>
1 parent 6ed7a91 commit 6ee3b62

File tree

1 file changed

+30
-5
lines changed

1 file changed

+30
-5
lines changed

examples/c/profile.c

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <stdio.h>
44
#include <unistd.h>
55
#include <string.h>
6+
#include <fcntl.h>
67
#include <sys/syscall.h>
78
#include <sys/sysinfo.h>
89
#include <linux/perf_event.h>
@@ -13,6 +14,13 @@
1314
#include "profile.h"
1415
#include "blazesym.h"
1516

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+
1624
static long perf_event_open(struct perf_event_attr *hw_event, pid_t pid,
1725
int cpu, int group_fd, unsigned long flags)
1826
{
@@ -115,14 +123,16 @@ static void show_help(const char *progname)
115123

116124
int main(int argc, char * const argv[])
117125
{
126+
const char *online_cpus_file = "/sys/devices/system/cpu/online";
118127
int freq = 1, pid = -1, cpu;
119128
struct profile_bpf *skel = NULL;
120129
struct perf_event_attr attr;
121130
struct bpf_link **links = NULL;
122131
struct ring_buffer *ring_buf = NULL;
123-
int num_cpus;
132+
int num_cpus, num_online_cpus;
124133
int *pefds = NULL, pefd;
125134
int argp, i, err = 0;
135+
bool *online_mask = NULL;
126136

127137
while ((argp = getopt(argc, argv, "hf:")) != -1) {
128138
switch (argp) {
@@ -139,16 +149,24 @@ int main(int argc, char * const argv[])
139149
}
140150
}
141151

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+
142158
num_cpus = libbpf_num_possible_cpus();
143159
if (num_cpus <= 0) {
144160
fprintf(stderr, "Fail to get the number of processors\n");
145-
return 1;
161+
err = -1;
162+
goto cleanup;
146163
}
147164

148165
skel = profile_bpf__open_and_load();
149166
if (!skel) {
150167
fprintf(stderr, "Fail to open and load BPF skeleton\n");
151-
return 1;
168+
err = -1;
169+
goto cleanup;
152170
}
153171

154172
symbolizer = blazesym_new();
@@ -166,8 +184,9 @@ int main(int argc, char * const argv[])
166184
}
167185

168186
pefds = malloc(num_cpus * sizeof(int));
169-
for (i = 0; i < num_cpus; i++)
187+
for (i = 0; i < num_cpus; i++) {
170188
pefds[i] = -1;
189+
}
171190

172191
links = calloc(num_cpus, sizeof(struct bpf_link *));
173192

@@ -179,10 +198,15 @@ int main(int argc, char * const argv[])
179198
attr.freq = 1;
180199

181200
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+
182205
/* Set up performance monitoring on a CPU/Core */
183206
pefd = perf_event_open(&attr, pid, cpu, -1, PERF_FLAG_FD_CLOEXEC);
184207
if (pefd < 0) {
185208
fprintf(stderr, "Fail to set up performance monitor on a CPU/Core\n");
209+
err = -1;
186210
goto cleanup;
187211
}
188212
pefds[cpu] = pefd;
@@ -194,7 +218,7 @@ int main(int argc, char * const argv[])
194218
goto cleanup;
195219
}
196220
}
197-
221+
198222
/* Wait and receive stack traces */
199223
while (ring_buffer__poll(ring_buf, -1) >= 0) {
200224
}
@@ -215,5 +239,6 @@ int main(int argc, char * const argv[])
215239
ring_buffer__free(ring_buf);
216240
profile_bpf__destroy(skel);
217241
blazesym_free(symbolizer);
242+
free(online_mask);
218243
return -err;
219244
}

0 commit comments

Comments
 (0)