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