Add test module to test find_last_zero_bit and find_each_*_bit_revserse. Signed-off-by: Levi Yun <ppbuk5246@xxxxxxxxx> --- lib/Kconfig.debug | 8 ++ lib/Makefile | 1 + lib/test_find_last_bit.c | 235 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 244 insertions(+) create mode 100644 lib/test_find_last_bit.c diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index c789b39ed527..481e366d0e82 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2188,6 +2188,14 @@ config FIND_BIT_BENCHMARK If unsure, say N. +config TEST_FIND_LAST_BIT + tristate "Test find_last_*_bit functions" + help + This builds the "test_find_last_bit" module that measure find_last_*_bit() + functions performance. + + If unsure, say N. + config TEST_FIRMWARE tristate "Test firmware loading via userspace interface" depends on FW_LOADER diff --git a/lib/Makefile b/lib/Makefile index ce45af50983a..310719df6207 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -58,6 +58,7 @@ obj-y += hexdump.o obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o obj-y += kstrtox.o obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o +obj-$(CONFIG_TEST_FIND_LAST_BIT) += test_find_last_bit.o obj-$(CONFIG_TEST_BPF) += test_bpf.o obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o obj-$(CONFIG_TEST_BITOPS) += test_bitops.o diff --git a/lib/test_find_last_bit.c b/lib/test_find_last_bit.c new file mode 100644 index 000000000000..579866c476d1 --- /dev/null +++ b/lib/test_find_last_bit.c @@ -0,0 +1,235 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Test for find_prev_*_bit functions. + * + * Copyright (c) 2020 Levi Yun. + */ + +#include <linux/bitops.h> +#include <linux/kernel.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/printk.h> +#include <linux/random.h> + + +#define BITMAP_LEN (4096UL * 8 * 10) +#define BITMAP_LAST_IDX BITMAP_LEN - 1 + + +static DECLARE_BITMAP(zero_bitmap, BITMAP_LEN) __initdata; +static DECLARE_BITMAP(full_bitmap, BITMAP_LEN) __initdata; + +static int __init test_for_each_clear_rev(const void *bitmap, unsigned long len) +{ + unsigned long cur; + unsigned long expect = BITMAP_LAST_IDX; + + pr_err("[%s:%d] Start test clear full iteration\n", __func__, __LINE__); + + len = BITMAP_LEN; + + for_each_clear_bit_reverse(cur, bitmap, len) { + if (cur != expect) { + pr_err("[%s:%d] full iteration fail!, expect: %lu, cur: %lu\n", + __func__, __LINE__, expect, cur); + + return 0; + } + + expect--; + } + + len = BITMAP_LEN; + + cur = len / 3; + expect = cur; + pr_err("[%s:%d] Success\n", __func__, __LINE__); + + pr_err("[%s:%d] Start test clear iteration with starting point\n", __func__, __LINE__); + for_each_clear_bit_from_reverse(cur, bitmap, len) { + if (cur != expect) { + pr_err("[%s:%d] full iteration fail!, expect: %lu, cur: %lu\n", + __func__, __LINE__, expect, cur); + + return 0; + } + + expect--; + } + + pr_err("[%s:%d] Success\n", __func__, __LINE__); + + return 0; +} + +static int __init test_for_each_set_rev(const void *bitmap, unsigned long len) +{ + unsigned long cur; + unsigned long expect = BITMAP_LAST_IDX; + + len = BITMAP_LEN; + pr_err("[%s:%d] Start test set full iteration\n", __func__, __LINE__); + for_each_set_bit_reverse(cur, bitmap, len) { + if (cur != expect) { + pr_err("[%s:%d] full iteration fail!, expect: %lu, cur: %lu\n", + __func__, __LINE__, expect, cur); + + return 0; + } + + expect--; + } + pr_err("[%s:%d] Success\n", __func__, __LINE__); + + + len = BITMAP_LEN; + cur = len / 3; + expect = cur; + + pr_err("[%s:%d] Start test set iteration with starting point\n", __func__, __LINE__); + for_each_set_bit_from_reverse(cur, bitmap, len) { + if (cur != expect) { + pr_err("[%s:%d] full iteration fail!, expect: %lu, cur: %lu\n", + __func__, __LINE__, expect, cur); + + return 0; + } + + expect--; + } + pr_err("[%s:%d] Success\n", __func__, __LINE__); + + return 0; +} + +static int __init test_find_last_bit_clear_middle(void *bitmap) +{ + unsigned long idx; + unsigned long len = 4096; + + pr_err("[%s] Start test\n", __func__); + + clear_bit(1, bitmap); + clear_bit(65, bitmap); + clear_bit(136, bitmap); + clear_bit(4095, bitmap); + + idx = find_last_zero_bit(bitmap, len); + if (idx != 4095) { + pr_err("[%s] Fail! expect: %u, idx: %lu\n", __func__, 4095, idx); + + goto teardown; + } + + idx = find_last_zero_bit(bitmap, idx); + if (idx != 136) { + pr_err("[%s] Fail! expect: %u, idx: %lu\n", __func__, 127, idx); + + goto teardown; + } + + idx = find_last_zero_bit(bitmap, idx); + if (idx != 65) { + pr_err("[%s] Fail! expect: %u, idx: %lu\n", __func__, 65, idx); + + goto teardown; + } + + idx = find_last_zero_bit(bitmap, idx); + if (idx != 1) { + pr_err("[%s] Fail! expect: %u, idx: %lu\n", __func__, 1, idx); + + goto teardown; + } + + idx = find_last_zero_bit(bitmap, idx); + if (idx != 1) { + pr_err("[%s] Fail (find no bit clear)! expect: %u, idx: %lu\n", __func__, 1, idx); + + goto teardown; + } + + pr_err("[%s] Success\n", __func__); + +teardown: + set_bit(4095, bitmap); + set_bit(136, bitmap); + set_bit(65, bitmap); + set_bit(1, bitmap); + + return 0; +} + +static int __init test_find_last_zero_bit(void *bitmap, unsigned long len) +{ + unsigned long idx; + pr_err("[%s] Start test\n", __func__); + + idx = find_last_zero_bit(bitmap, len); + if (idx != len) { + pr_err("[%s] Fail! expect: %lu, idx: %lu\n", __func__, len, idx); + + goto teardown; + } + + clear_bit(4095, bitmap); + clear_bit(2032, bitmap); + clear_bit(0, bitmap); + + idx = find_last_zero_bit(bitmap, len); + if (idx != 4095) { + pr_err("[%s] Fail! expect: %u, idx: %lu\n", __func__, 4095, idx); + + goto teardown; + } + + idx = find_last_zero_bit(bitmap, idx); + if (idx != 2032) { + pr_err("[%s] Fail! expect: %u, idx: %lu\n", __func__, 2032, idx); + + goto teardown; + } + + idx = find_last_zero_bit(bitmap, idx); + if (idx != 0) { + pr_err("[%s] Fail! expect: %u, idx: %lu\n", __func__, 0, idx); + + goto teardown; + } + + pr_err("[%s] Success\n", __func__); + +teardown: + set_bit(0, bitmap); + set_bit(2032, bitmap); + set_bit(4095, bitmap); + + return 0; +} + +static int __init find_last_bit_test(void) +{ + bitmap_zero(zero_bitmap, BITMAP_LEN); + bitmap_fill(full_bitmap, BITMAP_LEN); + pr_err("\nStart testing find_last_*_bit()\n"); + + test_for_each_clear_rev(zero_bitmap, BITMAP_LEN); + test_for_each_set_rev(full_bitmap, BITMAP_LEN); + test_find_last_bit_clear_middle(full_bitmap); + test_find_last_zero_bit(full_bitmap, BITMAP_LEN); + + pr_err("\nFinish testing find_last_*_bit()\n"); + + /* + * Everything is OK. Return error just to let user run benchmark + * again without annoying rmmod. + */ + return -EINVAL; +} + + +module_init(find_last_bit_test); + + +MODULE_LICENSE("GPL"); -- 2.27.0