xref: /DragonOS/kernel/crates/klog_types/src/lib.rs (revision 7b32f5080f42bcbf7d2421013f3ea53c776a063c)
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