Cannot add perf event into group with existing leader

Viewed 66

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!

0 Answers
Related