Skip to content

Commit cf9c085

Browse files
committed
cpumask: add functions similar to for_each_*_cpu
This commit adds three iterators which returns the CPU index. They are PossibleCpusIndexIter, OnlineCpusIndexIter, and PresentCpusIndexIter corresponding to C macros for_each_possible_cpu, for_each_online_cpu, and for_each_present_cpu exclusively. Signed-off-by: Li Hongyu <[email protected]>
1 parent df9024b commit cf9c085

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

rust/kernel/cpumask.rs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Cpumask variables and related functions.
4+
//!
5+
//! C header: [`include/linux/cpumask.h`](../../../../include/linux/cpumask.h).
6+
7+
use crate::bindings;
8+
use core::iter::Iterator;
9+
10+
/// An possible CPU index iterator.
11+
///
12+
/// This iterator has a similar abilitiy to the kernel's macro `for_each_possible_cpu`.
13+
pub struct PossibleCpusIndexIter {
14+
index: i32,
15+
}
16+
17+
/// An online CPU index iterator.
18+
///
19+
/// This iterator has a similar abilitiy to the kernel's macro `for_each_online_cpu`.
20+
pub struct OnlineCpusIndexIter {
21+
index: i32,
22+
}
23+
24+
/// An present CPU index iterator.
25+
///
26+
/// This iterator has a similar abilitiy to the kernel's macro `for_each_present_cpu`.
27+
pub struct PresentCpusIndexIter {
28+
index: i32,
29+
}
30+
31+
impl Iterator for PossibleCpusIndexIter {
32+
type Item = u32;
33+
34+
fn next(&mut self) -> Option<u32> {
35+
let next_cpu_id =
36+
unsafe { bindings::cpumask_next(self.index, &bindings::__cpu_possible_mask) };
37+
// When [`bindings::cpumask_next`] can not find further CPUs set in the
38+
// [`bindings::__cpu_possible_mask`], it returns a value >= [`bindings::nr_cpu_ids`].
39+
if next_cpu_id >= unsafe { bindings::nr_cpu_ids } {
40+
return None;
41+
}
42+
self.index = next_cpu_id as i32;
43+
Some(next_cpu_id)
44+
}
45+
}
46+
47+
impl Iterator for OnlineCpusIndexIter {
48+
type Item = u32;
49+
50+
fn next(&mut self) -> Option<u32> {
51+
let next_cpu_id =
52+
unsafe { bindings::cpumask_next(self.index, &bindings::__cpu_online_mask) };
53+
// When [`bindings::cpumask_next`] can not find further CPUs set in the
54+
// [`bindings::__cpu_online_mask`], it returns a value >= [`bindings::nr_cpu_ids`].
55+
if next_cpu_id >= unsafe { bindings::nr_cpu_ids } {
56+
return None;
57+
}
58+
self.index = next_cpu_id as i32;
59+
Some(next_cpu_id)
60+
}
61+
}
62+
63+
impl Iterator for PresentCpusIndexIter {
64+
type Item = u32;
65+
66+
fn next(&mut self) -> Option<u32> {
67+
let next_cpu_id =
68+
unsafe { bindings::cpumask_next(self.index, &bindings::__cpu_present_mask) };
69+
// When [`bindings::cpumask_next`] can not find further CPUs set in the
70+
// [`bindings::__cpu_present_mask`], it returns a value >= [`bindings::nr_cpu_ids`].
71+
if next_cpu_id >= unsafe { bindings::nr_cpu_ids } {
72+
return None;
73+
}
74+
self.index = next_cpu_id as i32;
75+
Some(next_cpu_id)
76+
}
77+
}
78+
79+
/// Returns a [`PossibleCpusIndexIter`] that gives the possible CPU indexes.
80+
///
81+
/// # Examples
82+
///
83+
/// ```
84+
/// # use kernel::prelude::*;
85+
/// # use kernel::cpumask::possible_cpus;
86+
///
87+
/// fn example() {
88+
/// // This prints all the possible cpu indexes.
89+
/// for cpu in possible_cpus(){
90+
/// pr_info!("{}\n", cpu);
91+
/// }
92+
/// }
93+
/// ```
94+
pub fn possible_cpus() -> PossibleCpusIndexIter {
95+
// Initial index is set to -1. Since [`bindings::cpumask_next`] return the next set bit in a
96+
// [`bindings::__cpu_possible_mask`], the CPU index should begins from 0.
97+
PossibleCpusIndexIter { index: -1 }
98+
}
99+
100+
/// Returns a [`OnlineCpusIndexIter`] that gives the online CPU indexes.
101+
///
102+
/// # Examples
103+
///
104+
/// ```
105+
/// # use kernel::prelude::*;
106+
/// # use kernel::cpumask::online_cpus;
107+
///
108+
/// fn example() {
109+
/// // This prints all the online cpu indexes.
110+
/// for cpu in online_cpus(){
111+
/// pr_info!("{}\n", cpu);
112+
/// }
113+
/// }
114+
/// ```
115+
pub fn online_cpus() -> OnlineCpusIndexIter {
116+
// Initial index is set to -1. Since [`bindings::cpumask_next`] return the next set bit in a
117+
// [`bindings::__cpu_online_mask`], the CPU index should begins from 0.
118+
OnlineCpusIndexIter { index: -1 }
119+
}
120+
121+
/// Returns a [`PresentCpusIndexIter`] that gives the present CPU indexes.
122+
///
123+
/// # Examples
124+
///
125+
/// ```
126+
/// # use kernel::prelude::*;
127+
/// # use kernel::cpumask::present_cpus;
128+
///
129+
/// fn example() {
130+
/// // This prints all the present cpu indexes.
131+
/// for cpu in present_cpus(){
132+
/// pr_info!("{}\n", cpu);
133+
/// }
134+
/// }
135+
/// ```
136+
pub fn present_cpus() -> PresentCpusIndexIter {
137+
// Initial index is set to -1. Since [`bindings::cpumask_next`] return the next set bit in a
138+
// [`bindings::__cpu_present_mask`], the CPU index should begins from 0.
139+
PresentCpusIndexIter { index: -1 }
140+
}

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ pub mod platform;
9494
mod types;
9595
pub mod user_ptr;
9696

97+
pub mod cpumask;
9798
#[doc(hidden)]
9899
pub use build_error::build_error;
99100

0 commit comments

Comments
 (0)