diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2025-10-02 08:57:03 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2025-10-02 08:57:03 -0700 |
commit | 77633c77eee37ddc160493a4cf6070c166f47dc0 (patch) | |
tree | 75682cdef2ffdd34057a3e05a0aa55aba12298f9 /lib | |
parent | d7a018eb761f44f1f48667540185d025354f33b6 (diff) | |
parent | 2cdae413cd3ee6aad782cf4bce8c10fdb0f0657c (diff) |
Merge tag 'bitmap-for-6.18' of https://github.com/norov/linux
Pull bitmap updates from Yury Norov:
- FIELD_PREP_WM16() consolidation (Nicolas)
- bitmaps for Rust (Burak)
- __fls() fix for arc (Kees)
* tag 'bitmap-for-6.18' of https://github.com/norov/linux: (25 commits)
rust: add dynamic ID pool abstraction for bitmap
rust: add find_bit_benchmark_rust module.
rust: add bitmap API.
rust: add bindings for bitops.h
rust: add bindings for bitmap.h
phy: rockchip-pcie: switch to FIELD_PREP_WM16 macro
clk: sp7021: switch to FIELD_PREP_WM16 macro
PCI: dw-rockchip: Switch to FIELD_PREP_WM16 macro
PCI: rockchip: Switch to FIELD_PREP_WM16* macros
net: stmmac: dwmac-rk: switch to FIELD_PREP_WM16 macro
ASoC: rockchip: i2s-tdm: switch to FIELD_PREP_WM16_CONST macro
drm/rockchip: dw_hdmi: switch to FIELD_PREP_WM16* macros
phy: rockchip-usb: switch to FIELD_PREP_WM16 macro
drm/rockchip: inno-hdmi: switch to FIELD_PREP_WM16 macro
drm/rockchip: dw_hdmi_qp: switch to FIELD_PREP_WM16 macro
phy: rockchip-samsung-dcphy: switch to FIELD_PREP_WM16 macro
drm/rockchip: vop2: switch to FIELD_PREP_WM16 macro
drm/rockchip: dsi: switch to FIELD_PREP_WM16* macros
phy: rockchip-emmc: switch to FIELD_PREP_WM16 macro
drm/rockchip: lvds: switch to FIELD_PREP_WM16 macro
...
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig.debug | 13 | ||||
-rw-r--r-- | lib/Makefile | 1 | ||||
-rw-r--r-- | lib/find_bit_benchmark_rust.rs | 104 |
3 files changed, 118 insertions, 0 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index fd14468e1b03..cab4c7b27e54 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2621,6 +2621,19 @@ config FIND_BIT_BENCHMARK If unsure, say N. +config FIND_BIT_BENCHMARK_RUST + tristate "Test find_bit functions in Rust" + depends on RUST + help + This builds the "find_bit_benchmark_rust" module. It is a micro + benchmark that measures the performance of Rust functions that + correspond to the find_*_bit() operations in C. It follows the + FIND_BIT_BENCHMARK closely but will in general not yield same + numbers due to extra bounds checks and overhead of foreign + function calls. + + 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 15a03f4c16e2..1ab2c4be3b66 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -62,6 +62,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_FIND_BIT_BENCHMARK_RUST) += find_bit_benchmark_rust.o obj-$(CONFIG_TEST_BPF) += test_bpf.o test_dhry-objs := dhry_1.o dhry_2.o dhry_run.o obj-$(CONFIG_TEST_DHRY) += test_dhry.o diff --git a/lib/find_bit_benchmark_rust.rs b/lib/find_bit_benchmark_rust.rs new file mode 100644 index 000000000000..6bdc51de2f30 --- /dev/null +++ b/lib/find_bit_benchmark_rust.rs @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: GPL-2.0 +//! Benchmark for find_bit-like methods in Bitmap Rust API. + +use kernel::alloc::flags::GFP_KERNEL; +use kernel::bindings; +use kernel::bitmap::BitmapVec; +use kernel::error::{code, Result}; +use kernel::prelude::module; +use kernel::time::{Instant, Monotonic}; +use kernel::ThisModule; +use kernel::{pr_cont, pr_err}; + +const BITMAP_LEN: usize = 4096 * 8 * 10; +// Reciprocal of the fraction of bits that are set in sparse bitmap. +const SPARSENESS: usize = 500; + +/// Test module that benchmarks performance of traversing bitmaps. +struct Benchmark(); + +fn test_next_bit(bitmap: &BitmapVec) { + let time = Instant::<Monotonic>::now(); + let mut cnt = 0; + let mut i = 0; + + while let Some(index) = bitmap.next_bit(i) { + cnt += 1; + i = index + 1; + // CONFIG_RUST_BITMAP_HARDENED enforces strict bounds. + if i == BITMAP_LEN { + break; + } + } + + let delta = time.elapsed(); + pr_cont!( + "\nnext_bit: {:18} ns, {:6} iterations", + delta.as_nanos(), + cnt + ); +} + +fn test_next_zero_bit(bitmap: &BitmapVec) { + let time = Instant::<Monotonic>::now(); + let mut cnt = 0; + let mut i = 0; + + while let Some(index) = bitmap.next_zero_bit(i) { + cnt += 1; + i = index + 1; + // CONFIG_RUST_BITMAP_HARDENED enforces strict bounds. + if i == BITMAP_LEN { + break; + } + } + + let delta = time.elapsed(); + pr_cont!( + "\nnext_zero_bit: {:18} ns, {:6} iterations", + delta.as_nanos(), + cnt + ); +} + +fn find_bit_test() { + pr_err!("Benchmark"); + pr_cont!("\nStart testing find_bit() Rust with random-filled bitmap"); + + let mut bitmap = BitmapVec::new(BITMAP_LEN, GFP_KERNEL).expect("alloc bitmap failed"); + bitmap.fill_random(); + + test_next_bit(&bitmap); + test_next_zero_bit(&bitmap); + + pr_cont!("\nStart testing find_bit() Rust with sparse bitmap"); + + let mut bitmap = BitmapVec::new(BITMAP_LEN, GFP_KERNEL).expect("alloc sparse bitmap failed"); + let nbits = BITMAP_LEN / SPARSENESS; + for _i in 0..nbits { + // SAFETY: __get_random_u32_below is safe to call with any u32 argument. + let bit = + unsafe { bindings::__get_random_u32_below(BITMAP_LEN.try_into().unwrap()) as usize }; + bitmap.set_bit(bit); + } + + test_next_bit(&bitmap); + test_next_zero_bit(&bitmap); + pr_cont!("\n"); +} + +impl kernel::Module for Benchmark { + fn init(_module: &'static ThisModule) -> Result<Self> { + find_bit_test(); + // Return error so test module can be inserted again without rmmod. + Err(code::EINVAL) + } +} + +module! { + type: Benchmark, + name: "find_bit_benchmark_rust", + authors: ["Burak Emir <bqe@google.com>"], + description: "Module with benchmark for bitmap Rust API", + license: "GPL v2", +} |