I'm trying to add perf event into group of events with an existing leader using the following code snippet (as example):
struct perf_event_attr perf_event;
int cpu_fd = -1;
int process_fd = -1;
memset(&perf_event, 0, sizeof(perf_event));
perf_event.type = PERF_TYPE_HARDWARE;
perf_event.size = sizeof(perf_event);
perf_event.config = config; // config (PERF_COUNT_HW_CPU_CYCLES) is passed as a function's argument
perf_event.use_clockid = 1;
perf_event.clockid = CLOCK_MONOTONIC;
perf_event.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | PERF_FORMAT_GROUP;
// First step:
// Create leader of perf events group
// cpu_idx is passed as an function's argument
cpu_fd = perf_event_open(&perf_event, -1, cpu_idx, -1,
PERF_FLAG_FD_CLOEXEC);
if (cpu_fd < 0) {
printf("Unable to open new CPU PMU event.\n");
return STATUS_NOK;
}
memset(&perf_event, 0, sizeof(perf_event));
perf_event.type = PERF_TYPE_HARDWARE;
perf_event.size = sizeof(perf_event);
perf_event.config = config; // same as above (PERF_COUNT_HW_CPU_CYCLES)
perf_event.use_clockid = 1;
perf_event.clockid = CLOCK_MONOTONIC;
perf_event.read_format = PERF_FORMAT_TOTAL_TIME_ENABLED;
// Second step:
// Attempting to add new perf event for account current process CPU cycles
// in existing group
// cpu_idx is passed as an function's argument
process_fd = perf_event_open(&perf_event, getpid(), cpu_idx, cpu_fd,
PERF_FLAG_FD_CLOEXEC);
if (process_fd < 0) {
printf("Unable to open new process PMU event.\n");
return STATUS_NOK;
}
On first step leader perf event is created for accounting the total number of CPU cycles on required CPU with cpu_idx. On the second step there is an attempt to add new perf event to existing leader in order to account current process CPU cycles on required CPU with cpu_idx.
But for unknown reason creation of new process_fd perf descriptor always fails with errno EINVAL (Invalid argument). I tried to investigate root cause with syscall tracing in the kernel but it seems I completely stuck.
Could you please help to find out root cause of such issue? These are many possible reasons for EINVAL case returned from perf_event_open syscall, I appreciate any suggestions or ideas for debugging.
Thanks a lot for your help!