1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Cavium, Inc
3 */
4
5 #include <stdio.h>
6 #include <inttypes.h>
7
8 #include <rte_common.h>
9 #include <rte_bitmap.h>
10 #include <rte_malloc.h>
11
12 #include "test.h"
13
14 #define MAX_BITS 1000
15
16 static int
test_bitmap_scan_operations(struct rte_bitmap * bmp)17 test_bitmap_scan_operations(struct rte_bitmap *bmp)
18 {
19 uint64_t slab1_magic = 0xBADC0FFEEBADF00D;
20 uint64_t slab2_magic = 0xFEEDDEADDEADF00D;
21 uint32_t pos = 0, start_pos;
22 int i, nb_clear, nb_set;
23 uint64_t out_slab = 0;
24
25 rte_bitmap_reset(bmp);
26
27 rte_bitmap_set_slab(bmp, pos, slab1_magic);
28 rte_bitmap_set_slab(bmp, pos + RTE_BITMAP_SLAB_BIT_SIZE, slab2_magic);
29
30 if (!rte_bitmap_scan(bmp, &pos, &out_slab)) {
31 printf("Failed to get slab from bitmap.\n");
32 return TEST_FAILED;
33 }
34
35 if (slab1_magic != out_slab) {
36 printf("Scan operation sanity failed.\n");
37 return TEST_FAILED;
38 }
39
40 if (!rte_bitmap_scan(bmp, &pos, &out_slab)) {
41 printf("Failed to get slab from bitmap.\n");
42 return TEST_FAILED;
43 }
44
45 if (slab2_magic != out_slab) {
46 printf("Scan operation sanity failed.\n");
47 return TEST_FAILED;
48 }
49
50 /* Wrap around */
51 if (!rte_bitmap_scan(bmp, &pos, &out_slab)) {
52 printf("Failed to get slab from bitmap.\n");
53 return TEST_FAILED;
54 }
55
56 if (slab1_magic != out_slab) {
57 printf("Scan operation wrap around failed.\n");
58 return TEST_FAILED;
59 }
60
61 /* Scan reset check. */
62 __rte_bitmap_scan_init(bmp);
63
64 if (!rte_bitmap_scan(bmp, &pos, &out_slab)) {
65 printf("Failed to get slab from bitmap.\n");
66 return TEST_FAILED;
67 }
68
69 if (slab1_magic != out_slab) {
70 printf("Scan reset operation failed.\n");
71 return TEST_FAILED;
72 }
73
74 /* Test scan when a cline is half full */
75 rte_bitmap_reset(bmp);
76 for (i = 0; i < MAX_BITS; i++)
77 rte_bitmap_set(bmp, i);
78
79 nb_clear = RTE_MIN(RTE_BITMAP_CL_BIT_SIZE / 2, MAX_BITS);
80 for (i = 0; i < nb_clear; i++)
81 rte_bitmap_clear(bmp, i);
82
83 /* Find remaining bits set in bmp */
84 __rte_bitmap_scan_init(bmp);
85
86 if (rte_bitmap_scan(bmp, &pos, &out_slab) != 1) {
87 printf("Initial scan failed with half CL empty.\n");
88 return TEST_FAILED;
89 }
90
91 start_pos = pos;
92 nb_set = 0;
93 do {
94 nb_set += rte_popcount64(out_slab);
95 if (!rte_bitmap_scan(bmp, &pos, &out_slab))
96 break;
97 } while (pos != start_pos);
98
99 if ((nb_clear + nb_set) != MAX_BITS) {
100 printf("Scan failed to find all set bits. "
101 "Expected %u, found %u.\n", MAX_BITS - nb_clear, nb_set);
102 return TEST_FAILED;
103 }
104
105 return TEST_SUCCESS;
106 }
107
108 static int
test_bitmap_slab_set_get(struct rte_bitmap * bmp)109 test_bitmap_slab_set_get(struct rte_bitmap *bmp)
110 {
111 uint32_t pos = 0;
112 uint64_t slab_magic = 0xBADC0FFEEBADF00D;
113 uint64_t out_slab = 0;
114
115 rte_bitmap_reset(bmp);
116 rte_bitmap_set_slab(bmp, pos, slab_magic);
117
118 if (!rte_bitmap_scan(bmp, &pos, &out_slab)) {
119 printf("Failed to get slab from bitmap.\n");
120 return TEST_FAILED;
121 }
122
123
124 if (slab_magic != out_slab) {
125 printf("Invalid slab in bitmap.\n");
126 return TEST_FAILED;
127 }
128
129
130 return TEST_SUCCESS;
131 }
132
133 static int
test_bitmap_set_get_clear(struct rte_bitmap * bmp)134 test_bitmap_set_get_clear(struct rte_bitmap *bmp)
135 {
136 uint64_t val;
137 int i;
138
139 rte_bitmap_reset(bmp);
140 for (i = 0; i < MAX_BITS; i++)
141 rte_bitmap_set(bmp, i);
142
143 for (i = 0; i < MAX_BITS; i++) {
144 if (!rte_bitmap_get(bmp, i)) {
145 printf("Failed to get set bit.\n");
146 return TEST_FAILED;
147 }
148 }
149
150 for (i = 0; i < MAX_BITS; i++)
151 rte_bitmap_clear(bmp, i);
152
153 for (i = 0; i < MAX_BITS; i++) {
154 if (rte_bitmap_get(bmp, i)) {
155 printf("Failed to clear set bit.\n");
156 return TEST_FAILED;
157 }
158 }
159
160 rte_bitmap_reset(bmp);
161
162 /* Alternate slab set test */
163 for (i = 0; i < MAX_BITS; i++) {
164 if (i % RTE_BITMAP_SLAB_BIT_SIZE)
165 rte_bitmap_set(bmp, i);
166 }
167
168 for (i = 0; i < MAX_BITS; i++) {
169 val = rte_bitmap_get(bmp, i);
170 if (((i % RTE_BITMAP_SLAB_BIT_SIZE) && !val) ||
171 (!(i % RTE_BITMAP_SLAB_BIT_SIZE) && val)) {
172 printf("Failed to get set bit.\n");
173 return TEST_FAILED;
174 }
175 }
176
177 return TEST_SUCCESS;
178 }
179
180 static int
test_bitmap_all_clear(void)181 test_bitmap_all_clear(void)
182 {
183 void *mem;
184 uint32_t bmp_size;
185 struct rte_bitmap *bmp;
186
187 bmp_size =
188 rte_bitmap_get_memory_footprint(MAX_BITS);
189
190 mem = rte_zmalloc("test_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
191 if (mem == NULL) {
192 printf("Failed to allocate memory for bitmap\n");
193 return TEST_FAILED;
194 }
195
196 bmp = rte_bitmap_init(MAX_BITS, mem, bmp_size);
197 if (bmp == NULL) {
198 printf("Failed to init bitmap\n");
199 return TEST_FAILED;
200 }
201
202 if (test_bitmap_set_get_clear(bmp) < 0)
203 return TEST_FAILED;
204
205 if (test_bitmap_slab_set_get(bmp) < 0)
206 return TEST_FAILED;
207
208 if (test_bitmap_scan_operations(bmp) < 0)
209 return TEST_FAILED;
210
211 rte_bitmap_free(bmp);
212 rte_free(mem);
213
214 return TEST_SUCCESS;
215 }
216
217 static int
test_bitmap_all_set(void)218 test_bitmap_all_set(void)
219 {
220 void *mem;
221 uint32_t i;
222 uint64_t slab;
223 uint32_t pos;
224 uint32_t bmp_size;
225 struct rte_bitmap *bmp;
226
227 bmp_size =
228 rte_bitmap_get_memory_footprint(MAX_BITS);
229
230 mem = rte_zmalloc("test_bmap", bmp_size, RTE_CACHE_LINE_SIZE);
231 if (mem == NULL) {
232 printf("Failed to allocate memory for bitmap\n");
233 return TEST_FAILED;
234 }
235
236 bmp = rte_bitmap_init_with_all_set(MAX_BITS, mem, bmp_size);
237 if (bmp == NULL) {
238 printf("Failed to init bitmap\n");
239 return TEST_FAILED;
240 }
241
242 for (i = 0; i < MAX_BITS; i++) {
243 pos = slab = 0;
244 if (!rte_bitmap_scan(bmp, &pos, &slab)) {
245 printf("Failed with init bitmap.\n");
246 return TEST_FAILED;
247 }
248 pos += (slab ? rte_ctz64(slab) : 0);
249 rte_bitmap_clear(bmp, pos);
250 }
251
252 if (rte_bitmap_scan(bmp, &pos, &slab)) {
253 printf("Too much bits set.\n");
254 return TEST_FAILED;
255 }
256
257 rte_bitmap_free(bmp);
258 rte_free(mem);
259
260 return TEST_SUCCESS;
261
262 }
263
264 static int
test_bitmap(void)265 test_bitmap(void)
266 {
267 if (test_bitmap_all_clear() != TEST_SUCCESS)
268 return TEST_FAILED;
269 return test_bitmap_all_set();
270 }
271
272 REGISTER_FAST_TEST(bitmap_autotest, true, true, test_bitmap);
273