1 #![no_std] 2 #![feature(const_refs_to_cell)] 3 #![feature(const_size_of_val)] 4 5 extern crate alloc; 6 use core::{fmt::Debug, mem::size_of_val}; 7 8 use alloc::format; 9 use kdepends::{memoffset::offset_of, thingbuf::StaticThingBuf}; 10 11 #[repr(C)] 12 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 13 pub struct AllocatorLog { 14 /// 日志的id 15 pub id: u64, 16 /// 日志类型 17 pub type_: AllocatorLogType, 18 /// 日志的时间 19 pub time: u64, 20 21 /// 日志的来源 22 pub source: LogSource, 23 24 /// 日志的来源pid 25 pub pid: Option<usize>, 26 27 pub checksum: u64, 28 } 29 30 impl AllocatorLog { 31 /// 创建一个日志 32 /// 33 /// ## 参数 34 /// 35 /// - `id`:日志的id 36 /// - `type_`:日志类型 37 /// - `source`:日志来源 38 /// - `pid`:日志来源的pid 39 /// - `time`:日志的时间 40 pub fn new( 41 id: u64, 42 type_: AllocatorLogType, 43 source: LogSource, 44 pid: Option<usize>, 45 time: u64, 46 ) -> Self { 47 let mut x = Self { 48 id, 49 type_, 50 time, 51 source, 52 pid, 53 checksum: 0, 54 }; 55 let checksum = Self::calculate_checksum(&x); 56 x.checksum = checksum; 57 return x; 58 } 59 60 pub const fn zeroed() -> Self { 61 return Self { 62 id: 0, 63 type_: AllocatorLogType::Undefined, 64 time: 0, 65 source: LogSource::Undefined, 66 pid: None, 67 checksum: 0, 68 }; 69 } 70 71 /// 计算日志的校验和 72 pub fn calculate_checksum(value: &Self) -> u64 { 73 let buf = unsafe { 74 core::slice::from_raw_parts( 75 value as *const _ as *const u8, 76 core::mem::size_of::<Self>() - core::mem::size_of::<u64>(), 77 ) 78 }; 79 let checksum = kdepends::crc::crc64::crc64_be(0, buf); 80 return checksum; 81 } 82 83 /// 验证日志的校验和 84 pub fn validate_checksum(&self) -> bool { 85 let checksum = Self::calculate_checksum(self); 86 return checksum == self.checksum; 87 } 88 89 /// 当前日志是否有效 90 pub fn is_valid(&self) -> bool { 91 if self.validate_checksum() == false { 92 return false; 93 } 94 95 if self.id == 0 { 96 return false; 97 } 98 99 return true; 100 } 101 } 102 103 impl PartialOrd for AllocatorLog { 104 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { 105 return self.id.partial_cmp(&other.id); 106 } 107 } 108 109 impl Ord for AllocatorLog { 110 fn cmp(&self, other: &Self) -> core::cmp::Ordering { 111 return self.id.cmp(&other.id); 112 } 113 } 114 115 /// 内存分配器日志类型 116 #[repr(C)] 117 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 118 pub enum AllocatorLogType { 119 Undefined, 120 Alloc(AllocLogItem), 121 AllocZeroed(AllocLogItem), 122 Free(AllocLogItem), 123 } 124 125 #[repr(C)] 126 #[derive(Copy, Clone, PartialEq, Eq)] 127 pub struct AllocLogItem { 128 pub layout: core::alloc::Layout, 129 pub vaddr: Option<usize>, 130 pub paddr: Option<usize>, 131 } 132 133 impl AllocLogItem { 134 pub fn new(layout: core::alloc::Layout, vaddr: Option<usize>, paddr: Option<usize>) -> Self { 135 return Self { 136 layout, 137 vaddr, 138 paddr, 139 }; 140 } 141 } 142 143 impl Debug for AllocLogItem { 144 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 145 f.debug_struct("AllocLogItem") 146 .field("layout", &self.layout) 147 .field( 148 "vaddr", 149 &format_args!("{:#x}", *self.vaddr.as_ref().unwrap_or(&0)), 150 ) 151 .field( 152 "paddr", 153 &format_args!("{:#x}", self.paddr.as_ref().unwrap_or(&0)), 154 ) 155 .finish() 156 } 157 } 158 159 #[repr(u8)] 160 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 161 pub enum LogSource { 162 Undefined = 0, 163 Bump = 1, 164 Buddy = 2, 165 Slab = 3, 166 } 167 168 pub struct MMLogCycle; 169 170 impl MMLogCycle { 171 pub const fn new() -> Self { 172 Self {} 173 } 174 } 175 176 impl kdepends::thingbuf::Recycle<AllocatorLog> for MMLogCycle { 177 fn new_element(&self) -> AllocatorLog { 178 AllocatorLog::zeroed() 179 } 180 181 fn recycle(&self, element: &mut AllocatorLog) { 182 *element = AllocatorLog::zeroed(); 183 } 184 } 185 186 /// 内存分配器日志通道 187 #[repr(C)] 188 pub struct MMLogChannel<const CAP: usize> { 189 pub magic: u32, 190 /// 日志元素的大小 191 pub element_size: u32, 192 /// 日志通道每个槽的大小(字节) 193 pub slot_size: u32, 194 pub capacity: u64, 195 pub slots_offset: u64, 196 pub buf: StaticThingBuf<AllocatorLog, CAP, MMLogCycle>, 197 } 198 199 impl<const CAP: usize> Debug for MMLogChannel<CAP> { 200 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 201 f.debug_struct("MMLogChannel") 202 .field("magic", &format!("{:#x}", self.magic)) 203 .field("element_size", &self.element_size) 204 .field("capacity", &self.capacity) 205 .field("slots_offset", &self.slots_offset) 206 .field( 207 "buf", 208 &format!( 209 "StaticThingBuf<AllocatorLog, {}, MMLogCycle>", 210 self.capacity 211 ), 212 ) 213 .finish() 214 } 215 } 216 217 impl<const CAP: usize> MMLogChannel<CAP> { 218 /// 日志通道的魔数 219 pub const MM_LOG_CHANNEL_MAGIC: u32 = 0x4d4c4348; 220 221 /// 创建一个大小为`capacity`日志通道 222 pub const fn new(capacity: usize) -> Self { 223 let buffer = StaticThingBuf::with_recycle(MMLogCycle::new()); 224 assert!(buffer.offset_of_slots() != 0); 225 let slot_total_size = size_of_val(&buffer) - buffer.offset_of_slots(); 226 let slot_size = slot_total_size / capacity; 227 assert!(slot_size != 0); 228 assert!(slot_size > size_of_val(&AllocatorLog::zeroed())); 229 230 let r = Self { 231 magic: Self::MM_LOG_CHANNEL_MAGIC, 232 element_size: core::mem::size_of::<AllocatorLog>() as u32, 233 capacity: capacity as u64, 234 slot_size: slot_size as u32, 235 slots_offset: (offset_of!(MMLogChannel<CAP>, buf) + buffer.offset_of_slots()) as u64, 236 buf: buffer, 237 }; 238 239 return r; 240 } 241 } 242