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