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