Commit 212eb893 authored by Wojciech Malikowski's avatar Wojciech Malikowski Committed by Jim Harris
Browse files

util: added bit array bitmask load, store and clear



Change-Id: I7cd47184d0dfb038297c0ac04d7dfb5d31f96b6b
Signed-off-by: default avatarWojciech Malikowski <wojciech.malikowski@intel.com>
Reviewed-on: https://review.gerrithub.io/432537


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarPaul Luse <paul.e.luse@intel.com>
Reviewed-by: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
parent 7245134a
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -173,6 +173,29 @@ uint32_t spdk_bit_array_count_set(const struct spdk_bit_array *ba);
 */
uint32_t spdk_bit_array_count_clear(const struct spdk_bit_array *ba);

/**
 * Store bitmask from bit array.
 *
 * \param ba Bit array.
 * \param mask Destination mask. Mask and bit array capacity must be equal.
 */
void spdk_bit_array_store_mask(const struct spdk_bit_array *ba, void *mask);

/**
 * Load bitmask to bit array.
 *
 * \param ba Bit array.
 * \param mask Source mask. Mask and bit array capacity must be equal.
 */
void spdk_bit_array_load_mask(struct spdk_bit_array *ba, const void *mask);

/**
 * Clear (to 0) bit array bitmask.
 *
 * \param ba Bit array.
 */
void spdk_bit_array_clear_mask(struct spdk_bit_array *ba);

#ifdef __cplusplus
}
#endif
+50 −0
Original line number Diff line number Diff line
@@ -311,3 +311,53 @@ spdk_bit_array_count_clear(const struct spdk_bit_array *ba)
{
	return ba->bit_count - spdk_bit_array_count_set(ba);
}

void
spdk_bit_array_store_mask(const struct spdk_bit_array *ba, void *mask)
{
	uint32_t size, i;
	uint32_t num_bits = spdk_bit_array_capacity(ba);

	size = num_bits / CHAR_BIT;
	memcpy(mask, ba->words, size);

	for (i = 0; i < num_bits % CHAR_BIT; i++) {
		if (spdk_bit_array_get(ba, i + size * CHAR_BIT)) {
			((uint8_t *)mask)[size] |= (1U << i);
		} else {
			((uint8_t *)mask)[size] &= ~(1U << i);
		}
	}
}

void
spdk_bit_array_load_mask(struct spdk_bit_array *ba, const void *mask)
{
	uint32_t size, i;
	uint32_t num_bits = spdk_bit_array_capacity(ba);

	size = num_bits / CHAR_BIT;
	memcpy(ba->words, mask, size);

	for (i = 0; i < num_bits % CHAR_BIT; i++) {
		if (((uint8_t *)mask)[size] & (1U << i)) {
			spdk_bit_array_set(ba, i + size * CHAR_BIT);
		} else {
			spdk_bit_array_clear(ba, i + size * CHAR_BIT);
		}
	}
}

void
spdk_bit_array_clear_mask(struct spdk_bit_array *ba)
{
	uint32_t size, i;
	uint32_t num_bits = spdk_bit_array_capacity(ba);

	size = num_bits / CHAR_BIT;
	memset(ba->words, 0, size);

	for (i = 0; i < num_bits % CHAR_BIT; i++) {
		spdk_bit_array_clear(ba, i + size * CHAR_BIT);
	}
}
+70 −1
Original line number Diff line number Diff line
@@ -289,6 +289,73 @@ test_count(void)
	spdk_bit_array_free(&ba);
}

#define TEST_MASK_SIZE 128
#define TEST_BITS_NUM (TEST_MASK_SIZE * 8 - 3)
static void
test_mask_store_load(void)
{
	struct spdk_bit_array *ba;
	uint8_t mask[TEST_MASK_SIZE] = { 0 };
	uint32_t i;

	ba = spdk_bit_array_create(TEST_BITS_NUM);

	/* Check if stored mask is consistent with bit array mask */
	spdk_bit_array_set(ba, 0);
	spdk_bit_array_set(ba, TEST_BITS_NUM / 2);
	spdk_bit_array_set(ba, TEST_BITS_NUM - 1);

	spdk_bit_array_store_mask(ba, mask);

	for (i = 0; i < TEST_BITS_NUM; i++) {
		if (i == 0 || i == TEST_BITS_NUM / 2 || i == TEST_BITS_NUM - 1) {
			CU_ASSERT((mask[i / 8] & (1U << (i % 8))));
		} else {
			CU_ASSERT(!(mask[i / 8] & (1U << (i % 8))));
		}
	}

	/* Check if loaded mask is consistent with bit array mask */
	memset(mask, 0, TEST_MASK_SIZE);
	mask[0] = 1;
	mask[TEST_MASK_SIZE - 1] = 1U << 4;

	spdk_bit_array_load_mask(ba, mask);

	CU_ASSERT(spdk_bit_array_get(ba, 0));
	CU_ASSERT(spdk_bit_array_get(ba, TEST_BITS_NUM - 1));

	spdk_bit_array_clear(ba, 0);
	spdk_bit_array_clear(ba, TEST_BITS_NUM - 1);

	for (i = 0; i < TEST_BITS_NUM; i++) {
		CU_ASSERT(!spdk_bit_array_get(ba, i));
	}

	spdk_bit_array_free(&ba);
}

static void
test_mask_clear(void)
{
	struct spdk_bit_array *ba;
	uint32_t i;

	ba = spdk_bit_array_create(TEST_BITS_NUM);

	for (i = 0; i < TEST_BITS_NUM; i++) {
		spdk_bit_array_set(ba, i);
	}

	spdk_bit_array_clear_mask(ba);

	for (i = 0; i < TEST_BITS_NUM; i++) {
		CU_ASSERT(!spdk_bit_array_get(ba, i));
	}

	spdk_bit_array_free(&ba);
}

int
main(int argc, char **argv)
{
@@ -311,7 +378,9 @@ main(int argc, char **argv)
		CU_add_test(suite, "test_find", test_find) == NULL ||
		CU_add_test(suite, "test_resize", test_resize) == NULL ||
		CU_add_test(suite, "test_errors", test_errors) == NULL ||
		CU_add_test(suite, "test_count", test_count) == NULL) {
		CU_add_test(suite, "test_count", test_count) == NULL ||
		CU_add_test(suite, "test_mask_store_load", test_mask_store_load) == NULL ||
		CU_add_test(suite, "test_mask_clear", test_mask_clear) == NULL) {
		CU_cleanup_registry();
		return CU_get_error();
	}