File Index
Files and directories
Sign in
FILE

free_timer.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/bpf/prog_tests/free_timer.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (C) 2025. Huawei Technologies Co., Ltd */
  3#define _GNU_SOURCE
  4#include <unistd.h>
  5#include <sys/syscall.h>
  6#include <test_progs.h>
  7
  8#include "free_timer.skel.h"
  9
 10struct run_ctx {
 11	struct bpf_program *start_prog;
 12	struct bpf_program *overwrite_prog;
 13	pthread_barrier_t notify;
 14	int loop;
 15	bool start;
 16	bool stop;
 17};
 18
 19static void start_threads(struct run_ctx *ctx)
 20{
 21	ctx->start = true;
 22}
 23
 24static void stop_threads(struct run_ctx *ctx)
 25{
 26	ctx->stop = true;
 27	/* Guarantee the order between ->stop and ->start */
 28	__atomic_store_n(&ctx->start, true, __ATOMIC_RELEASE);
 29}
 30
 31static int wait_for_start(struct run_ctx *ctx)
 32{
 33	while (!__atomic_load_n(&ctx->start, __ATOMIC_ACQUIRE))
 34		usleep(10);
 35
 36	return ctx->stop;
 37}
 38
 39static void *overwrite_timer_fn(void *arg)
 40{
 41	struct run_ctx *ctx = arg;
 42	int loop, fd, err;
 43	cpu_set_t cpuset;
 44	long ret = 0;
 45
 46	/* Pin on CPU 0 */
 47	CPU_ZERO(&cpuset);
 48	CPU_SET(0, &cpuset);
 49	pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
 50
 51	/* Is the thread being stopped ? */
 52	err = wait_for_start(ctx);
 53	if (err)
 54		return NULL;
 55
 56	fd = bpf_program__fd(ctx->overwrite_prog);
 57	loop = ctx->loop;
 58	while (loop-- > 0) {
 59		LIBBPF_OPTS(bpf_test_run_opts, opts);
 60
 61		/* Wait for start thread to complete */
 62		pthread_barrier_wait(&ctx->notify);
 63
 64		/* Overwrite timers */
 65		err = bpf_prog_test_run_opts(fd, &opts);
 66		if (err)
 67			ret |= 1;
 68		else if (opts.retval)
 69			ret |= 2;
 70
 71		/* Notify start thread to start timers */
 72		pthread_barrier_wait(&ctx->notify);
 73	}
 74
 75	return (void *)ret;
 76}
 77
 78static void *start_timer_fn(void *arg)
 79{
 80	struct run_ctx *ctx = arg;
 81	int loop, fd, err;
 82	cpu_set_t cpuset;
 83	long ret = 0;
 84
 85	/* Pin on CPU 1 */
 86	CPU_ZERO(&cpuset);
 87	CPU_SET(1, &cpuset);
 88	pthread_setaffinity_np(pthread_self(), sizeof(cpuset), &cpuset);
 89
 90	/* Is the thread being stopped ? */
 91	err = wait_for_start(ctx);
 92	if (err)
 93		return NULL;
 94
 95	fd = bpf_program__fd(ctx->start_prog);
 96	loop = ctx->loop;
 97	while (loop-- > 0) {
 98		LIBBPF_OPTS(bpf_test_run_opts, opts);
 99
100		/* Run the prog to start timer */
101		err = bpf_prog_test_run_opts(fd, &opts);
102		if (err)
103			ret |= 4;
104		else if (opts.retval)
105			ret |= 8;
106
107		/* Notify overwrite thread to do overwrite */
108		pthread_barrier_wait(&ctx->notify);
109
110		/* Wait for overwrite thread to complete */
111		pthread_barrier_wait(&ctx->notify);
112	}
113
114	return (void *)ret;
115}
116
117void test_free_timer(void)
118{
119	struct free_timer *skel;
120	struct bpf_program *prog;
121	struct run_ctx ctx;
122	pthread_t tid[2];
123	void *ret;
124	int err;
125
126	skel = free_timer__open_and_load();
127	if (!skel && errno == EOPNOTSUPP) {
128		test__skip();
129		return;
130	}
131	if (!ASSERT_OK_PTR(skel, "open_load"))
132		return;
133
134	memset(&ctx, 0, sizeof(ctx));
135
136	prog = bpf_object__find_program_by_name(skel->obj, "start_timer");
137	if (!ASSERT_OK_PTR(prog, "find start prog"))
138		goto out;
139	ctx.start_prog = prog;
140
141	prog = bpf_object__find_program_by_name(skel->obj, "overwrite_timer");
142	if (!ASSERT_OK_PTR(prog, "find overwrite prog"))
143		goto out;
144	ctx.overwrite_prog = prog;
145
146	pthread_barrier_init(&ctx.notify, NULL, 2);
147	ctx.loop = 10;
148
149	err = pthread_create(&tid[0], NULL, start_timer_fn, &ctx);
150	if (!ASSERT_OK(err, "create start_timer"))
151		goto out;
152
153	err = pthread_create(&tid[1], NULL, overwrite_timer_fn, &ctx);
154	if (!ASSERT_OK(err, "create overwrite_timer")) {
155		stop_threads(&ctx);
156		goto out;
157	}
158
159	start_threads(&ctx);
160
161	ret = NULL;
162	err = pthread_join(tid[0], &ret);
163	ASSERT_EQ(err | (long)ret, 0, "start_timer");
164	ret = NULL;
165	err = pthread_join(tid[1], &ret);
166	ASSERT_EQ(err | (long)ret, 0, "overwrite_timer");
167out:
168	free_timer__destroy(skel);
169}
~/ Read-only file preview.