diff --git a/kernel/src/main.rs b/kernel/src/main.rs index c25bdd000..0277374ef 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -26,6 +26,7 @@ mod platform; mod server; mod services; mod syscall; +mod utils; #[cfg(feature = "swap")] mod swap; diff --git a/kernel/src/utils.rs b/kernel/src/utils.rs new file mode 100644 index 000000000..f867004ae --- /dev/null +++ b/kernel/src/utils.rs @@ -0,0 +1,49 @@ +/// Amount of stack-allocated space we allow for a MinSet pass. Increasing this +/// uses more memory, but reduces stack footprint. The current setting of 64 +/// should use about 256 bytes of stack, which comfortably fits within the one-page +/// stack limit of the kernel. +pub const RENORM_PASS_SIZE: usize = 64; + +/// A helper for assisting with renormalization of the epoch. This uses a small, +/// stack-allocated scratch space, limited by the size of `PASS_SIZE`, to find +/// a set of smallest values within a larger list. We can then use that set to +/// renormalize (e.g. compact down) those values to the smallest possible values, +/// while preserving duplicates and ordering within the overall list. +/// +/// `dead_code` is allowed because we want this to be runnable in the set of +/// tests without having to enable the `swap` flag. +#[allow(dead_code)] +pub struct MinSet { + /// Set is ordered from lowest to highest, once fully initialized + pub set: [u32; RENORM_PASS_SIZE], +} +#[allow(dead_code)] +impl MinSet { + pub fn new() -> Self { Self { set: [u32::MAX; RENORM_PASS_SIZE] } } + + pub fn insert(&mut self, item: u32) { + // search from lowest to highest for a duplicate + for s in self.set.iter_mut() { + if *s == item { + return; + } + } + // it's not a duplicate + // items are unique and sorted, find a spot to insert, if it deserves a place + if item < self.set[RENORM_PASS_SIZE - 1] { + self.set[RENORM_PASS_SIZE - 1] = item; + self.set.sort_unstable(); + } + } + + pub fn max(&self) -> u32 { self.set[RENORM_PASS_SIZE - 1] } + + pub fn index_of(&self, data: u32) -> Option { + for (i, &d) in self.set.iter().enumerate() { + if d == data { + return Some(i); + } + } + None + } +}