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