Nothing to see here, move along
at main 211 lines 6.2 kB view raw
1use crate::error::KernelError; 2use crate::mem::addr; 3use crate::sync::IrqMutex; 4use crate::types::{Generation, ObjPhys}; 5use lancer_core::header::KernelObjectHeader; 6use lancer_core::object_layout::KernelObject; 7use lancer_core::object_tag::ObjectTag; 8use x86_64::PhysAddr; 9 10pub struct ObjectPool { 11 generation_counter: u32, 12 #[cfg(lancer_test)] 13 active_count: u32, 14} 15 16impl ObjectPool { 17 const fn new() -> Self { 18 Self { 19 generation_counter: 0, 20 #[cfg(lancer_test)] 21 active_count: 0, 22 } 23 } 24 25 pub fn init(&mut self) { 26 self.generation_counter = 0; 27 #[cfg(lancer_test)] 28 { 29 self.active_count = 0; 30 } 31 } 32 33 #[cfg(lancer_test)] 34 pub fn active_count(&self) -> u32 { 35 self.active_count 36 } 37 38 pub fn register_object( 39 &mut self, 40 phys: u64, 41 _tag: ObjectTag, 42 ) -> Result<(ObjPhys, Generation), KernelError> { 43 debug_assert!( 44 phys.is_multiple_of(core::mem::align_of::<KernelObjectHeader>() as u64), 45 "register_object: misaligned phys {phys:#x}" 46 ); 47 self.generation_counter = self.generation_counter.wrapping_add(1); 48 let generation = self.generation_counter; 49 unsafe { 50 let hdr_ptr = 51 addr::phys_to_virt(PhysAddr::new(phys)).as_mut_ptr::<KernelObjectHeader>(); 52 (*hdr_ptr).generation = generation; 53 (*hdr_ptr).ref_count = 1; 54 } 55 #[cfg(lancer_test)] 56 { 57 self.active_count += 1; 58 } 59 Ok((ObjPhys::new(phys), Generation::new(generation))) 60 } 61 62 fn read_header(&self, phys: ObjPhys) -> &'static KernelObjectHeader { 63 unsafe { 64 &*(addr::phys_to_virt(PhysAddr::new(phys.raw())).as_ptr::<KernelObjectHeader>()) 65 } 66 } 67 68 fn write_header(&mut self, phys: ObjPhys) -> &'static mut KernelObjectHeader { 69 unsafe { 70 &mut *(addr::phys_to_virt(PhysAddr::new(phys.raw())) 71 .as_mut_ptr::<KernelObjectHeader>()) 72 } 73 } 74 75 fn validate_generation( 76 &self, 77 phys: ObjPhys, 78 generation: Generation, 79 ) -> Result<(), KernelError> { 80 let hdr = self.read_header(phys); 81 match hdr.generation != generation.raw() { 82 true => Err(KernelError::StaleGeneration), 83 false => match hdr.ref_count { 84 0 => Err(KernelError::InvalidObject), 85 _ => Ok(()), 86 }, 87 } 88 } 89 90 pub fn inc_ref(&mut self, phys: ObjPhys, generation: Generation) -> Result<(), KernelError> { 91 self.validate_generation(phys, generation)?; 92 let hdr = self.write_header(phys); 93 hdr.inc_ref().ok_or(KernelError::ResourceExhausted)?; 94 Ok(()) 95 } 96 97 pub fn get_tag( 98 &self, 99 phys: ObjPhys, 100 generation: Generation, 101 ) -> Result<ObjectTag, KernelError> { 102 self.validate_generation(phys, generation)?; 103 let hdr = self.read_header(phys); 104 ObjectTag::try_from(hdr.tag).map_err(|_| KernelError::InvalidType) 105 } 106 107 pub fn read_as<T: KernelObject + 'static>( 108 &self, 109 phys: ObjPhys, 110 generation: Generation, 111 ) -> Result<&T, KernelError> { 112 unsafe { super::accessor::read_object::<T>(PhysAddr::new(phys.raw()), generation.raw()) } 113 } 114 115 pub fn write_as<T: KernelObject>( 116 &mut self, 117 phys: ObjPhys, 118 generation: Generation, 119 ) -> Result<&mut T, KernelError> { 120 let ptr = unsafe { 121 super::accessor::write_object::<T>(PhysAddr::new(phys.raw()), generation.raw())? 122 }; 123 Ok(unsafe { &mut *ptr }) 124 } 125 126 pub fn dec_ref_phys( 127 &mut self, 128 phys: ObjPhys, 129 generation: Generation, 130 ) -> Option<(u64, ObjectTag)> { 131 let hdr = self.read_header(phys); 132 match hdr.generation != generation.raw() || hdr.ref_count == 0 { 133 true => return None, 134 false => {} 135 } 136 137 let tag_byte = hdr.tag; 138 let tag = ObjectTag::try_from(tag_byte).ok()?; 139 140 let hdr = self.write_header(phys); 141 let new_rc = hdr.dec_ref(); 142 match new_rc { 143 0 => { 144 hdr.bump_generation(); 145 #[cfg(lancer_test)] 146 { 147 self.active_count = self.active_count.saturating_sub(1); 148 } 149 Some((phys.raw(), tag)) 150 } 151 _ => None, 152 } 153 } 154 155 pub fn free_phys( 156 &mut self, 157 phys: ObjPhys, 158 generation: Generation, 159 ) -> Result<Option<(u64, ObjectTag)>, KernelError> { 160 let hdr = self.read_header(phys); 161 match hdr.generation != generation.raw() { 162 true => return Err(KernelError::StaleGeneration), 163 false => {} 164 } 165 match hdr.ref_count { 166 0 => return Ok(None), 167 _ => {} 168 } 169 170 let tag = ObjectTag::try_from(hdr.tag).ok().map(|t| (phys.raw(), t)); 171 let hdr = self.write_header(phys); 172 hdr.invalidate(); 173 #[cfg(lancer_test)] 174 { 175 self.active_count = self.active_count.saturating_sub(1); 176 } 177 Ok(tag) 178 } 179 180 pub fn revoke_phys( 181 &mut self, 182 phys: ObjPhys, 183 generation: Generation, 184 ) -> Result<(Generation, Option<(u64, ObjectTag)>), KernelError> { 185 let hdr = self.read_header(phys); 186 match hdr.generation != generation.raw() || hdr.ref_count == 0 { 187 true => return Err(KernelError::StaleGeneration), 188 false => {} 189 } 190 191 let tag = ObjectTag::try_from(hdr.tag).ok().map(|t| (phys.raw(), t)); 192 let hdr = self.write_header(phys); 193 hdr.invalidate(); 194 let new_gen = hdr.generation; 195 #[cfg(lancer_test)] 196 { 197 self.active_count = self.active_count.saturating_sub(1); 198 } 199 Ok((Generation::new(new_gen), tag)) 200 } 201 202 pub fn generation_of(&self, phys: ObjPhys) -> Option<u32> { 203 let hdr = self.read_header(phys); 204 match hdr.ref_count > 0 { 205 true => Some(hdr.generation), 206 false => None, 207 } 208 } 209} 210 211pub static POOL: IrqMutex<ObjectPool, 1> = IrqMutex::new(ObjectPool::new());