#![no_std] #![feature(const_refs_to_cell)] #![feature(const_size_of_val)] #![allow(clippy::needless_return)] extern crate alloc; use core::{fmt::Debug, mem::size_of_val}; use alloc::format; use kdepends::{memoffset::offset_of, thingbuf::StaticThingBuf}; #[repr(C)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct AllocatorLog { /// 日志的id pub id: u64, /// 日志类型 pub type_: AllocatorLogType, /// 日志的时间 pub time: u64, /// 日志的来源 pub source: LogSource, /// 日志的来源pid pub pid: Option, pub checksum: u64, } impl AllocatorLog { /// 创建一个日志 /// /// ## 参数 /// /// - `id`:日志的id /// - `type_`:日志类型 /// - `source`:日志来源 /// - `pid`:日志来源的pid /// - `time`:日志的时间 pub fn new( id: u64, type_: AllocatorLogType, source: LogSource, pid: Option, time: u64, ) -> Self { let mut x = Self { id, type_, time, source, pid, checksum: 0, }; let checksum = Self::calculate_checksum(&x); x.checksum = checksum; return x; } pub const fn zeroed() -> Self { return Self { id: 0, type_: AllocatorLogType::Undefined, time: 0, source: LogSource::Undefined, pid: None, checksum: 0, }; } /// 计算日志的校验和 pub fn calculate_checksum(value: &Self) -> u64 { let buf = unsafe { core::slice::from_raw_parts( value as *const _ as *const u8, core::mem::size_of::() - core::mem::size_of::(), ) }; let checksum = kdepends::crc::crc64::crc64_be(0, buf); return checksum; } /// 验证日志的校验和 pub fn validate_checksum(&self) -> bool { let checksum = Self::calculate_checksum(self); return checksum == self.checksum; } /// 当前日志是否有效 pub fn is_valid(&self) -> bool { if !self.validate_checksum() { return false; } if self.id == 0 { return false; } return true; } } impl PartialOrd for AllocatorLog { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } impl Ord for AllocatorLog { fn cmp(&self, other: &Self) -> core::cmp::Ordering { return self.id.cmp(&other.id); } } /// 内存分配器日志类型 #[repr(C)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum AllocatorLogType { Undefined, Alloc(AllocLogItem), AllocZeroed(AllocLogItem), Free(AllocLogItem), LazyAlloc(AllocLogItem), } #[repr(C)] #[derive(Copy, Clone, PartialEq, Eq)] pub struct AllocLogItem { pub layout: core::alloc::Layout, pub vaddr: Option, pub paddr: Option, } impl AllocLogItem { pub fn new(layout: core::alloc::Layout, vaddr: Option, paddr: Option) -> Self { return Self { layout, vaddr, paddr, }; } } impl Debug for AllocLogItem { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("AllocLogItem") .field("layout", &self.layout) .field( "vaddr", &format_args!("{:#x}", *self.vaddr.as_ref().unwrap_or(&0)), ) .field( "paddr", &format_args!("{:#x}", self.paddr.as_ref().unwrap_or(&0)), ) .finish() } } #[repr(u8)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum LogSource { Undefined = 0, Bump = 1, Buddy = 2, Slab = 3, } pub struct MMLogCycle; impl MMLogCycle { pub const fn new() -> Self { Self {} } } impl Default for MMLogCycle { fn default() -> Self { Self::new() } } impl kdepends::thingbuf::Recycle for MMLogCycle { fn new_element(&self) -> AllocatorLog { AllocatorLog::zeroed() } fn recycle(&self, element: &mut AllocatorLog) { *element = AllocatorLog::zeroed(); } } /// 内存分配器日志通道 #[repr(C)] pub struct MMLogChannel { pub magic: u32, /// 日志元素的大小 pub element_size: u32, /// 日志通道每个槽的大小(字节) pub slot_size: u32, pub capacity: u64, pub slots_offset: u64, pub buf: StaticThingBuf, } impl Debug for MMLogChannel { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { f.debug_struct("MMLogChannel") .field("magic", &format!("{:#x}", self.magic)) .field("element_size", &self.element_size) .field("capacity", &self.capacity) .field("slots_offset", &self.slots_offset) .field( "buf", &format!( "StaticThingBuf", self.capacity ), ) .finish() } } impl MMLogChannel { /// 日志通道的魔数 pub const MM_LOG_CHANNEL_MAGIC: u32 = 0x4d4c4348; /// 创建一个大小为`capacity`日志通道 pub const fn new(capacity: usize) -> Self { let buffer = StaticThingBuf::with_recycle(MMLogCycle::new()); assert!(buffer.offset_of_slots() != 0); let slot_total_size = size_of_val(&buffer) - buffer.offset_of_slots(); let slot_size = slot_total_size / capacity; assert!(slot_size != 0); assert!(slot_size > size_of_val(&AllocatorLog::zeroed())); let r = Self { magic: Self::MM_LOG_CHANNEL_MAGIC, element_size: core::mem::size_of::() as u32, capacity: capacity as u64, slot_size: slot_size as u32, slots_offset: (offset_of!(MMLogChannel, buf) + buffer.offset_of_slots()) as u64, buf: buffer, }; return r; } }