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