1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2021 Facebook */ 3 #define _GNU_SOURCE 4 #include <pthread.h> 5 #include <sched.h> 6 #include <test_progs.h> 7 #include "test_perf_link.skel.h" 8 9 static void burn_cpu(void) 10 { 11 volatile int j = 0; 12 cpu_set_t cpu_set; 13 int i, err; 14 15 /* generate some branches on cpu 0 */ 16 CPU_ZERO(&cpu_set); 17 CPU_SET(0, &cpu_set); 18 err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set); 19 ASSERT_OK(err, "set_thread_affinity"); 20 21 /* spin the loop for a while (random high number) */ 22 for (i = 0; i < 1000000; ++i) 23 ++j; 24 } 25 26 /* TODO: often fails in concurrent mode */ 27 void serial_test_perf_link(void) 28 { 29 struct test_perf_link *skel = NULL; 30 struct perf_event_attr attr; 31 int pfd = -1, link_fd = -1, err; 32 int run_cnt_before, run_cnt_after; 33 struct bpf_link_info info; 34 __u32 info_len = sizeof(info); 35 36 /* create perf event */ 37 memset(&attr, 0, sizeof(attr)); 38 attr.size = sizeof(attr); 39 attr.type = PERF_TYPE_SOFTWARE; 40 attr.config = PERF_COUNT_SW_CPU_CLOCK; 41 attr.freq = 1; 42 attr.sample_freq = 4000; 43 pfd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC); 44 if (!ASSERT_GE(pfd, 0, "perf_fd")) 45 goto cleanup; 46 47 skel = test_perf_link__open_and_load(); 48 if (!ASSERT_OK_PTR(skel, "skel_load")) 49 goto cleanup; 50 51 link_fd = bpf_link_create(bpf_program__fd(skel->progs.handler), pfd, 52 BPF_PERF_EVENT, NULL); 53 if (!ASSERT_GE(link_fd, 0, "link_fd")) 54 goto cleanup; 55 56 memset(&info, 0, sizeof(info)); 57 err = bpf_obj_get_info_by_fd(link_fd, &info, &info_len); 58 if (!ASSERT_OK(err, "link_get_info")) 59 goto cleanup; 60 61 ASSERT_EQ(info.type, BPF_LINK_TYPE_PERF_EVENT, "link_type"); 62 ASSERT_GT(info.id, 0, "link_id"); 63 ASSERT_GT(info.prog_id, 0, "link_prog_id"); 64 65 /* ensure we get at least one perf_event prog execution */ 66 burn_cpu(); 67 ASSERT_GT(skel->bss->run_cnt, 0, "run_cnt"); 68 69 /* perf_event is still active, but we close link and BPF program 70 * shouldn't be executed anymore 71 */ 72 close(link_fd); 73 link_fd = -1; 74 75 /* make sure there are no stragglers */ 76 kern_sync_rcu(); 77 78 run_cnt_before = skel->bss->run_cnt; 79 burn_cpu(); 80 run_cnt_after = skel->bss->run_cnt; 81 82 ASSERT_EQ(run_cnt_before, run_cnt_after, "run_cnt_before_after"); 83 84 cleanup: 85 if (link_fd >= 0) 86 close(link_fd); 87 if (pfd >= 0) 88 close(pfd); 89 test_perf_link__destroy(skel); 90 } 91