mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 11:03:43 +02:00
selftests/bpf: Add hit/attach/detach race optimized uprobe test
Adding test that makes sure parallel execution of the uprobe and attach/detach of optimized uprobe on it works properly. By default the test runs for 500ms, which is adjustable by using BPF_SELFTESTS_UPROBE_SYSCALL_RACE_MSEC env variable. Signed-off-by: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/r/20250720112133.244369-16-jolsa@kernel.org
This commit is contained in:
parent
d5c86c3370
commit
c8be59667c
|
|
@ -15,6 +15,7 @@
|
|||
#include <asm/prctl.h>
|
||||
#include "uprobe_syscall.skel.h"
|
||||
#include "uprobe_syscall_executed.skel.h"
|
||||
#include "bpf/libbpf_internal.h"
|
||||
|
||||
#define USDT_NOP .byte 0x0f, 0x1f, 0x44, 0x00, 0x00
|
||||
#include "usdt.h"
|
||||
|
|
@ -629,6 +630,111 @@ static void test_uretprobe_shadow_stack(void)
|
|||
ARCH_PRCTL(ARCH_SHSTK_DISABLE, ARCH_SHSTK_SHSTK);
|
||||
}
|
||||
|
||||
static volatile bool race_stop;
|
||||
|
||||
static USDT_DEFINE_SEMA(race);
|
||||
|
||||
static void *worker_trigger(void *arg)
|
||||
{
|
||||
unsigned long rounds = 0;
|
||||
|
||||
while (!race_stop) {
|
||||
uprobe_test();
|
||||
rounds++;
|
||||
}
|
||||
|
||||
printf("tid %d trigger rounds: %lu\n", gettid(), rounds);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *worker_attach(void *arg)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_uprobe_opts, opts);
|
||||
struct uprobe_syscall_executed *skel;
|
||||
unsigned long rounds = 0, offset;
|
||||
const char *sema[2] = {
|
||||
__stringify(USDT_SEMA(race)),
|
||||
NULL,
|
||||
};
|
||||
unsigned long *ref;
|
||||
int err;
|
||||
|
||||
offset = get_uprobe_offset(&uprobe_test);
|
||||
if (!ASSERT_GE(offset, 0, "get_uprobe_offset"))
|
||||
return NULL;
|
||||
|
||||
err = elf_resolve_syms_offsets("/proc/self/exe", 1, (const char **) &sema, &ref, STT_OBJECT);
|
||||
if (!ASSERT_OK(err, "elf_resolve_syms_offsets_sema"))
|
||||
return NULL;
|
||||
|
||||
opts.ref_ctr_offset = *ref;
|
||||
|
||||
skel = uprobe_syscall_executed__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "uprobe_syscall_executed__open_and_load"))
|
||||
return NULL;
|
||||
|
||||
skel->bss->pid = getpid();
|
||||
|
||||
while (!race_stop) {
|
||||
skel->links.test_uprobe = bpf_program__attach_uprobe_opts(skel->progs.test_uprobe,
|
||||
0, "/proc/self/exe", offset, &opts);
|
||||
if (!ASSERT_OK_PTR(skel->links.test_uprobe, "bpf_program__attach_uprobe_opts"))
|
||||
break;
|
||||
|
||||
bpf_link__destroy(skel->links.test_uprobe);
|
||||
skel->links.test_uprobe = NULL;
|
||||
rounds++;
|
||||
}
|
||||
|
||||
printf("tid %d attach rounds: %lu hits: %d\n", gettid(), rounds, skel->bss->executed);
|
||||
uprobe_syscall_executed__destroy(skel);
|
||||
free(ref);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static useconds_t race_msec(void)
|
||||
{
|
||||
char *env;
|
||||
|
||||
env = getenv("BPF_SELFTESTS_UPROBE_SYSCALL_RACE_MSEC");
|
||||
if (env)
|
||||
return atoi(env);
|
||||
|
||||
/* default duration is 500ms */
|
||||
return 500;
|
||||
}
|
||||
|
||||
static void test_uprobe_race(void)
|
||||
{
|
||||
int err, i, nr_threads;
|
||||
pthread_t *threads;
|
||||
|
||||
nr_threads = libbpf_num_possible_cpus();
|
||||
if (!ASSERT_GT(nr_threads, 0, "libbpf_num_possible_cpus"))
|
||||
return;
|
||||
nr_threads = max(2, nr_threads);
|
||||
|
||||
threads = alloca(sizeof(*threads) * nr_threads);
|
||||
if (!ASSERT_OK_PTR(threads, "malloc"))
|
||||
return;
|
||||
|
||||
for (i = 0; i < nr_threads; i++) {
|
||||
err = pthread_create(&threads[i], NULL, i % 2 ? worker_trigger : worker_attach,
|
||||
NULL);
|
||||
if (!ASSERT_OK(err, "pthread_create"))
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
usleep(race_msec() * 1000);
|
||||
|
||||
cleanup:
|
||||
race_stop = true;
|
||||
for (nr_threads = i, i = 0; i < nr_threads; i++)
|
||||
pthread_join(threads[i], NULL);
|
||||
|
||||
ASSERT_FALSE(USDT_SEMA_IS_ACTIVE(race), "race_semaphore");
|
||||
}
|
||||
|
||||
static void __test_uprobe_syscall(void)
|
||||
{
|
||||
if (test__start_subtest("uretprobe_regs_equal"))
|
||||
|
|
@ -647,6 +753,8 @@ static void __test_uprobe_syscall(void)
|
|||
test_uprobe_session();
|
||||
if (test__start_subtest("uprobe_usdt"))
|
||||
test_uprobe_usdt();
|
||||
if (test__start_subtest("uprobe_race"))
|
||||
test_uprobe_race();
|
||||
}
|
||||
#else
|
||||
static void __test_uprobe_syscall(void)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user