1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2023. Huawei Technologies Co., Ltd */
3 #define _GNU_SOURCE
4 #include <sched.h>
5 #include <stdbool.h>
6 #include <test_progs.h>
7 #include "htab_reuse.skel.h"
8 
9 struct htab_op_ctx {
10 	int fd;
11 	int loop;
12 	bool stop;
13 };
14 
15 struct htab_val {
16 	unsigned int lock;
17 	unsigned int data;
18 };
19 
20 static void *htab_lookup_fn(void *arg)
21 {
22 	struct htab_op_ctx *ctx = arg;
23 	int i = 0;
24 
25 	while (i++ < ctx->loop && !ctx->stop) {
26 		struct htab_val value;
27 		unsigned int key;
28 
29 		/* Use BPF_F_LOCK to use spin-lock in map value. */
30 		key = 7;
31 		bpf_map_lookup_elem_flags(ctx->fd, &key, &value, BPF_F_LOCK);
32 	}
33 
34 	return NULL;
35 }
36 
37 static void *htab_update_fn(void *arg)
38 {
39 	struct htab_op_ctx *ctx = arg;
40 	int i = 0;
41 
42 	while (i++ < ctx->loop && !ctx->stop) {
43 		struct htab_val value;
44 		unsigned int key;
45 
46 		key = 7;
47 		value.lock = 0;
48 		value.data = key;
49 		bpf_map_update_elem(ctx->fd, &key, &value, BPF_F_LOCK);
50 		bpf_map_delete_elem(ctx->fd, &key);
51 
52 		key = 24;
53 		value.lock = 0;
54 		value.data = key;
55 		bpf_map_update_elem(ctx->fd, &key, &value, BPF_F_LOCK);
56 		bpf_map_delete_elem(ctx->fd, &key);
57 	}
58 
59 	return NULL;
60 }
61 
62 void test_htab_reuse(void)
63 {
64 	unsigned int i, wr_nr = 1, rd_nr = 4;
65 	pthread_t tids[wr_nr + rd_nr];
66 	struct htab_reuse *skel;
67 	struct htab_op_ctx ctx;
68 	int err;
69 
70 	skel = htab_reuse__open_and_load();
71 	if (!ASSERT_OK_PTR(skel, "htab_reuse__open_and_load"))
72 		return;
73 
74 	ctx.fd = bpf_map__fd(skel->maps.htab);
75 	ctx.loop = 500;
76 	ctx.stop = false;
77 
78 	memset(tids, 0, sizeof(tids));
79 	for (i = 0; i < wr_nr; i++) {
80 		err = pthread_create(&tids[i], NULL, htab_update_fn, &ctx);
81 		if (!ASSERT_OK(err, "pthread_create")) {
82 			ctx.stop = true;
83 			goto reap;
84 		}
85 	}
86 	for (i = 0; i < rd_nr; i++) {
87 		err = pthread_create(&tids[i + wr_nr], NULL, htab_lookup_fn, &ctx);
88 		if (!ASSERT_OK(err, "pthread_create")) {
89 			ctx.stop = true;
90 			goto reap;
91 		}
92 	}
93 
94 reap:
95 	for (i = 0; i < wr_nr + rd_nr; i++) {
96 		if (!tids[i])
97 			continue;
98 		pthread_join(tids[i], NULL);
99 	}
100 	htab_reuse__destroy(skel);
101 }
102