strat9_kernel/ostd/
util.rs1#![deny(unsafe_code)]
9
10extern crate alloc;
11
12use alloc::vec::Vec;
13
14#[derive(Debug, Clone)]
19pub struct IdSet {
20 low_bits: u64,
22 high_ids: Vec<usize>,
24}
25
26impl IdSet {
27 pub const fn new() -> Self {
29 Self {
30 low_bits: 0,
31 high_ids: Vec::new(),
32 }
33 }
34
35 pub fn all(max: usize) -> Self {
37 let mut set = Self::new();
38 for i in 0..=max {
39 set.insert(i);
40 }
41 set
42 }
43
44 pub fn insert(&mut self, id: usize) {
46 if id < 64 {
47 self.low_bits |= 1 << id;
48 } else {
49 if !self.high_ids.contains(&id) {
50 self.high_ids.push(id);
51 }
52 }
53 }
54
55 pub fn remove(&mut self, id: usize) {
57 if id < 64 {
58 self.low_bits &= !(1 << id);
59 } else {
60 self.high_ids.retain(|&x| x != id);
61 }
62 }
63
64 pub fn contains(&self, id: usize) -> bool {
66 if id < 64 {
67 (self.low_bits & (1 << id)) != 0
68 } else {
69 self.high_ids.contains(&id)
70 }
71 }
72
73 pub fn is_empty(&self) -> bool {
75 self.low_bits == 0 && self.high_ids.is_empty()
76 }
77
78 pub fn len(&self) -> usize {
80 self.low_bits.count_ones() as usize + self.high_ids.len()
81 }
82
83 pub fn clear(&mut self) {
85 self.low_bits = 0;
86 self.high_ids.clear();
87 }
88
89 pub fn iter(&self) -> IdSetIter<'_> {
91 IdSetIter {
92 low_bits: self.low_bits,
93 low_index: 0,
94 high_iter: self.high_ids.iter(),
95 }
96 }
97}
98
99impl Default for IdSet {
100 fn default() -> Self {
102 Self::new()
103 }
104}
105
106pub struct IdSetIter<'a> {
108 low_bits: u64,
109 low_index: usize,
110 high_iter: core::slice::Iter<'a, usize>,
111}
112
113impl<'a> Iterator for IdSetIter<'a> {
114 type Item = usize;
115
116 fn next(&mut self) -> Option<Self::Item> {
118 while self.low_index < 64 {
120 if (self.low_bits & (1 << self.low_index)) != 0 {
121 let id = self.low_index;
122 self.low_index += 1;
123 return Some(id);
124 }
125 self.low_index += 1;
126 }
127
128 self.high_iter.next().copied()
130 }
131}
132
133pub type CpuSet = IdSet;
135
136pub mod bits {
138 #[inline]
140 pub const fn align_up(value: usize, align: usize) -> usize {
141 (value + align - 1) & !(align - 1)
142 }
143
144 #[inline]
146 pub const fn align_down(value: usize, align: usize) -> usize {
147 value & !(align - 1)
148 }
149
150 #[inline]
152 pub const fn is_aligned(value: usize, align: usize) -> bool {
153 value & (align - 1) == 0
154 }
155
156 #[inline]
158 pub const fn leading_zeros(x: u64) -> u32 {
159 x.leading_zeros()
160 }
161
162 #[inline]
164 pub const fn trailing_zeros(x: u64) -> u32 {
165 x.trailing_zeros()
166 }
167
168 #[inline]
170 pub const fn count_ones(x: u64) -> u32 {
171 x.count_ones()
172 }
173
174 #[inline]
176 pub const fn next_power_of_two(mut x: usize) -> usize {
177 if x == 0 {
178 return 1;
179 }
180 x -= 1;
181 x |= x >> 1;
182 x |= x >> 2;
183 x |= x >> 4;
184 x |= x >> 8;
185 x |= x >> 16;
186 #[cfg(target_pointer_width = "64")]
187 {
188 x |= x >> 32;
189 }
190 x + 1
191 }
192
193 #[inline]
195 pub const fn log2_floor(x: usize) -> u32 {
196 if x == 0 {
197 return 0;
198 }
199 31 - x.leading_zeros()
200 }
201
202 #[inline]
204 pub const fn log2_ceil(x: usize) -> u32 {
205 if x == 0 {
206 return 0;
207 }
208 let floor = log2_floor(x);
209 if x.is_power_of_two() {
210 floor
211 } else {
212 floor + 1
213 }
214 }
215}
216
217#[inline]
219pub const fn round_up(value: usize, align: usize) -> usize {
220 bits::align_up(value, align)
221}
222
223#[inline]
225pub const fn round_down(value: usize, align: usize) -> usize {
226 bits::align_down(value, align)
227}
228
229#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
230pub enum Error {
231 #[error("out of memory")]
232 OutOfMemory,
233 #[error("invalid argument")]
234 InvalidArgument,
235 #[error("not found")]
236 NotFound,
237 #[error("already exists")]
238 AlreadyExists,
239 #[error("permission denied")]
240 PermissionDenied,
241 #[error("busy")]
242 Busy,
243 #[error("page fault")]
244 PageFault,
245 #[error("architecture error: {0}")]
246 ArchError(&'static str),
247}
248
249pub type Result<T> = core::result::Result<T, Error>;