strat9_kernel/memory/
mapping_index.rs1use alloc::collections::BTreeMap;
4
5use smallvec::SmallVec;
6use x86_64::VirtAddr;
7
8use crate::{
9 capability::CapId, memory::address_space::VmaPageSize, process::task::Pid, sync::SpinLock,
10};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14pub struct MappingRef {
15 pub pid: Pid,
17 pub vaddr: VirtAddr,
19 pub page_size: VmaPageSize,
21}
22
23pub struct MappingIndex {
36 index: SpinLock<BTreeMap<CapId, SmallVec<[MappingRef; 8]>>>,
37}
38
39impl MappingIndex {
40 pub fn new() -> Self {
42 Self {
43 index: SpinLock::new(BTreeMap::new()),
44 }
45 }
46
47 pub fn register(&self, cap_id: CapId, mapping: MappingRef) {
49 let mut index = self.index.lock();
50 let mappings = index.entry(cap_id).or_default();
51 if !mappings.iter().any(|existing| *existing == mapping) {
52 let was_spilled = mappings.spilled();
53 mappings.push(mapping);
54 debug_assert!(
55 !mappings.spilled() || was_spilled,
56 "mapping_index: SmallVec spilled to heap for cap={:?} : consider growing inline capacity",
57 cap_id,
58 );
59 }
60 }
61
62 pub fn unregister(&self, cap_id: CapId, pid: Pid, vaddr: VirtAddr) {
64 let mut index = self.index.lock();
65 let should_remove = if let Some(mappings) = index.get_mut(&cap_id) {
66 mappings.retain(|mapping| !(mapping.pid == pid && mapping.vaddr == vaddr));
67 mappings.is_empty()
68 } else {
69 false
70 };
71 if should_remove {
72 index.remove(&cap_id);
73 }
74 }
75
76 pub fn lookup(&self, cap_id: CapId) -> SmallVec<[MappingRef; 8]> {
78 self.index.lock().get(&cap_id).cloned().unwrap_or_default()
79 }
80
81 pub fn remove_all(&self, cap_id: CapId) -> SmallVec<[MappingRef; 8]> {
83 self.index.lock().remove(&cap_id).unwrap_or_default()
84 }
85}
86
87impl Default for MappingIndex {
88 fn default() -> Self {
90 Self::new()
91 }
92}