Messages in this thread Patch in this message |  | | From | Mitchell Levy <> | | Date | Fri, 10 Apr 2026 14:35:31 -0700 | | Subject | [PATCH v5 1/8] rust: cpumask: Add a `Cpumask` iterator |
| |
Add an iterator for `Cpumask` making use of C's `cpumask_next`.
Acked-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Mitchell Levy <levymitchell0@gmail.com> --- rust/helpers/cpumask.c | 6 ++++++ rust/kernel/cpumask.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/rust/helpers/cpumask.c b/rust/helpers/cpumask.c index 5deced5b975e..76990e14dfdd 100644 --- a/rust/helpers/cpumask.c +++ b/rust/helpers/cpumask.c @@ -50,6 +50,12 @@ bool rust_helper_cpumask_full(struct cpumask *srcp) return cpumask_full(srcp); } +__rust_helper +unsigned int rust_helper_cpumask_next(int n, struct cpumask *srcp) +{ + return cpumask_next(n, srcp); +} + __rust_helper unsigned int rust_helper_cpumask_weight(struct cpumask *srcp) { diff --git a/rust/kernel/cpumask.rs b/rust/kernel/cpumask.rs index 44bb36636ee3..b74a3fccf4b4 100644 --- a/rust/kernel/cpumask.rs +++ b/rust/kernel/cpumask.rs @@ -14,7 +14,10 @@ #[cfg(CONFIG_CPUMASK_OFFSTACK)] use core::ptr::{self, NonNull}; -use core::ops::{Deref, DerefMut}; +use core::{ + iter::FusedIterator, + ops::{Deref, DerefMut}, +}; /// A CPU Mask. /// @@ -161,6 +164,52 @@ pub fn copy(&self, dstp: &mut Self) { } } +/// Iterator for a `Cpumask`. +pub struct CpumaskIter<'a> { + mask: &'a Cpumask, + /// [`None`] if no bits have been returned yet, or the index of the last bit returned by the + /// iterator. Equal to [`kernel::cpu::nr_cpu_ids()`] when the iterator has been exhausted. + last: Option<u32>, +} + +impl<'a> CpumaskIter<'a> { + /// Creates a new `CpumaskIter` for the given `Cpumask`. + fn new(mask: &'a Cpumask) -> CpumaskIter<'a> { + Self { mask, last: None } + } +} + +impl<'a> Iterator for CpumaskIter<'a> { + type Item = CpuId; + + fn next(&mut self) -> Option<Self::Item> { + // cpumask_next WARNs if the first argument is >= nr_cpu_ids when CONFIG_DEBUG_PER_CPU_MAPS + // is set. So, early out in that case + if let Some(last) = self.last { + if last >= kernel::cpu::nr_cpu_ids() { + return None; + } + } + + // SAFETY: By the type invariant, `self.mask.as_raw` is a `struct cpumask *`. + let next = unsafe { + bindings::cpumask_next(self.last.map_or(-1, |l| l as i32), self.mask.as_raw()) + }; + + self.last = Some(next); + CpuId::from_u32(next) + } +} + +impl<'a> FusedIterator for CpumaskIter<'a> {} + +impl Cpumask { + /// Returns an iterator over the set bits in the cpumask. + pub fn iter(&self) -> CpumaskIter<'_> { + CpumaskIter::new(self) + } +} + /// A CPU Mask pointer. /// /// Rust abstraction for the C `struct cpumask_var_t`. -- 2.34.1
|  |