xref: /DragonOS/kernel/src/debug/klog/mm.rs (revision 7b32f5080f42bcbf7d2421013f3ea53c776a063c)
1*7b32f508SLoGin extern crate klog_types;
2*7b32f508SLoGin 
3*7b32f508SLoGin use core::intrinsics::unlikely;
4*7b32f508SLoGin 
5*7b32f508SLoGin use klog_types::{AllocatorLog, AllocatorLogType, LogSource, MMLogChannel};
6*7b32f508SLoGin 
7*7b32f508SLoGin use crate::{
8*7b32f508SLoGin     arch::CurrentTimeArch,
9*7b32f508SLoGin     process::{Pid, ProcessManager},
10*7b32f508SLoGin     time::TimeArch,
11*7b32f508SLoGin };
12*7b32f508SLoGin 
13*7b32f508SLoGin /// 全局的内存分配器日志通道
14*7b32f508SLoGin ///
15*7b32f508SLoGin /// 标记为`no_mangle`是为了让调试器能够找到这个变量
16*7b32f508SLoGin #[no_mangle]
17*7b32f508SLoGin static __MM_ALLOCATOR_LOG_CHANNEL: MMLogChannel<{ MMDebugLogManager::MAX_ALLOC_LOG_NUM }> =
18*7b32f508SLoGin     MMLogChannel::new(MMDebugLogManager::MAX_ALLOC_LOG_NUM);
19*7b32f508SLoGin 
20*7b32f508SLoGin /// 全局的内存分配器日志id分配器
21*7b32f508SLoGin ///
22*7b32f508SLoGin /// id从1开始, 因为0是无效的id
23*7b32f508SLoGin static __MM_DEBUG_LOG_IDA: ida::IdAllocator = ida::IdAllocator::new(1, usize::MAX);
24*7b32f508SLoGin 
25*7b32f508SLoGin /// 记录内存分配器的日志
26*7b32f508SLoGin ///
27*7b32f508SLoGin /// ## 参数
28*7b32f508SLoGin ///
29*7b32f508SLoGin /// - `log_type`:日志类型
30*7b32f508SLoGin /// - `source`:日志来源
31*7b32f508SLoGin pub fn mm_debug_log(log_type: AllocatorLogType, source: LogSource) {
32*7b32f508SLoGin     let pid = if unlikely(!ProcessManager::initialized()) {
33*7b32f508SLoGin         Some(Pid::new(0))
34*7b32f508SLoGin     } else {
35*7b32f508SLoGin         Some(ProcessManager::current_pcb().pid())
36*7b32f508SLoGin     };
37*7b32f508SLoGin     MMDebugLogManager::log(log_type, source, pid);
38*7b32f508SLoGin }
39*7b32f508SLoGin 
40*7b32f508SLoGin #[derive(Debug)]
41*7b32f508SLoGin pub(super) struct MMDebugLogManager;
42*7b32f508SLoGin 
43*7b32f508SLoGin impl MMDebugLogManager {
44*7b32f508SLoGin     /// 最大的内存分配器日志数量
45*7b32f508SLoGin     pub const MAX_ALLOC_LOG_NUM: usize = 100000;
46*7b32f508SLoGin 
47*7b32f508SLoGin     /// 记录内存分配器的日志
48*7b32f508SLoGin     ///
49*7b32f508SLoGin     /// ## 参数
50*7b32f508SLoGin     ///
51*7b32f508SLoGin     /// - `log_type`:日志类型
52*7b32f508SLoGin     /// - `source`:日志来源
53*7b32f508SLoGin     /// - `pid`:日志来源的pid
54*7b32f508SLoGin     pub fn log(log_type: AllocatorLogType, source: LogSource, pid: Option<Pid>) {
55*7b32f508SLoGin         let id = __MM_DEBUG_LOG_IDA.alloc().unwrap();
56*7b32f508SLoGin         let log = AllocatorLog::new(
57*7b32f508SLoGin             id as u64,
58*7b32f508SLoGin             log_type,
59*7b32f508SLoGin             source,
60*7b32f508SLoGin             pid.map(|p| p.data()),
61*7b32f508SLoGin             CurrentTimeArch::get_cycles() as u64,
62*7b32f508SLoGin         );
63*7b32f508SLoGin 
64*7b32f508SLoGin         let mut log = log;
65*7b32f508SLoGin         loop {
66*7b32f508SLoGin             let r = __MM_ALLOCATOR_LOG_CHANNEL.buf.push(log);
67*7b32f508SLoGin             if let Err(r) = r {
68*7b32f508SLoGin                 // 如果日志通道满了,就把最早的日志丢弃
69*7b32f508SLoGin                 if __MM_ALLOCATOR_LOG_CHANNEL.buf.remaining() == 0 {
70*7b32f508SLoGin                     __MM_ALLOCATOR_LOG_CHANNEL.buf.pop();
71*7b32f508SLoGin                 }
72*7b32f508SLoGin                 log = r.into_inner();
73*7b32f508SLoGin             } else {
74*7b32f508SLoGin                 break;
75*7b32f508SLoGin             }
76*7b32f508SLoGin         }
77*7b32f508SLoGin     }
78*7b32f508SLoGin }
79