DragonOS/kernel/src/debug/tracing/tracepoint.rs
LoGin 0b89d7130e
refactor(vfs): 重构statx系统调用的实现 (#1149)
- 将kstat的获取,与posix statx的获取进行分离.
- 修复statx没有处理dirfd的bug
- 在Metadata结构体中新增btime字段,表示文件的创建时间
- 更新多个文件系统的metadata实现,添加对btime的支持
- 引入derive_builder crate以简化Metadata构建过程
- 重构vfs模块,将core重命名为vcore以避免命名冲突
- 实现vfs_statx和vfs_getattr函数,支持更详细的文件属性查询
- 新增LookUpFlags定义,用于路径查找时的标志位

Signed-off-by: longjin <longjin@dragonos.org>
2025-05-09 14:46:10 +08:00

188 lines
6.1 KiB
Rust

use crate::libs::spinlock::{SpinLock, SpinLockGuard};
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use core::any::Any;
use core::fmt::Debug;
use static_keys::StaticFalseKey;
pub struct TracePoint {
name: &'static str,
module_path: &'static str,
key: &'static StaticFalseKey,
register: Option<fn()>,
unregister: Option<fn()>,
callback: SpinLock<BTreeMap<usize, TracePointFunc>>,
}
impl Debug for TracePoint {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("TracePoint")
.field("name", &self.name)
.finish()
}
}
#[derive(Debug)]
#[repr(C)]
pub struct CommonTracePointMeta {
pub trace_point: &'static TracePoint,
pub print_func: fn(),
}
#[derive(Debug)]
pub struct TracePointFunc {
pub func: fn(),
pub data: Box<dyn Any + Send + Sync>,
}
impl TracePoint {
pub const fn new(
key: &'static StaticFalseKey,
name: &'static str,
module_path: &'static str,
register: Option<fn()>,
unregister: Option<fn()>,
) -> Self {
Self {
name,
module_path,
key,
register,
unregister,
callback: SpinLock::new(BTreeMap::new()),
}
}
pub fn name(&self) -> &'static str {
self.name
}
pub fn module_path(&self) -> &'static str {
self.module_path
}
/// Register a callback function to the tracepoint
pub fn register(&self, func: fn(), data: Box<dyn Any + Sync + Send>) {
let trace_point_func = TracePointFunc { func, data };
let mut funcs = self.callback.lock();
if let Some(register) = self.register {
register();
}
let ptr = func as usize;
funcs.entry(ptr).or_insert(trace_point_func);
}
/// Unregister a callback function from the tracepoint
pub fn unregister(&self, func: fn()) {
let mut funcs = self.callback.lock();
if let Some(unregister) = self.unregister {
unregister();
}
let func_ptr = func as usize;
funcs.remove(&func_ptr);
}
/// Get the callback list
pub fn callback_list(&self) -> SpinLockGuard<BTreeMap<usize, TracePointFunc>> {
self.callback.lock()
}
/// Enable the tracepoint
pub fn enable(&self) {
unsafe {
self.key.enable();
}
}
/// Disable the tracepoint
pub fn disable(&self) {
unsafe {
self.key.disable();
}
}
/// Check if the tracepoint is enabled
pub fn is_enabled(&self) -> bool {
self.key.is_enabled()
}
}
/// Define a tracepoint
///
/// User should call register_trace_\$name to register a callback function to the tracepoint and
/// call trace_\$name to trigger the callback function
#[macro_export]
macro_rules! define_trace_point {
($name:ident $(,$arg:ident:$arg_type:ty),*) => {
paste::paste!{
static_keys::define_static_key_false!([<__ $name _KEY>]);
#[allow(non_upper_case_globals)]
#[used]
static [<__ $name>]: $crate::debug::tracing::tracepoint::TracePoint = $crate::debug::tracing::tracepoint::TracePoint::new(&[<__ $name _KEY>],stringify!($name), module_path!(),None,None);
#[inline(always)]
#[allow(non_snake_case)]
pub fn [<TRACE_ $name>]( $($arg:$arg_type),* ){
if static_keys::static_branch_unlikely!([<__ $name _KEY>]){
let mut funcs = [<__ $name>].callback_list();
for trace_func in funcs.values_mut(){
let func = trace_func.func;
let data = trace_func.data.as_mut();
let func = unsafe{core::mem::transmute::<fn(),fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*)>(func)};
func(data $(,$arg)*);
}
}
}
#[allow(unused,non_snake_case)]
pub fn [<register_trace_ $name>](func:fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),data:alloc::boxed::Box<dyn core::any::Any+Send+Sync>){
let func = unsafe{core::mem::transmute::<fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),fn()>(func)};
[<__ $name>].register(func,data);
}
#[allow(unused,non_snake_case)]
pub fn [<unregister_trace_ $name>](func:fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*)){
let func = unsafe{core::mem::transmute::<fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),fn()>(func)};
[<__ $name>].unregister(func);
}
}
};
}
#[macro_export]
macro_rules! define_event_trace{
($name:ident,
($($arg:ident:$arg_type:ty),*),
$fmt:expr) =>{
define_trace_point!($name $(,$arg:$arg_type),*);
paste::paste!{
#[derive(Debug)]
#[repr(C)]
#[allow(non_snake_case)]
#[allow(non_camel_case_types)]
struct [<__ $name _TracePointMeta>]{
trace_point: &'static $crate::debug::tracing::tracepoint::TracePoint,
print_func: fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),
}
#[allow(non_upper_case_globals)]
#[link_section = ".tracepoint"]
#[used]
static [<__ $name _meta>]: [<__ $name _TracePointMeta>] = [<__ $name _TracePointMeta>]{
trace_point:&[<__ $name>],
print_func:[<TRACE_PRINT_ $name>],
};
#[allow(non_snake_case)]
pub fn [<TRACE_PRINT_ $name>](_data:&mut (dyn core::any::Any+Send+Sync),$($arg:$arg_type),* ){
let time = $crate::time::Instant::now();
let cpu_id = $crate::arch::cpu::current_cpu_id().data();
let current_pid = $crate::process::ProcessManager::current_pcb().pid().data();
let format = format!("[{}][{}][{}] {}\n",time,cpu_id,current_pid,$fmt);
$crate::debug::tracing::trace_pipe::trace_pipe_push_record(format);
}
}
};
}