| // SPDX-License-Identifier: GPL-2.0 | |
| // Copyright (c) 2020 Facebook | |
| #define _GNU_SOURCE | |
| #include <pthread.h> | |
| #include <sched.h> | |
| #include <test_progs.h> | |
| #include "perf_event_stackmap.skel.h" | |
| #ifndef noinline | |
| #define noinline __attribute__((noinline)) | |
| #endif | |
| noinline int func_1(void) | |
| { | |
| static int val = 1; | |
| val += 1; | |
| usleep(100); | |
| return val; | |
| } | |
| noinline int func_2(void) | |
| { | |
| return func_1(); | |
| } | |
| noinline int func_3(void) | |
| { | |
| return func_2(); | |
| } | |
| noinline int func_4(void) | |
| { | |
| return func_3(); | |
| } | |
| noinline int func_5(void) | |
| { | |
| return func_4(); | |
| } | |
| noinline int func_6(void) | |
| { | |
| int i, val = 1; | |
| for (i = 0; i < 100; i++) | |
| val += func_5(); | |
| return val; | |
| } | |
| void test_perf_event_stackmap(void) | |
| { | |
| struct perf_event_attr attr = { | |
| /* .type = PERF_TYPE_SOFTWARE, */ | |
| .type = PERF_TYPE_HARDWARE, | |
| .config = PERF_COUNT_HW_CPU_CYCLES, | |
| .precise_ip = 2, | |
| .sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_BRANCH_STACK | | |
| PERF_SAMPLE_CALLCHAIN, | |
| .branch_sample_type = PERF_SAMPLE_BRANCH_USER | | |
| PERF_SAMPLE_BRANCH_NO_FLAGS | | |
| PERF_SAMPLE_BRANCH_NO_CYCLES | | |
| PERF_SAMPLE_BRANCH_CALL_STACK, | |
| .freq = 1, | |
| .sample_freq = read_perf_max_sample_freq(), | |
| .size = sizeof(struct perf_event_attr), | |
| }; | |
| struct perf_event_stackmap *skel; | |
| __u32 duration = 0; | |
| cpu_set_t cpu_set; | |
| int pmu_fd, err; | |
| skel = perf_event_stackmap__open(); | |
| if (CHECK(!skel, "skel_open", "skeleton open failed\n")) | |
| return; | |
| err = perf_event_stackmap__load(skel); | |
| if (CHECK(err, "skel_load", "skeleton load failed: %d\n", err)) | |
| goto cleanup; | |
| CPU_ZERO(&cpu_set); | |
| CPU_SET(0, &cpu_set); | |
| err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set); | |
| if (CHECK(err, "set_affinity", "err %d, errno %d\n", err, errno)) | |
| goto cleanup; | |
| pmu_fd = syscall(__NR_perf_event_open, &attr, -1 /* pid */, | |
| 0 /* cpu 0 */, -1 /* group id */, | |
| 0 /* flags */); | |
| if (pmu_fd < 0) { | |
| printf("%s:SKIP:cpu doesn't support the event\n", __func__); | |
| test__skip(); | |
| goto cleanup; | |
| } | |
| skel->links.oncpu = bpf_program__attach_perf_event(skel->progs.oncpu, | |
| pmu_fd); | |
| if (!ASSERT_OK_PTR(skel->links.oncpu, "attach_perf_event")) { | |
| close(pmu_fd); | |
| goto cleanup; | |
| } | |
| /* create kernel and user stack traces for testing */ | |
| func_6(); | |
| CHECK(skel->data->stackid_kernel != 2, "get_stackid_kernel", "failed\n"); | |
| CHECK(skel->data->stackid_user != 2, "get_stackid_user", "failed\n"); | |
| CHECK(skel->data->stack_kernel != 2, "get_stack_kernel", "failed\n"); | |
| CHECK(skel->data->stack_user != 2, "get_stack_user", "failed\n"); | |
| cleanup: | |
| perf_event_stackmap__destroy(skel); | |
| } |