summaryrefslogtreecommitdiff
path: root/tools/perf/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/tests')
-rw-r--r--tools/perf/tests/sigtrap.c46
1 files changed, 44 insertions, 2 deletions
diff --git a/tools/perf/tests/sigtrap.c b/tools/perf/tests/sigtrap.c
index a1bc7c776254..e6fd934b027a 100644
--- a/tools/perf/tests/sigtrap.c
+++ b/tools/perf/tests/sigtrap.c
@@ -103,6 +103,34 @@ static bool attr_has_sigtrap(void)
return __btf_type__find_member_by_name(id, "sigtrap") != NULL;
}
+
+static bool kernel_with_sleepable_spinlocks(void)
+{
+ const struct btf_member *member;
+ const struct btf_type *type;
+ const char *type_name;
+ int id;
+
+ if (!btf__available())
+ return false;
+
+ id = btf__find_by_name_kind(btf, "spinlock", BTF_KIND_STRUCT);
+ if (id < 0)
+ return false;
+
+ // Only RT has a "lock" member for "struct spinlock"
+ member = __btf_type__find_member_by_name(id, "lock");
+ if (member == NULL)
+ return false;
+
+ // But check its type as well
+ type = btf__type_by_id(btf, member->type);
+ if (!type || !btf_is_struct(type))
+ return false;
+
+ type_name = btf__name_by_offset(btf, type->name_off);
+ return type_name && !strcmp(type_name, "rt_mutex_base");
+}
#else /* !HAVE_BPF_SKEL */
static bool attr_has_sigtrap(void)
{
@@ -125,6 +153,11 @@ static bool attr_has_sigtrap(void)
return ret;
}
+static bool kernel_with_sleepable_spinlocks(void)
+{
+ return false;
+}
+
static void btf__exit(void)
{
}
@@ -166,7 +199,7 @@ static int run_test_threads(pthread_t *threads, pthread_barrier_t *barrier)
static int run_stress_test(int fd, pthread_t *threads, pthread_barrier_t *barrier)
{
- int ret;
+ int ret, expected_sigtraps;
ctx.iterate_on = 3000;
@@ -175,7 +208,16 @@ static int run_stress_test(int fd, pthread_t *threads, pthread_barrier_t *barrie
ret = run_test_threads(threads, barrier);
TEST_ASSERT_EQUAL("disable failed", ioctl(fd, PERF_EVENT_IOC_DISABLE, 0), 0);
- TEST_ASSERT_EQUAL("unexpected sigtraps", ctx.signal_count, NUM_THREADS * ctx.iterate_on);
+ expected_sigtraps = NUM_THREADS * ctx.iterate_on;
+
+ if (ctx.signal_count < expected_sigtraps && kernel_with_sleepable_spinlocks()) {
+ pr_debug("Expected %d sigtraps, got %d, running on a kernel with sleepable spinlocks.\n",
+ expected_sigtraps, ctx.signal_count);
+ pr_debug("See https://lore.kernel.org/all/e368f2c848d77fbc8d259f44e2055fe469c219cf.camel@gmx.de/\n");
+ return TEST_SKIP;
+ } else
+ TEST_ASSERT_EQUAL("unexpected sigtraps", ctx.signal_count, expected_sigtraps);
+
TEST_ASSERT_EQUAL("missing signals or incorrectly delivered", ctx.tids_want_signal, 0);
TEST_ASSERT_VAL("unexpected si_addr", ctx.first_siginfo.si_addr == &ctx.iterate_on);
#if 0 /* FIXME: enable when libc's signal.h has si_perf_{type,data} */