File Index
Files and directories
Sign in
FILE

arena_spin_lock.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/prog_tests/arena_spin_lock.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2025 Meta Platforms, Inc. and affiliates. */
  3#include <test_progs.h>
  4#include <network_helpers.h>
  5#include <sys/sysinfo.h>
  6
  7struct __qspinlock { int val; };
  8typedef struct __qspinlock arena_spinlock_t;
  9
 10struct arena_qnode {
 11	unsigned long next;
 12	int count;
 13	int locked;
 14};
 15
 16#include "arena_spin_lock.skel.h"
 17
 18static long cpu;
 19static int repeat;
 20
 21pthread_barrier_t barrier;
 22
 23static void *spin_lock_thread(void *arg)
 24{
 25	int err, prog_fd = *(u32 *)arg;
 26	LIBBPF_OPTS(bpf_test_run_opts, topts,
 27		.data_in = &pkt_v4,
 28		.data_size_in = sizeof(pkt_v4),
 29		.repeat = repeat,
 30	);
 31	cpu_set_t cpuset;
 32
 33	CPU_ZERO(&cpuset);
 34	CPU_SET(__sync_fetch_and_add(&cpu, 1), &cpuset);
 35	ASSERT_OK(pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset), "cpu affinity");
 36
 37	err = pthread_barrier_wait(&barrier);
 38	if (err != PTHREAD_BARRIER_SERIAL_THREAD && err != 0)
 39		ASSERT_FALSE(true, "pthread_barrier");
 40
 41	err = bpf_prog_test_run_opts(prog_fd, &topts);
 42	ASSERT_OK(err, "test_run err");
 43
 44	if (topts.retval == -EOPNOTSUPP)
 45		goto end;
 46
 47	ASSERT_EQ((int)topts.retval, 0, "test_run retval");
 48
 49end:
 50	pthread_exit(arg);
 51}
 52
 53static void test_arena_spin_lock_size(int size)
 54{
 55	LIBBPF_OPTS(bpf_test_run_opts, topts);
 56	struct arena_spin_lock *skel;
 57	pthread_t thread_id[16];
 58	int prog_fd, i, err;
 59	int nthreads;
 60	void *ret;
 61
 62	nthreads = MIN(get_nprocs(), ARRAY_SIZE(thread_id));
 63	if (nthreads < 2) {
 64		test__skip();
 65		return;
 66	}
 67
 68	skel = arena_spin_lock__open_and_load();
 69	if (!ASSERT_OK_PTR(skel, "arena_spin_lock__open_and_load"))
 70		return;
 71
 72	if (skel->data->test_skip == 2) {
 73		test__skip();
 74		goto end;
 75	}
 76	skel->bss->cs_count = size;
 77	skel->bss->limit = repeat * nthreads;
 78
 79	ASSERT_OK(pthread_barrier_init(&barrier, NULL, nthreads), "barrier init");
 80
 81	prog_fd = bpf_program__fd(skel->progs.prog);
 82	for (i = 0; i < nthreads; i++) {
 83		err = pthread_create(&thread_id[i], NULL, &spin_lock_thread, &prog_fd);
 84		if (!ASSERT_OK(err, "pthread_create"))
 85			goto end_barrier;
 86	}
 87
 88	for (i = 0; i < nthreads; i++) {
 89		if (!ASSERT_OK(pthread_join(thread_id[i], &ret), "pthread_join"))
 90			goto end_barrier;
 91		if (!ASSERT_EQ(ret, &prog_fd, "ret == prog_fd"))
 92			goto end_barrier;
 93	}
 94
 95	if (skel->data->test_skip == 3) {
 96		printf("%s:SKIP: CONFIG_NR_CPUS exceed the maximum supported by arena spinlock\n",
 97		       __func__);
 98		test__skip();
 99		goto end_barrier;
100	}
101
102	ASSERT_EQ(skel->bss->counter, repeat * nthreads, "check counter value");
103
104end_barrier:
105	pthread_barrier_destroy(&barrier);
106end:
107	arena_spin_lock__destroy(skel);
108	return;
109}
110
111void test_arena_spin_lock(void)
112{
113	repeat = 1000;
114	if (test__start_subtest("arena_spin_lock_1"))
115		test_arena_spin_lock_size(1);
116	cpu = 0;
117	if (test__start_subtest("arena_spin_lock_1000"))
118		test_arena_spin_lock_size(1000);
119	cpu = 0;
120	repeat = 100;
121	if (test__start_subtest("arena_spin_lock_50000"))
122		test_arena_spin_lock_size(50000);
123}
~/ Read-only file preview.