selftests/perf_events: Add a SIGTRAP stress test with disables
authorMarco Elver <elver@google.com>
Tue, 11 Oct 2022 12:45:35 +0000 (14:45 +0200)
committerPeter Zijlstra <peterz@infradead.org>
Mon, 17 Oct 2022 14:32:06 +0000 (16:32 +0200)
Add a SIGTRAP stress test that exercises repeatedly enabling/disabling
an event while it concurrently keeps firing.

Signed-off-by: Marco Elver <elver@google.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/all/Y0E3uG7jOywn7vy3@elver.google.com/
tools/testing/selftests/perf_events/sigtrap_threads.c

index 6d849dc..d1d8483 100644 (file)
@@ -62,6 +62,8 @@ static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr,
                .remove_on_exec = 1, /* Required by sigtrap. */
                .sigtrap        = 1, /* Request synchronous SIGTRAP on event. */
                .sig_data       = TEST_SIG_DATA(addr, id),
+               .exclude_kernel = 1, /* To allow */
+               .exclude_hv     = 1, /* running as !root */
        };
        return attr;
 }
@@ -93,9 +95,13 @@ static void *test_thread(void *arg)
 
        __atomic_fetch_add(&ctx.tids_want_signal, tid, __ATOMIC_RELAXED);
        iter = ctx.iterate_on; /* read */
-       for (i = 0; i < iter - 1; i++) {
-               __atomic_fetch_add(&ctx.tids_want_signal, tid, __ATOMIC_RELAXED);
-               ctx.iterate_on = iter; /* idempotent write */
+       if (iter >= 0) {
+               for (i = 0; i < iter - 1; i++) {
+                       __atomic_fetch_add(&ctx.tids_want_signal, tid, __ATOMIC_RELAXED);
+                       ctx.iterate_on = iter; /* idempotent write */
+               }
+       } else {
+               while (ctx.iterate_on);
        }
 
        return NULL;
@@ -208,4 +214,27 @@ TEST_F(sigtrap_threads, signal_stress)
        EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
 }
 
+TEST_F(sigtrap_threads, signal_stress_with_disable)
+{
+       const int target_count = NUM_THREADS * 3000;
+       int i;
+
+       ctx.iterate_on = -1;
+
+       EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
+       pthread_barrier_wait(&self->barrier);
+       while (__atomic_load_n(&ctx.signal_count, __ATOMIC_RELAXED) < target_count) {
+               EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_DISABLE, 0), 0);
+               EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_ENABLE, 0), 0);
+       }
+       ctx.iterate_on = 0;
+       for (i = 0; i < NUM_THREADS; i++)
+               ASSERT_EQ(pthread_join(self->threads[i], NULL), 0);
+       EXPECT_EQ(ioctl(self->fd, PERF_EVENT_IOC_DISABLE, 0), 0);
+
+       EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
+       EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
+       EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on, 0));
+}
+
 TEST_HARNESS_MAIN