Mykola Lysenko says: ==================== First patch reduces the sample_freq to 1000 to ensure test will work even when kernel.perf_event_max_sample_rate was reduced to 1000. Patches for send_signal and find_vma tune the test implementation to make sure needed thread is scheduled. Also, both tests will finish as soon as possible after the test condition is met. ====================
Unified · Split
| @@ -199,7 +199,7 @@ static void pe_subtest(struct test_bpf_cookie *skel) · 198 unmodified lines | ||
| 199 | 199 | attr.type = PERF_TYPE_SOFTWARE; |
| 200 | 200 | attr.config = PERF_COUNT_SW_CPU_CLOCK; |
| 201 | 201 | attr.freq = 1; |
| 202 | − attr.sample_freq = 4000; | |
| 202 | + attr.sample_freq = 1000; | |
| 203 | 203 | pfd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC); |
| 204 | 204 | if (!ASSERT_GE(pfd, 0, "perf_fd")) |
| 205 | 205 | goto cleanup; |
| @@ -7,12 +7,14 @@ · 6 unmodified lines | ||
| 7 | 7 | #include "find_vma_fail1.skel.h" |
| 8 | 8 | #include "find_vma_fail2.skel.h" |
| 9 | 9 | |
| 10 | −static void test_and_reset_skel(struct find_vma *skel, int expected_find_zero_ret) | |
| 10 | +static void test_and_reset_skel(struct find_vma *skel, int expected_find_zero_ret, bool need_test) | |
| 11 | 11 | { |
| 12 | − ASSERT_EQ(skel->bss->found_vm_exec, 1, "found_vm_exec"); | |
| 13 | − ASSERT_EQ(skel->data->find_addr_ret, 0, "find_addr_ret"); | |
| 14 | − ASSERT_EQ(skel->data->find_zero_ret, expected_find_zero_ret, "find_zero_ret"); | |
| 15 | − ASSERT_OK_PTR(strstr(skel->bss->d_iname, "test_progs"), "find_test_progs"); | |
| 12 | + if (need_test) { | |
| 13 | + ASSERT_EQ(skel->bss->found_vm_exec, 1, "found_vm_exec"); | |
| 14 | + ASSERT_EQ(skel->data->find_addr_ret, 0, "find_addr_ret"); | |
| 15 | + ASSERT_EQ(skel->data->find_zero_ret, expected_find_zero_ret, "find_zero_ret"); | |
| 16 | + ASSERT_OK_PTR(strstr(skel->bss->d_iname, "test_progs"), "find_test_progs"); | |
| 17 | + } | |
| 16 | 18 | |
| 17 | 19 | skel->bss->found_vm_exec = 0; |
| 18 | 20 | skel->data->find_addr_ret = -1; |
| @@ -30,17 +32,26 @@ static int open_pe(void) · 11 unmodified lines | ||
| 30 | 32 | attr.type = PERF_TYPE_HARDWARE; |
| 31 | 33 | attr.config = PERF_COUNT_HW_CPU_CYCLES; |
| 32 | 34 | attr.freq = 1; |
| 33 | − attr.sample_freq = 4000; | |
| 35 | + attr.sample_freq = 1000; | |
| 34 | 36 | pfd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, PERF_FLAG_FD_CLOEXEC); |
| 35 | 37 | |
| 36 | 38 | return pfd >= 0 ? pfd : -errno; |
| 37 | 39 | } |
| 38 | 40 | |
| 41 | +static bool find_vma_pe_condition(struct find_vma *skel) | |
| 42 | +{ | |
| 43 | + return skel->bss->found_vm_exec == 0 || | |
| 44 | + skel->data->find_addr_ret != 0 || | |
| 45 | + skel->data->find_zero_ret == -1 || | |
| 46 | + strcmp(skel->bss->d_iname, "test_progs") != 0; | |
| 47 | +} | |
| 48 | + | |
| 39 | 49 | static void test_find_vma_pe(struct find_vma *skel) |
| 40 | 50 | { |
| 41 | 51 | struct bpf_link *link = NULL; |
| 42 | 52 | volatile int j = 0; |
| 43 | 53 | int pfd, i; |
| 54 | + const int one_bn = 1000000000; | |
| 44 | 55 | |
| 45 | 56 | pfd = open_pe(); |
| 46 | 57 | if (pfd < 0) { |
| @@ -57,10 +68,10 @@ static void test_find_vma_pe(struct find_vma *skel) · 10 unmodified lines | ||
| 57 | 68 | if (!ASSERT_OK_PTR(link, "attach_perf_event")) |
| 58 | 69 | goto cleanup; |
| 59 | 70 | |
| 60 | − for (i = 0; i < 1000000; ++i) | |
| 71 | + for (i = 0; i < one_bn && find_vma_pe_condition(skel); ++i) | |
| 61 | 72 | ++j; |
| 62 | 73 | |
| 63 | − test_and_reset_skel(skel, -EBUSY /* in nmi, irq_work is busy */); | |
| 74 | + test_and_reset_skel(skel, -EBUSY /* in nmi, irq_work is busy */, i == one_bn); | |
| 64 | 75 | cleanup: |
| 65 | 76 | bpf_link__destroy(link); |
| 66 | 77 | close(pfd); |
| @@ -75,7 +86,7 @@ static void test_find_vma_kprobe(struct find_vma *skel) · 8 unmodified lines | ||
| 75 | 86 | return; |
| 76 | 87 | |
| 77 | 88 | getpgid(skel->bss->target_pid); |
| 78 | − test_and_reset_skel(skel, -ENOENT /* could not find vma for ptr 0 */); | |
| 89 | + test_and_reset_skel(skel, -ENOENT /* could not find vma for ptr 0 */, true); | |
| 79 | 90 | } |
| 80 | 91 | |
| 81 | 92 | static void test_illegal_write_vma(void) |
| @@ -108,7 +119,6 @@ void serial_test_find_vma(void) · 26 unmodified lines | ||
| 108 | 119 | skel->bss->addr = (__u64)(uintptr_t)test_find_vma_pe; |
| 109 | 120 | |
| 110 | 121 | test_find_vma_pe(skel); |
| 111 | − usleep(100000); /* allow the irq_work to finish */ | |
| 112 | 122 | test_find_vma_kprobe(skel); |
| 113 | 123 | |
| 114 | 124 | find_vma__destroy(skel); |
| @@ -110,7 +110,7 @@ static void test_perf_branches_hw(void) · 109 unmodified lines | ||
| 110 | 110 | attr.type = PERF_TYPE_HARDWARE; |
| 111 | 111 | attr.config = PERF_COUNT_HW_CPU_CYCLES; |
| 112 | 112 | attr.freq = 1; |
| 113 | − attr.sample_freq = 4000; | |
| 113 | + attr.sample_freq = 1000; | |
| 114 | 114 | attr.sample_type = PERF_SAMPLE_BRANCH_STACK; |
| 115 | 115 | attr.branch_sample_type = PERF_SAMPLE_BRANCH_USER | PERF_SAMPLE_BRANCH_ANY; |
| 116 | 116 | pfd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC); |
| @@ -151,7 +151,7 @@ static void test_perf_branches_no_hw(void) · 34 unmodified lines | ||
| 151 | 151 | attr.type = PERF_TYPE_SOFTWARE; |
| 152 | 152 | attr.config = PERF_COUNT_SW_CPU_CLOCK; |
| 153 | 153 | attr.freq = 1; |
| 154 | − attr.sample_freq = 4000; | |
| 154 | + attr.sample_freq = 1000; | |
| 155 | 155 | pfd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC); |
| 156 | 156 | if (CHECK(pfd < 0, "perf_event_open", "err %d\n", pfd)) |
| 157 | 157 | return; |
| @@ -39,7 +39,7 @@ void serial_test_perf_link(void) · 38 unmodified lines | ||
| 39 | 39 | attr.type = PERF_TYPE_SOFTWARE; |
| 40 | 40 | attr.config = PERF_COUNT_SW_CPU_CLOCK; |
| 41 | 41 | attr.freq = 1; |
| 42 | − attr.sample_freq = 4000; | |
| 42 | + attr.sample_freq = 1000; | |
| 43 | 43 | pfd = syscall(__NR_perf_event_open, &attr, -1, 0, -1, PERF_FLAG_FD_CLOEXEC); |
| 44 | 44 | if (!ASSERT_GE(pfd, 0, "perf_fd")) |
| 45 | 45 | goto cleanup; |
| @@ -4,11 +4,11 @@ · 3 unmodified lines | ||
| 4 | 4 | #include <sys/resource.h> |
| 5 | 5 | #include "test_send_signal_kern.skel.h" |
| 6 | 6 | |
| 7 | −int sigusr1_received = 0; | |
| 7 | +static int sigusr1_received; | |
| 8 | 8 | |
| 9 | 9 | static void sigusr1_handler(int signum) |
| 10 | 10 | { |
| 11 | − sigusr1_received++; | |
| 11 | + sigusr1_received = 1; | |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | 14 | static void test_send_signal_common(struct perf_event_attr *attr, |
| @@ -40,9 +40,10 @@ static void test_send_signal_common(struct perf_event_attr *attr, · 25 unmodified lines | ||
| 40 | 40 | |
| 41 | 41 | if (pid == 0) { |
| 42 | 42 | int old_prio; |
| 43 | + volatile int j = 0; | |
| 43 | 44 | |
| 44 | 45 | /* install signal handler and notify parent */ |
| 45 | − signal(SIGUSR1, sigusr1_handler); | |
| 46 | + ASSERT_NEQ(signal(SIGUSR1, sigusr1_handler), SIG_ERR, "signal"); | |
| 46 | 47 | |
| 47 | 48 | close(pipe_c2p[0]); /* close read */ |
| 48 | 49 | close(pipe_p2c[1]); /* close write */ |
| @@ -63,9 +64,11 @@ static void test_send_signal_common(struct perf_event_attr *attr, · 14 unmodified lines | ||
| 63 | 64 | ASSERT_EQ(read(pipe_p2c[0], buf, 1), 1, "pipe_read"); |
| 64 | 65 | |
| 65 | 66 | /* wait a little for signal handler */ |
| 66 | − sleep(1); | |
| 67 | + for (int i = 0; i < 100000000 && !sigusr1_received; i++) | |
| 68 | + j /= i + 1; | |
| 67 | 69 | |
| 68 | 70 | buf[0] = sigusr1_received ? '2' : '0'; |
| 71 | + ASSERT_EQ(sigusr1_received, 1, "sigusr1_received"); | |
| 69 | 72 | ASSERT_EQ(write(pipe_c2p[1], buf, 1), 1, "pipe_write"); |
| 70 | 73 | |
| 71 | 74 | /* wait for parent notification and exit */ |
| @@ -93,7 +96,7 @@ static void test_send_signal_common(struct perf_event_attr *attr, · 21 unmodified lines | ||
| 93 | 96 | goto destroy_skel; |
| 94 | 97 | } |
| 95 | 98 | } else { |
| 96 | − pmu_fd = syscall(__NR_perf_event_open, attr, pid, -1, | |
| 99 | + pmu_fd = syscall(__NR_perf_event_open, attr, pid, -1 /* cpu */, | |
| 97 | 100 | -1 /* group id */, 0 /* flags */); |
| 98 | 101 | if (!ASSERT_GE(pmu_fd, 0, "perf_event_open")) { |
| 99 | 102 | err = -1; |
| @@ -110,9 +113,9 @@ static void test_send_signal_common(struct perf_event_attr *attr, · 10 unmodified lines | ||
| 110 | 113 | ASSERT_EQ(read(pipe_c2p[0], buf, 1), 1, "pipe_read"); |
| 111 | 114 | |
| 112 | 115 | /* trigger the bpf send_signal */ |
| 113 | − skel->bss->pid = pid; | |
| 114 | − skel->bss->sig = SIGUSR1; | |
| 115 | 116 | skel->bss->signal_thread = signal_thread; |
| 117 | + skel->bss->sig = SIGUSR1; | |
| 118 | + skel->bss->pid = pid; | |
| 116 | 119 | |
| 117 | 120 | /* notify child that bpf program can send_signal now */ |
| 118 | 121 | ASSERT_EQ(write(pipe_p2c[1], buf, 1), 1, "pipe_write"); |
| @@ -10,7 +10,7 @@ static __always_inline int bpf_send_signal_test(void *ctx) · 9 unmodified lines | ||
| 10 | 10 | { |
| 11 | 11 | int ret; |
| 12 | 12 | |
| 13 | − if (status != 0 || sig == 0 || pid == 0) | |
| 13 | + if (status != 0 || pid == 0) | |
| 14 | 14 | return 0; |
| 15 | 15 | |
| 16 | 16 | if ((bpf_get_current_pid_tgid() >> 32) == pid) { |