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