xref: /dpdk/app/test/test_bitops.c (revision 46ce151ce49d2e44155436adad5e39359db2889e)
17660614cSJoyce Kong /* SPDX-License-Identifier: BSD-3-Clause
27660614cSJoyce Kong  * Copyright(c) 2019 Arm Limited
3471de107SMattias Rönnblom  * Copyright(c) 2024 Ericsson AB
47660614cSJoyce Kong  */
57660614cSJoyce Kong 
635326b61SMattias Rönnblom #include <inttypes.h>
7471de107SMattias Rönnblom #include <stdbool.h>
8471de107SMattias Rönnblom 
97660614cSJoyce Kong #include <rte_bitops.h>
1035326b61SMattias Rönnblom #include <rte_cycles.h>
1135326b61SMattias Rönnblom #include <rte_launch.h>
1235326b61SMattias Rönnblom #include <rte_lcore.h>
13471de107SMattias Rönnblom #include <rte_random.h>
147660614cSJoyce Kong #include "test.h"
157660614cSJoyce Kong 
16*46ce151cSDavid Marchand static unsigned int
17*46ce151cSDavid Marchand get_worker_lcore(void)
18*46ce151cSDavid Marchand {
19*46ce151cSDavid Marchand 	unsigned int lcore_id = rte_get_next_lcore(-1, 1, 0);
20*46ce151cSDavid Marchand 
21*46ce151cSDavid Marchand 	/* avoid checkers (like Coverity) false positives */
22*46ce151cSDavid Marchand 	RTE_VERIFY(lcore_id < RTE_MAX_LCORE);
23*46ce151cSDavid Marchand 
24*46ce151cSDavid Marchand 	return lcore_id;
25*46ce151cSDavid Marchand }
26*46ce151cSDavid Marchand 
270883d736SMattias Rönnblom #define GEN_TEST_BIT_ACCESS(test_name, set_fun, clear_fun, assign_fun, flip_fun, test_fun, size, \
280883d736SMattias Rönnblom 		mod) \
29471de107SMattias Rönnblom static int \
30471de107SMattias Rönnblom test_name(void) \
31471de107SMattias Rönnblom { \
32471de107SMattias Rönnblom 	uint ## size ## _t reference = (uint ## size ## _t)rte_rand(); \
33471de107SMattias Rönnblom 	unsigned int bit_nr; \
340883d736SMattias Rönnblom 	mod uint ## size ## _t word = (uint ## size ## _t)rte_rand(); \
35471de107SMattias Rönnblom 	for (bit_nr = 0; bit_nr < size; bit_nr++) { \
36471de107SMattias Rönnblom 		bool reference_bit = (reference >> bit_nr) & 1; \
37471de107SMattias Rönnblom 		bool assign = rte_rand() & 1; \
38471de107SMattias Rönnblom 		if (assign) { \
39471de107SMattias Rönnblom 			assign_fun(&word, bit_nr, reference_bit); \
40471de107SMattias Rönnblom 		} else { \
41471de107SMattias Rönnblom 			if (reference_bit) \
42471de107SMattias Rönnblom 				set_fun(&word, bit_nr); \
43471de107SMattias Rönnblom 			else \
44471de107SMattias Rönnblom 				clear_fun(&word, bit_nr); \
45471de107SMattias Rönnblom 		} \
46471de107SMattias Rönnblom 		TEST_ASSERT(test_fun(&word, bit_nr) == reference_bit, \
47471de107SMattias Rönnblom 			"Bit %d had unexpected value", bit_nr); \
48471de107SMattias Rönnblom 		flip_fun(&word, bit_nr); \
49471de107SMattias Rönnblom 		TEST_ASSERT(test_fun(&word, bit_nr) != reference_bit, \
50471de107SMattias Rönnblom 			"Bit %d had unflipped value", bit_nr); \
51471de107SMattias Rönnblom 		flip_fun(&word, bit_nr); \
520883d736SMattias Rönnblom 		const mod uint ## size ## _t *const_ptr = &word; \
53471de107SMattias Rönnblom 		TEST_ASSERT(test_fun(const_ptr, bit_nr) == reference_bit, \
54471de107SMattias Rönnblom 			"Bit %d had unexpected value", bit_nr); \
55471de107SMattias Rönnblom 	} \
56471de107SMattias Rönnblom 	for (bit_nr = 0; bit_nr < size; bit_nr++) { \
57471de107SMattias Rönnblom 		bool reference_bit = (reference >> bit_nr) & 1; \
58471de107SMattias Rönnblom 		TEST_ASSERT(test_fun(&word, bit_nr) == reference_bit, \
59471de107SMattias Rönnblom 			"Bit %d had unexpected value", bit_nr); \
60471de107SMattias Rönnblom 	} \
61471de107SMattias Rönnblom 	TEST_ASSERT(reference == word, "Word had unexpected value"); \
62471de107SMattias Rönnblom 	return TEST_SUCCESS; \
63471de107SMattias Rönnblom }
64471de107SMattias Rönnblom 
65471de107SMattias Rönnblom GEN_TEST_BIT_ACCESS(test_bit_access32, rte_bit_set, rte_bit_clear, rte_bit_assign, rte_bit_flip,
660883d736SMattias Rönnblom 	rte_bit_test, 32,)
67471de107SMattias Rönnblom 
68471de107SMattias Rönnblom GEN_TEST_BIT_ACCESS(test_bit_access64, rte_bit_set, rte_bit_clear, rte_bit_assign, rte_bit_flip,
690883d736SMattias Rönnblom 	rte_bit_test, 64,)
700883d736SMattias Rönnblom 
710883d736SMattias Rönnblom GEN_TEST_BIT_ACCESS(test_bit_v_access32, rte_bit_set, rte_bit_clear, rte_bit_assign, rte_bit_flip,
720883d736SMattias Rönnblom 	rte_bit_test, 32, volatile)
730883d736SMattias Rönnblom 
740883d736SMattias Rönnblom GEN_TEST_BIT_ACCESS(test_bit_v_access64, rte_bit_set, rte_bit_clear, rte_bit_assign, rte_bit_flip,
750883d736SMattias Rönnblom 	rte_bit_test, 64, volatile)
76471de107SMattias Rönnblom 
7735326b61SMattias Rönnblom #define bit_atomic_set(addr, nr) \
7835326b61SMattias Rönnblom 	rte_bit_atomic_set(addr, nr, rte_memory_order_relaxed)
7935326b61SMattias Rönnblom 
8035326b61SMattias Rönnblom #define bit_atomic_clear(addr, nr) \
8135326b61SMattias Rönnblom 	rte_bit_atomic_clear(addr, nr, rte_memory_order_relaxed)
8235326b61SMattias Rönnblom 
8335326b61SMattias Rönnblom #define bit_atomic_assign(addr, nr, value) \
8435326b61SMattias Rönnblom 	rte_bit_atomic_assign(addr, nr, value, rte_memory_order_relaxed)
8535326b61SMattias Rönnblom 
8635326b61SMattias Rönnblom #define bit_atomic_flip(addr, nr) \
8735326b61SMattias Rönnblom 	rte_bit_atomic_flip(addr, nr, rte_memory_order_relaxed)
8835326b61SMattias Rönnblom 
8935326b61SMattias Rönnblom #define bit_atomic_test(addr, nr) \
9035326b61SMattias Rönnblom 	rte_bit_atomic_test(addr, nr, rte_memory_order_relaxed)
9135326b61SMattias Rönnblom 
9235326b61SMattias Rönnblom GEN_TEST_BIT_ACCESS(test_bit_atomic_access32, bit_atomic_set, bit_atomic_clear, bit_atomic_assign,
930883d736SMattias Rönnblom 	bit_atomic_flip, bit_atomic_test, 32,)
9435326b61SMattias Rönnblom 
9535326b61SMattias Rönnblom GEN_TEST_BIT_ACCESS(test_bit_atomic_access64, bit_atomic_set, bit_atomic_clear, bit_atomic_assign,
960883d736SMattias Rönnblom 	bit_atomic_flip, bit_atomic_test, 64,)
970883d736SMattias Rönnblom 
980883d736SMattias Rönnblom GEN_TEST_BIT_ACCESS(test_bit_atomic_v_access32, bit_atomic_set, bit_atomic_clear, bit_atomic_assign,
990883d736SMattias Rönnblom 	bit_atomic_flip, bit_atomic_test, 32, volatile)
1000883d736SMattias Rönnblom 
1010883d736SMattias Rönnblom GEN_TEST_BIT_ACCESS(test_bit_atomic_v_access64, bit_atomic_set, bit_atomic_clear, bit_atomic_assign,
1020883d736SMattias Rönnblom 	bit_atomic_flip, bit_atomic_test, 64, volatile)
10335326b61SMattias Rönnblom 
10435326b61SMattias Rönnblom #define PARALLEL_TEST_RUNTIME 0.25
10535326b61SMattias Rönnblom 
10635326b61SMattias Rönnblom #define GEN_TEST_BIT_PARALLEL_ASSIGN(size) \
10735326b61SMattias Rönnblom struct parallel_access_lcore ## size \
10835326b61SMattias Rönnblom { \
10935326b61SMattias Rönnblom 	unsigned int bit; \
11035326b61SMattias Rönnblom 	uint ## size ##_t *word; \
11135326b61SMattias Rönnblom 	bool failed; \
11235326b61SMattias Rönnblom }; \
11335326b61SMattias Rönnblom static int \
11435326b61SMattias Rönnblom run_parallel_assign ## size(void *arg) \
11535326b61SMattias Rönnblom { \
11635326b61SMattias Rönnblom 	struct parallel_access_lcore ## size *lcore = arg; \
11735326b61SMattias Rönnblom 	uint64_t deadline = rte_get_timer_cycles() + PARALLEL_TEST_RUNTIME * rte_get_timer_hz(); \
11835326b61SMattias Rönnblom 	bool value = false; \
11935326b61SMattias Rönnblom 	do { \
12035326b61SMattias Rönnblom 		bool new_value = rte_rand() & 1; \
12135326b61SMattias Rönnblom 		bool use_test_and_modify = rte_rand() & 1; \
12235326b61SMattias Rönnblom 		bool use_assign = rte_rand() & 1; \
12335326b61SMattias Rönnblom 		if (rte_bit_atomic_test(lcore->word, lcore->bit, \
12435326b61SMattias Rönnblom 					rte_memory_order_relaxed) != value) { \
12535326b61SMattias Rönnblom 			lcore->failed = true; \
12635326b61SMattias Rönnblom 			break; \
12735326b61SMattias Rönnblom 		} \
12835326b61SMattias Rönnblom 		if (use_test_and_modify) { \
12935326b61SMattias Rönnblom 			bool old_value; \
13035326b61SMattias Rönnblom 			if (use_assign) { \
13135326b61SMattias Rönnblom 				old_value = rte_bit_atomic_test_and_assign(lcore->word, \
13235326b61SMattias Rönnblom 					lcore->bit, new_value, rte_memory_order_relaxed); \
13335326b61SMattias Rönnblom 			} else { \
13435326b61SMattias Rönnblom 				old_value = new_value ? \
13535326b61SMattias Rönnblom 					rte_bit_atomic_test_and_set(lcore->word, lcore->bit, \
13635326b61SMattias Rönnblom 						rte_memory_order_relaxed) : \
13735326b61SMattias Rönnblom 					rte_bit_atomic_test_and_clear(lcore->word, lcore->bit, \
13835326b61SMattias Rönnblom 						rte_memory_order_relaxed); \
13935326b61SMattias Rönnblom 			} \
14035326b61SMattias Rönnblom 			if (old_value != value) { \
14135326b61SMattias Rönnblom 				lcore->failed = true; \
14235326b61SMattias Rönnblom 				break; \
14335326b61SMattias Rönnblom 			} \
14435326b61SMattias Rönnblom 		} else { \
14535326b61SMattias Rönnblom 			if (use_assign) { \
14635326b61SMattias Rönnblom 				rte_bit_atomic_assign(lcore->word, lcore->bit, new_value, \
14735326b61SMattias Rönnblom 					rte_memory_order_relaxed); \
14835326b61SMattias Rönnblom 			} else { \
14935326b61SMattias Rönnblom 				if (new_value) \
15035326b61SMattias Rönnblom 					rte_bit_atomic_set(lcore->word, lcore->bit, \
15135326b61SMattias Rönnblom 						rte_memory_order_relaxed); \
15235326b61SMattias Rönnblom 				else \
15335326b61SMattias Rönnblom 					rte_bit_atomic_clear(lcore->word, lcore->bit, \
15435326b61SMattias Rönnblom 						rte_memory_order_relaxed); \
15535326b61SMattias Rönnblom 			} \
15635326b61SMattias Rönnblom 		} \
15735326b61SMattias Rönnblom 		value = new_value; \
15835326b61SMattias Rönnblom 	} while (rte_get_timer_cycles() < deadline); \
15935326b61SMattias Rönnblom 	return 0; \
16035326b61SMattias Rönnblom } \
16135326b61SMattias Rönnblom static int \
16235326b61SMattias Rönnblom test_bit_atomic_parallel_assign ## size(void) \
16335326b61SMattias Rönnblom { \
16435326b61SMattias Rönnblom 	unsigned int worker_lcore_id; \
16535326b61SMattias Rönnblom 	uint ## size ## _t word = 0; \
16635326b61SMattias Rönnblom 	struct parallel_access_lcore ## size lmain = { .word = &word }; \
16735326b61SMattias Rönnblom 	struct parallel_access_lcore ## size lworker = { .word = &word }; \
16835326b61SMattias Rönnblom 	if (rte_lcore_count() < 2) { \
16935326b61SMattias Rönnblom 		printf("Need multiple cores to run parallel test.\n"); \
17035326b61SMattias Rönnblom 		return TEST_SKIPPED; \
17135326b61SMattias Rönnblom 	} \
172*46ce151cSDavid Marchand 	worker_lcore_id = get_worker_lcore(); \
17335326b61SMattias Rönnblom 	lmain.bit = rte_rand_max(size); \
17435326b61SMattias Rönnblom 	do { \
17535326b61SMattias Rönnblom 		lworker.bit = rte_rand_max(size); \
17635326b61SMattias Rönnblom 	} while (lworker.bit == lmain.bit); \
17735326b61SMattias Rönnblom 	int rc = rte_eal_remote_launch(run_parallel_assign ## size, &lworker, worker_lcore_id); \
17835326b61SMattias Rönnblom 	TEST_ASSERT(rc == 0, "Worker thread launch failed"); \
17935326b61SMattias Rönnblom 	run_parallel_assign ## size(&lmain); \
18035326b61SMattias Rönnblom 	rte_eal_mp_wait_lcore(); \
18135326b61SMattias Rönnblom 	TEST_ASSERT(!lmain.failed, "Main lcore atomic access failed"); \
18235326b61SMattias Rönnblom 	TEST_ASSERT(!lworker.failed, "Worker lcore atomic access failed"); \
18335326b61SMattias Rönnblom 	return TEST_SUCCESS; \
18435326b61SMattias Rönnblom }
18535326b61SMattias Rönnblom 
18635326b61SMattias Rönnblom GEN_TEST_BIT_PARALLEL_ASSIGN(32)
18735326b61SMattias Rönnblom GEN_TEST_BIT_PARALLEL_ASSIGN(64)
18835326b61SMattias Rönnblom 
18935326b61SMattias Rönnblom #define GEN_TEST_BIT_PARALLEL_TEST_AND_MODIFY(size) \
19035326b61SMattias Rönnblom struct parallel_test_and_set_lcore ## size \
19135326b61SMattias Rönnblom { \
19235326b61SMattias Rönnblom 	uint ## size ##_t *word; \
19335326b61SMattias Rönnblom 	unsigned int bit; \
19435326b61SMattias Rönnblom 	uint64_t flips; \
19535326b61SMattias Rönnblom }; \
19635326b61SMattias Rönnblom static int \
19735326b61SMattias Rönnblom run_parallel_test_and_modify ## size(void *arg) \
19835326b61SMattias Rönnblom { \
19935326b61SMattias Rönnblom 	struct parallel_test_and_set_lcore ## size *lcore = arg; \
20035326b61SMattias Rönnblom 	uint64_t deadline = rte_get_timer_cycles() + PARALLEL_TEST_RUNTIME * rte_get_timer_hz(); \
20135326b61SMattias Rönnblom 	do { \
20235326b61SMattias Rönnblom 		bool old_value; \
20335326b61SMattias Rönnblom 		bool new_value = rte_rand() & 1; \
20435326b61SMattias Rönnblom 		bool use_assign = rte_rand() & 1; \
20535326b61SMattias Rönnblom 		if (use_assign) \
20635326b61SMattias Rönnblom 			old_value = rte_bit_atomic_test_and_assign(lcore->word, lcore->bit, \
20735326b61SMattias Rönnblom 				new_value, rte_memory_order_relaxed); \
20835326b61SMattias Rönnblom 		else \
20935326b61SMattias Rönnblom 			old_value = new_value ? \
21035326b61SMattias Rönnblom 				rte_bit_atomic_test_and_set(lcore->word, lcore->bit, \
21135326b61SMattias Rönnblom 					rte_memory_order_relaxed) : \
21235326b61SMattias Rönnblom 				rte_bit_atomic_test_and_clear(lcore->word, lcore->bit, \
21335326b61SMattias Rönnblom 					rte_memory_order_relaxed); \
21435326b61SMattias Rönnblom 		if (old_value != new_value) \
21535326b61SMattias Rönnblom 			lcore->flips++; \
21635326b61SMattias Rönnblom 	} while (rte_get_timer_cycles() < deadline); \
21735326b61SMattias Rönnblom 	return 0; \
21835326b61SMattias Rönnblom } \
21935326b61SMattias Rönnblom static int \
22035326b61SMattias Rönnblom test_bit_atomic_parallel_test_and_modify ## size(void) \
22135326b61SMattias Rönnblom { \
22235326b61SMattias Rönnblom 	unsigned int worker_lcore_id; \
22335326b61SMattias Rönnblom 	uint ## size ## _t word = 0; \
22435326b61SMattias Rönnblom 	unsigned int bit = rte_rand_max(size); \
22535326b61SMattias Rönnblom 	struct parallel_test_and_set_lcore ## size lmain = { .word = &word, .bit = bit }; \
22635326b61SMattias Rönnblom 	struct parallel_test_and_set_lcore ## size lworker = { .word = &word, .bit = bit }; \
22735326b61SMattias Rönnblom 	if (rte_lcore_count() < 2) { \
22835326b61SMattias Rönnblom 		printf("Need multiple cores to run parallel test.\n"); \
22935326b61SMattias Rönnblom 		return TEST_SKIPPED; \
23035326b61SMattias Rönnblom 	} \
231*46ce151cSDavid Marchand 	worker_lcore_id = get_worker_lcore(); \
23235326b61SMattias Rönnblom 	int rc = rte_eal_remote_launch(run_parallel_test_and_modify ## size, &lworker, \
23335326b61SMattias Rönnblom 		worker_lcore_id); \
23435326b61SMattias Rönnblom 	TEST_ASSERT(rc == 0, "Worker thread launch failed"); \
23535326b61SMattias Rönnblom 	run_parallel_test_and_modify ## size(&lmain); \
23635326b61SMattias Rönnblom 	rte_eal_mp_wait_lcore(); \
23735326b61SMattias Rönnblom 	uint64_t total_flips = lmain.flips + lworker.flips; \
23835326b61SMattias Rönnblom 	bool expected_value = total_flips % 2; \
23935326b61SMattias Rönnblom 	TEST_ASSERT(expected_value == rte_bit_test(&word, bit), \
24035326b61SMattias Rönnblom 		"After %"PRId64" flips, the bit value should be %d", total_flips, expected_value); \
241899cffe0SMattias Rönnblom 	uint ## size ## _t expected_word = 0; \
24235326b61SMattias Rönnblom 	rte_bit_assign(&expected_word, bit, expected_value); \
24335326b61SMattias Rönnblom 	TEST_ASSERT(expected_word == word, "Untouched bits have changed value"); \
24435326b61SMattias Rönnblom 	return TEST_SUCCESS; \
24535326b61SMattias Rönnblom }
24635326b61SMattias Rönnblom 
24735326b61SMattias Rönnblom GEN_TEST_BIT_PARALLEL_TEST_AND_MODIFY(32)
24835326b61SMattias Rönnblom GEN_TEST_BIT_PARALLEL_TEST_AND_MODIFY(64)
24935326b61SMattias Rönnblom 
25035326b61SMattias Rönnblom #define GEN_TEST_BIT_PARALLEL_FLIP(size) \
25135326b61SMattias Rönnblom struct parallel_flip_lcore ## size \
25235326b61SMattias Rönnblom { \
25335326b61SMattias Rönnblom 	uint ## size ##_t *word; \
25435326b61SMattias Rönnblom 	unsigned int bit; \
25535326b61SMattias Rönnblom 	uint64_t flips; \
25635326b61SMattias Rönnblom }; \
25735326b61SMattias Rönnblom static int \
25835326b61SMattias Rönnblom run_parallel_flip ## size(void *arg) \
25935326b61SMattias Rönnblom { \
26035326b61SMattias Rönnblom 	struct parallel_flip_lcore ## size *lcore = arg; \
26135326b61SMattias Rönnblom 	uint64_t deadline = rte_get_timer_cycles() + PARALLEL_TEST_RUNTIME * rte_get_timer_hz(); \
26235326b61SMattias Rönnblom 	do { \
26335326b61SMattias Rönnblom 		rte_bit_atomic_flip(lcore->word, lcore->bit, rte_memory_order_relaxed); \
26435326b61SMattias Rönnblom 		lcore->flips++; \
26535326b61SMattias Rönnblom 	} while (rte_get_timer_cycles() < deadline); \
26635326b61SMattias Rönnblom 	return 0; \
26735326b61SMattias Rönnblom } \
26835326b61SMattias Rönnblom static int \
26935326b61SMattias Rönnblom test_bit_atomic_parallel_flip ## size(void) \
27035326b61SMattias Rönnblom { \
27135326b61SMattias Rönnblom 	unsigned int worker_lcore_id; \
27235326b61SMattias Rönnblom 	uint ## size ## _t word = 0; \
27335326b61SMattias Rönnblom 	unsigned int bit = rte_rand_max(size); \
27435326b61SMattias Rönnblom 	struct parallel_flip_lcore ## size lmain = { .word = &word, .bit = bit }; \
27535326b61SMattias Rönnblom 	struct parallel_flip_lcore ## size lworker = { .word = &word, .bit = bit }; \
27635326b61SMattias Rönnblom 	if (rte_lcore_count() < 2) { \
27735326b61SMattias Rönnblom 		printf("Need multiple cores to run parallel test.\n"); \
27835326b61SMattias Rönnblom 		return TEST_SKIPPED; \
27935326b61SMattias Rönnblom 	} \
280*46ce151cSDavid Marchand 	worker_lcore_id = get_worker_lcore(); \
28135326b61SMattias Rönnblom 	int rc = rte_eal_remote_launch(run_parallel_flip ## size, &lworker, worker_lcore_id); \
28235326b61SMattias Rönnblom 	TEST_ASSERT(rc == 0, "Worker thread launch failed"); \
28335326b61SMattias Rönnblom 	run_parallel_flip ## size(&lmain); \
28435326b61SMattias Rönnblom 	rte_eal_mp_wait_lcore(); \
28535326b61SMattias Rönnblom 	uint64_t total_flips = lmain.flips + lworker.flips; \
28635326b61SMattias Rönnblom 	bool expected_value = total_flips % 2; \
28735326b61SMattias Rönnblom 	TEST_ASSERT(expected_value == rte_bit_test(&word, bit), \
28835326b61SMattias Rönnblom 		"After %"PRId64" flips, the bit value should be %d", total_flips, expected_value); \
289899cffe0SMattias Rönnblom 	uint ## size ## _t expected_word = 0; \
29035326b61SMattias Rönnblom 	rte_bit_assign(&expected_word, bit, expected_value); \
29135326b61SMattias Rönnblom 	TEST_ASSERT(expected_word == word, "Untouched bits have changed value"); \
29235326b61SMattias Rönnblom 	return TEST_SUCCESS; \
29335326b61SMattias Rönnblom }
29435326b61SMattias Rönnblom 
29535326b61SMattias Rönnblom GEN_TEST_BIT_PARALLEL_FLIP(32)
29635326b61SMattias Rönnblom GEN_TEST_BIT_PARALLEL_FLIP(64)
29735326b61SMattias Rönnblom 
298471de107SMattias Rönnblom static uint32_t val32;
299471de107SMattias Rönnblom static uint64_t val64;
3007660614cSJoyce Kong 
3017660614cSJoyce Kong #define MAX_BITS_32 32
3027660614cSJoyce Kong #define MAX_BITS_64 64
3037660614cSJoyce Kong 
3047660614cSJoyce Kong /*
3057660614cSJoyce Kong  * Bitops functions
3067660614cSJoyce Kong  * ================
3077660614cSJoyce Kong  *
3087660614cSJoyce Kong  * - The main test function performs several subtests.
3097660614cSJoyce Kong  * - Check bit operations on one core.
3107660614cSJoyce Kong  *   - Initialize valXX to specified values, then set each bit of valXX
3117660614cSJoyce Kong  *     to 1 one by one in "test_bit_relaxed_set".
3127660614cSJoyce Kong  *
3137660614cSJoyce Kong  *   - Clear each bit of valXX to 0 one by one in "test_bit_relaxed_clear".
3147660614cSJoyce Kong  *
3157660614cSJoyce Kong  *   - Function "test_bit_relaxed_test_set_clear" checks whether each bit
3167660614cSJoyce Kong  *     of valXX can do "test and set" and "test and clear" correctly.
3177660614cSJoyce Kong  */
3187660614cSJoyce Kong 
3197660614cSJoyce Kong static int
3207660614cSJoyce Kong test_bit_relaxed_set(void)
3217660614cSJoyce Kong {
3227660614cSJoyce Kong 	unsigned int i;
3237660614cSJoyce Kong 
3247660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_32; i++)
3257660614cSJoyce Kong 		rte_bit_relaxed_set32(i, &val32);
3267660614cSJoyce Kong 
3277660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_32; i++)
3287660614cSJoyce Kong 		if (!rte_bit_relaxed_get32(i, &val32)) {
3297660614cSJoyce Kong 			printf("Failed to set bit in relaxed version.\n");
3307660614cSJoyce Kong 			return TEST_FAILED;
3317660614cSJoyce Kong 		}
3327660614cSJoyce Kong 
3337660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_64; i++)
3347660614cSJoyce Kong 		rte_bit_relaxed_set64(i, &val64);
3357660614cSJoyce Kong 
3367660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_64; i++)
3377660614cSJoyce Kong 		if (!rte_bit_relaxed_get64(i, &val64)) {
3387660614cSJoyce Kong 			printf("Failed to set bit in relaxed version.\n");
3397660614cSJoyce Kong 			return TEST_FAILED;
3407660614cSJoyce Kong 		}
3417660614cSJoyce Kong 
3427660614cSJoyce Kong 	return TEST_SUCCESS;
3437660614cSJoyce Kong }
3447660614cSJoyce Kong 
3457660614cSJoyce Kong static int
3467660614cSJoyce Kong test_bit_relaxed_clear(void)
3477660614cSJoyce Kong {
3487660614cSJoyce Kong 	unsigned int i;
3497660614cSJoyce Kong 
3507660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_32; i++)
3517660614cSJoyce Kong 		rte_bit_relaxed_clear32(i, &val32);
3527660614cSJoyce Kong 
3537660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_32; i++)
3547660614cSJoyce Kong 		if (rte_bit_relaxed_get32(i, &val32)) {
3557660614cSJoyce Kong 			printf("Failed to clear bit in relaxed version.\n");
3567660614cSJoyce Kong 			return TEST_FAILED;
3577660614cSJoyce Kong 		}
3587660614cSJoyce Kong 
3597660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_64; i++)
3607660614cSJoyce Kong 		rte_bit_relaxed_clear64(i, &val64);
3617660614cSJoyce Kong 
3627660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_64; i++)
3637660614cSJoyce Kong 		if (rte_bit_relaxed_get64(i, &val64)) {
3647660614cSJoyce Kong 			printf("Failed to clear bit in relaxed version.\n");
3657660614cSJoyce Kong 			return TEST_FAILED;
3667660614cSJoyce Kong 		}
3677660614cSJoyce Kong 
3687660614cSJoyce Kong 	return TEST_SUCCESS;
3697660614cSJoyce Kong }
3707660614cSJoyce Kong 
3717660614cSJoyce Kong static int
3727660614cSJoyce Kong test_bit_relaxed_test_set_clear(void)
3737660614cSJoyce Kong {
3747660614cSJoyce Kong 	unsigned int i;
3757660614cSJoyce Kong 
3767660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_32; i++)
3777660614cSJoyce Kong 		rte_bit_relaxed_test_and_set32(i, &val32);
3787660614cSJoyce Kong 
3797660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_32; i++)
3807660614cSJoyce Kong 		if (!rte_bit_relaxed_test_and_clear32(i, &val32)) {
3817660614cSJoyce Kong 			printf("Failed to set and test bit in relaxed version.\n");
3827660614cSJoyce Kong 			return TEST_FAILED;
3837660614cSJoyce Kong 	}
3847660614cSJoyce Kong 
3857660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_32; i++)
3867660614cSJoyce Kong 		if (rte_bit_relaxed_get32(i, &val32)) {
3877660614cSJoyce Kong 			printf("Failed to test and clear bit in relaxed version.\n");
3887660614cSJoyce Kong 			return TEST_FAILED;
3897660614cSJoyce Kong 		}
3907660614cSJoyce Kong 
3917660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_64; i++)
3927660614cSJoyce Kong 		rte_bit_relaxed_test_and_set64(i, &val64);
3937660614cSJoyce Kong 
3947660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_64; i++)
3957660614cSJoyce Kong 		if (!rte_bit_relaxed_test_and_clear64(i, &val64)) {
3967660614cSJoyce Kong 			printf("Failed to set and test bit in relaxed version.\n");
3977660614cSJoyce Kong 			return TEST_FAILED;
3987660614cSJoyce Kong 		}
3997660614cSJoyce Kong 
4007660614cSJoyce Kong 	for (i = 0; i < MAX_BITS_64; i++)
4017660614cSJoyce Kong 		if (rte_bit_relaxed_get64(i, &val64)) {
4027660614cSJoyce Kong 			printf("Failed to test and clear bit in relaxed version.\n");
4037660614cSJoyce Kong 			return TEST_FAILED;
4047660614cSJoyce Kong 		}
4057660614cSJoyce Kong 
4067660614cSJoyce Kong 	return TEST_SUCCESS;
4077660614cSJoyce Kong }
4087660614cSJoyce Kong 
409471de107SMattias Rönnblom static struct unit_test_suite test_suite = {
410471de107SMattias Rönnblom 	.suite_name = "Bitops test suite",
411471de107SMattias Rönnblom 	.unit_test_cases = {
412471de107SMattias Rönnblom 		TEST_CASE(test_bit_access32),
413471de107SMattias Rönnblom 		TEST_CASE(test_bit_access64),
41435326b61SMattias Rönnblom 		TEST_CASE(test_bit_access32),
41535326b61SMattias Rönnblom 		TEST_CASE(test_bit_access64),
4160883d736SMattias Rönnblom 		TEST_CASE(test_bit_v_access32),
4170883d736SMattias Rönnblom 		TEST_CASE(test_bit_v_access64),
41835326b61SMattias Rönnblom 		TEST_CASE(test_bit_atomic_access32),
41935326b61SMattias Rönnblom 		TEST_CASE(test_bit_atomic_access64),
4200883d736SMattias Rönnblom 		TEST_CASE(test_bit_atomic_v_access32),
4210883d736SMattias Rönnblom 		TEST_CASE(test_bit_atomic_v_access64),
42235326b61SMattias Rönnblom 		TEST_CASE(test_bit_atomic_parallel_assign32),
42335326b61SMattias Rönnblom 		TEST_CASE(test_bit_atomic_parallel_assign64),
42435326b61SMattias Rönnblom 		TEST_CASE(test_bit_atomic_parallel_test_and_modify32),
42535326b61SMattias Rönnblom 		TEST_CASE(test_bit_atomic_parallel_test_and_modify64),
42635326b61SMattias Rönnblom 		TEST_CASE(test_bit_atomic_parallel_flip32),
42735326b61SMattias Rönnblom 		TEST_CASE(test_bit_atomic_parallel_flip64),
428471de107SMattias Rönnblom 		TEST_CASE(test_bit_relaxed_set),
429471de107SMattias Rönnblom 		TEST_CASE(test_bit_relaxed_clear),
430471de107SMattias Rönnblom 		TEST_CASE(test_bit_relaxed_test_set_clear),
431471de107SMattias Rönnblom 		TEST_CASES_END()
432471de107SMattias Rönnblom 	}
433471de107SMattias Rönnblom };
434471de107SMattias Rönnblom 
4357660614cSJoyce Kong static int
4367660614cSJoyce Kong test_bitops(void)
4377660614cSJoyce Kong {
438471de107SMattias Rönnblom 	return unit_test_suite_runner(&test_suite);
4397660614cSJoyce Kong }
4407660614cSJoyce Kong 
441e0a8442cSBruce Richardson REGISTER_FAST_TEST(bitops_autotest, true, true, test_bitops);
442