xref: /freebsd/tests/sys/sys/buf_ring_test.c (revision e189296153a232e6066af7e4ddab0430d3b6677d)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2024 Arm Ltd
5  */
6 
7 #include <sys/types.h>
8 
9 #include <machine/cpu.h>
10 #include <machine/cpufunc.h>
11 
12 #include <errno.h>
13 #include <stdint.h>
14 
15 #include <atf-c.h>
16 
17 static void critical_enter(void);
18 static void critical_exit(void);
19 
20 #include <sys/buf_ring.h>
21 
22 static void
critical_enter(void)23 critical_enter(void)
24 {
25 }
26 
27 static void
critical_exit(void)28 critical_exit(void)
29 {
30 }
31 
32 static void *
buf_ring_dequeue_peek(struct buf_ring * br)33 buf_ring_dequeue_peek(struct buf_ring *br)
34 {
35 	void *val;
36 
37 	val = buf_ring_peek(br);
38 	if (val != NULL)
39 		buf_ring_advance_sc(br);
40 	return (val);
41 }
42 
43 static void *
buf_ring_dequeue_peek_clear_sc(struct buf_ring * br)44 buf_ring_dequeue_peek_clear_sc(struct buf_ring *br)
45 {
46 	void *val;
47 
48 	val = buf_ring_peek_clear_sc(br);
49 	if (val != NULL)
50 		buf_ring_advance_sc(br);
51 	return (val);
52 }
53 
54 #define	MC_SC_TEST(dequeue_func)					\
55 ATF_TC_WITHOUT_HEAD(dequeue_func);					\
56 ATF_TC_BODY(dequeue_func, tc)						\
57 {									\
58 	struct buf_ring *br;						\
59 									\
60 	br = buf_ring_alloc(4);						\
61 	ATF_REQUIRE_MSG(br != NULL, "buf_ring_alloc returned NULL");	\
62 									\
63 	ATF_REQUIRE(dequeue_func(br) == NULL);				\
64 	ATF_REQUIRE(buf_ring_count(br) == 0);				\
65 	ATF_REQUIRE(!buf_ring_full(br));				\
66 	ATF_REQUIRE(buf_ring_empty(br));				\
67 									\
68 	/* Try filling the buf_ring */					\
69 	ATF_REQUIRE(buf_ring_enqueue(br, (void *)1) == 0);		\
70 	ATF_REQUIRE(buf_ring_enqueue(br, (void *)2) == 0);		\
71 	ATF_REQUIRE(buf_ring_enqueue(br, (void *)3) == 0);		\
72 	ATF_REQUIRE(buf_ring_enqueue(br, (void *)4) == ENOBUFS);	\
73 									\
74 	ATF_REQUIRE(buf_ring_count(br) == 3);				\
75 	ATF_REQUIRE(buf_ring_full(br));					\
76 	ATF_REQUIRE(!buf_ring_empty(br));				\
77 									\
78 	/* Partially empty it */					\
79 	ATF_REQUIRE(dequeue_func(br) == (void *)1);			\
80 	ATF_REQUIRE(dequeue_func(br) == (void *)2);			\
81 									\
82 	ATF_REQUIRE(buf_ring_count(br) == 1);				\
83 	ATF_REQUIRE(!buf_ring_full(br));				\
84 	ATF_REQUIRE(!buf_ring_empty(br));				\
85 									\
86 	/* Add more items */						\
87 	ATF_REQUIRE(buf_ring_enqueue(br, (void *)5) == 0);		\
88 	ATF_REQUIRE(buf_ring_count(br) == 2);				\
89 									\
90 	/* Finish emptying it */					\
91 	ATF_REQUIRE(dequeue_func(br) == (void *)3);			\
92 	ATF_REQUIRE(dequeue_func(br) == (void *)5);			\
93 	ATF_REQUIRE(dequeue_func(br) == NULL);				\
94 									\
95 	ATF_REQUIRE(buf_ring_count(br) == 0);				\
96 	ATF_REQUIRE(!buf_ring_full(br));				\
97 	ATF_REQUIRE(buf_ring_empty(br));				\
98 									\
99 	for (uintptr_t i = 0; i < 8; i++) {				\
100 		ATF_REQUIRE(buf_ring_enqueue(br, (void *)(i + 100)) == 0);  \
101 		ATF_REQUIRE(buf_ring_enqueue(br, (void *)(i + 200)) == 0);  \
102 		ATF_REQUIRE(buf_ring_enqueue(br, (void *)(i + 300)) == 0);  \
103 		ATF_REQUIRE(buf_ring_count(br) == 3);			\
104 		ATF_REQUIRE(dequeue_func(br) == (void *)(i + 100));	\
105 		ATF_REQUIRE(dequeue_func(br) == (void *)(i + 200));	\
106 		ATF_REQUIRE(dequeue_func(br) == (void *)(i + 300));	\
107 									\
108 		ATF_REQUIRE(!buf_ring_full(br));			\
109 		ATF_REQUIRE(buf_ring_empty(br));			\
110 	}								\
111 									\
112 	buf_ring_free(br);						\
113 }
114 
115 MC_SC_TEST(buf_ring_dequeue_sc)
116 MC_SC_TEST(buf_ring_dequeue_mc)
117 MC_SC_TEST(buf_ring_dequeue_peek)
118 MC_SC_TEST(buf_ring_dequeue_peek_clear_sc)
119 
120 ATF_TC_WITHOUT_HEAD(overflow);
ATF_TC_BODY(overflow,tc)121 ATF_TC_BODY(overflow, tc)
122 {
123 	struct buf_ring *br;
124 
125 	br = buf_ring_alloc(4);
126 	ATF_REQUIRE_MSG(br != NULL, "buf_ring_alloc returned NULL");
127 
128 	br->br_prod_head = br->br_cons_head = br->br_prod_tail =
129 	    br->br_cons_tail = UINT32_MAX - 1;
130 	ATF_REQUIRE(buf_ring_count(br) == 0);
131 	ATF_REQUIRE(!buf_ring_full(br));
132 	ATF_REQUIRE(buf_ring_empty(br));
133 
134 	ATF_REQUIRE(buf_ring_enqueue(br, (void *)1) == 0);
135 	ATF_REQUIRE(buf_ring_count(br) == 1);
136 	ATF_REQUIRE(!buf_ring_full(br));
137 	ATF_REQUIRE(!buf_ring_empty(br));
138 
139 	ATF_REQUIRE(buf_ring_enqueue(br, (void *)2) == 0);
140 	ATF_REQUIRE(buf_ring_count(br) == 2);
141 	ATF_REQUIRE(!buf_ring_full(br));
142 	ATF_REQUIRE(!buf_ring_empty(br));
143 
144 	ATF_REQUIRE(buf_ring_enqueue(br, (void *)3) == 0);
145 	ATF_REQUIRE(buf_ring_count(br) == 3);
146 	ATF_REQUIRE(buf_ring_full(br));
147 	ATF_REQUIRE(!buf_ring_empty(br));
148 
149 	ATF_REQUIRE(br->br_prod_head == 1);
150 	ATF_REQUIRE(br->br_prod_tail == 1);
151 	ATF_REQUIRE(br->br_cons_head == UINT32_MAX - 1);
152 	ATF_REQUIRE(br->br_cons_tail == UINT32_MAX - 1);
153 
154 	ATF_REQUIRE(buf_ring_dequeue_sc(br) == (void *)1);
155 	ATF_REQUIRE(buf_ring_count(br) == 2);
156 	ATF_REQUIRE(!buf_ring_full(br));
157 	ATF_REQUIRE(!buf_ring_empty(br));
158 
159 	ATF_REQUIRE(buf_ring_dequeue_sc(br) == (void *)2);
160 	ATF_REQUIRE(buf_ring_count(br) == 1);
161 	ATF_REQUIRE(!buf_ring_full(br));
162 	ATF_REQUIRE(!buf_ring_empty(br));
163 
164 	ATF_REQUIRE(buf_ring_dequeue_sc(br) == (void *)3);
165 	ATF_REQUIRE(buf_ring_count(br) == 0);
166 	ATF_REQUIRE(!buf_ring_full(br));
167 	ATF_REQUIRE(buf_ring_empty(br));
168 
169 	buf_ring_free(br);
170 }
171 
ATF_TP_ADD_TCS(tp)172 ATF_TP_ADD_TCS(tp)
173 {
174 	ATF_TP_ADD_TC(tp, buf_ring_dequeue_sc);
175 	ATF_TP_ADD_TC(tp, buf_ring_dequeue_mc);
176 	ATF_TP_ADD_TC(tp, buf_ring_dequeue_peek);
177 	ATF_TP_ADD_TC(tp, buf_ring_dequeue_peek_clear_sc);
178 	ATF_TP_ADD_TC(tp, overflow);
179 	return (atf_no_error());
180 }
181