| // SPDX-License-Identifier: GPL-2.0 |
| /* Copyright (C) 2023. Huawei Technologies Co., Ltd */ |
| #define _GNU_SOURCE |
| #include <sched.h> |
| #include <pthread.h> |
| #include <stdbool.h> |
| #include <test_progs.h> |
| |
| #include "preempted_bpf_ma_op.skel.h" |
| |
| #define ALLOC_THREAD_NR 4 |
| #define ALLOC_LOOP_NR 512 |
| |
| struct alloc_ctx { |
| /* output */ |
| int run_err; |
| /* input */ |
| int fd; |
| bool *nomem_err; |
| }; |
| |
| static void *run_alloc_prog(void *data) |
| { |
| struct alloc_ctx *ctx = data; |
| cpu_set_t cpu_set; |
| int i; |
| |
| CPU_ZERO(&cpu_set); |
| CPU_SET(0, &cpu_set); |
| pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set); |
| |
| for (i = 0; i < ALLOC_LOOP_NR && !*ctx->nomem_err; i++) { |
| LIBBPF_OPTS(bpf_test_run_opts, topts); |
| int err; |
| |
| err = bpf_prog_test_run_opts(ctx->fd, &topts); |
| ctx->run_err |= err | topts.retval; |
| } |
| |
| return NULL; |
| } |
| |
| void test_preempted_bpf_ma_op(void) |
| { |
| struct alloc_ctx ctx[ALLOC_THREAD_NR]; |
| struct preempted_bpf_ma_op *skel; |
| pthread_t tid[ALLOC_THREAD_NR]; |
| int i, err; |
| |
| skel = preempted_bpf_ma_op__open_and_load(); |
| if (!ASSERT_OK_PTR(skel, "open_and_load")) |
| return; |
| |
| err = preempted_bpf_ma_op__attach(skel); |
| if (!ASSERT_OK(err, "attach")) |
| goto out; |
| |
| for (i = 0; i < ARRAY_SIZE(ctx); i++) { |
| struct bpf_program *prog; |
| char name[8]; |
| |
| snprintf(name, sizeof(name), "test%d", i); |
| prog = bpf_object__find_program_by_name(skel->obj, name); |
| if (!ASSERT_OK_PTR(prog, "no test prog")) |
| goto out; |
| |
| ctx[i].run_err = 0; |
| ctx[i].fd = bpf_program__fd(prog); |
| ctx[i].nomem_err = &skel->bss->nomem_err; |
| } |
| |
| memset(tid, 0, sizeof(tid)); |
| for (i = 0; i < ARRAY_SIZE(tid); i++) { |
| err = pthread_create(&tid[i], NULL, run_alloc_prog, &ctx[i]); |
| if (!ASSERT_OK(err, "pthread_create")) |
| break; |
| } |
| |
| for (i = 0; i < ARRAY_SIZE(tid); i++) { |
| if (!tid[i]) |
| break; |
| pthread_join(tid[i], NULL); |
| ASSERT_EQ(ctx[i].run_err, 0, "run prog err"); |
| } |
| |
| ASSERT_FALSE(skel->bss->nomem_err, "ENOMEM"); |
| out: |
| preempted_bpf_ma_op__destroy(skel); |
| } |