1 #![no_std] 2 #![feature(const_size_of_val)] 3 #![allow(clippy::needless_return)] 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`:日志的时间 new( id: u64, type_: AllocatorLogType, source: LogSource, pid: Option<usize>, time: u64, ) -> Self40 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 zeroed() -> Self60 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 /// 计算日志的校验和 calculate_checksum(value: &Self) -> u6472 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 /// 验证日志的校验和 validate_checksum(&self) -> bool84 pub fn validate_checksum(&self) -> bool { 85 let checksum = Self::calculate_checksum(self); 86 return checksum == self.checksum; 87 } 88 89 /// 当前日志是否有效 is_valid(&self) -> bool90 pub fn is_valid(&self) -> bool { 91 if !self.validate_checksum() { 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 { partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering>104 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> { 105 Some(self.cmp(other)) 106 } 107 } 108 109 impl Ord for AllocatorLog { cmp(&self, other: &Self) -> core::cmp::Ordering110 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 LazyAlloc(AllocLogItem), 124 } 125 126 #[repr(C)] 127 #[derive(Copy, Clone, PartialEq, Eq)] 128 pub struct AllocLogItem { 129 pub layout: core::alloc::Layout, 130 pub vaddr: Option<usize>, 131 pub paddr: Option<usize>, 132 } 133 134 impl AllocLogItem { new(layout: core::alloc::Layout, vaddr: Option<usize>, paddr: Option<usize>) -> Self135 pub fn new(layout: core::alloc::Layout, vaddr: Option<usize>, paddr: Option<usize>) -> Self { 136 return Self { 137 layout, 138 vaddr, 139 paddr, 140 }; 141 } 142 } 143 144 impl Debug for AllocLogItem { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result145 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 146 f.debug_struct("AllocLogItem") 147 .field("layout", &self.layout) 148 .field( 149 "vaddr", 150 &format_args!("{:#x}", *self.vaddr.as_ref().unwrap_or(&0)), 151 ) 152 .field( 153 "paddr", 154 &format_args!("{:#x}", self.paddr.as_ref().unwrap_or(&0)), 155 ) 156 .finish() 157 } 158 } 159 160 #[repr(u8)] 161 #[derive(Debug, Copy, Clone, PartialEq, Eq)] 162 pub enum LogSource { 163 Undefined = 0, 164 Bump = 1, 165 Buddy = 2, 166 Slab = 3, 167 } 168 169 pub struct MMLogCycle; 170 171 impl MMLogCycle { new() -> Self172 pub const fn new() -> Self { 173 Self {} 174 } 175 } 176 177 impl Default for MMLogCycle { default() -> Self178 fn default() -> Self { 179 Self::new() 180 } 181 } 182 183 impl kdepends::thingbuf::Recycle<AllocatorLog> for MMLogCycle { new_element(&self) -> AllocatorLog184 fn new_element(&self) -> AllocatorLog { 185 AllocatorLog::zeroed() 186 } 187 recycle(&self, element: &mut AllocatorLog)188 fn recycle(&self, element: &mut AllocatorLog) { 189 *element = AllocatorLog::zeroed(); 190 } 191 } 192 193 /// 内存分配器日志通道 194 #[repr(C)] 195 pub struct MMLogChannel<const CAP: usize> { 196 pub magic: u32, 197 /// 日志元素的大小 198 pub element_size: u32, 199 /// 日志通道每个槽的大小(字节) 200 pub slot_size: u32, 201 pub capacity: u64, 202 pub slots_offset: u64, 203 pub buf: StaticThingBuf<AllocatorLog, CAP, MMLogCycle>, 204 } 205 206 impl<const CAP: usize> Debug for MMLogChannel<CAP> { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result207 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 208 f.debug_struct("MMLogChannel") 209 .field("magic", &format!("{:#x}", self.magic)) 210 .field("element_size", &self.element_size) 211 .field("capacity", &self.capacity) 212 .field("slots_offset", &self.slots_offset) 213 .field( 214 "buf", 215 &format!( 216 "StaticThingBuf<AllocatorLog, {}, MMLogCycle>", 217 self.capacity 218 ), 219 ) 220 .finish() 221 } 222 } 223 224 impl<const CAP: usize> MMLogChannel<CAP> { 225 /// 日志通道的魔数 226 pub const MM_LOG_CHANNEL_MAGIC: u32 = 0x4d4c4348; 227 228 /// 创建一个大小为`capacity`日志通道 new(capacity: usize) -> Self229 pub const fn new(capacity: usize) -> Self { 230 let buffer = StaticThingBuf::with_recycle(MMLogCycle::new()); 231 assert!(buffer.offset_of_slots() != 0); 232 let slot_total_size = size_of_val(&buffer) - buffer.offset_of_slots(); 233 let slot_size = slot_total_size / capacity; 234 assert!(slot_size != 0); 235 assert!(slot_size > size_of_val(&AllocatorLog::zeroed())); 236 237 let r = Self { 238 magic: Self::MM_LOG_CHANNEL_MAGIC, 239 element_size: core::mem::size_of::<AllocatorLog>() as u32, 240 capacity: capacity as u64, 241 slot_size: slot_size as u32, 242 slots_offset: (offset_of!(MMLogChannel<CAP>, buf) + buffer.offset_of_slots()) as u64, 243 buf: buffer, 244 }; 245 246 return r; 247 } 248 } 249