feat:Add tracepoint prototype (#1088)

* feat:Add tracepoint prototype

Signed-off-by: Godones <chenlinfeng25@outlook.com>
This commit is contained in:
linfeng
2025-04-22 01:58:44 +08:00
committed by GitHub
parent 2c81a9760e
commit 50bbcae01a
14 changed files with 869 additions and 26 deletions

155
kernel/Cargo.lock generated
View File

@ -212,7 +212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe05a1a3c09033e9e87f7ba13af35cf2508148d3a97fb6b16475df84207993fa"
dependencies = [
"libc",
"windows",
"windows 0.58.0",
]
[[package]]
@ -1498,14 +1498,14 @@ dependencies = [
[[package]]
name = "static-keys"
version = "0.6.1"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ae6eb9d5e3c88a62145a3f2edd2e45c296bad8ef3e31b06d654acff70272744"
checksum = "aa784228d57f9f47a0f5837289ba92296239c2273f146d97b35bbd8538806777"
dependencies = [
"clear-cache",
"libc",
"mach2",
"windows",
"windows 0.59.0",
]
[[package]]
@ -1972,23 +1972,46 @@ version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
dependencies = [
"windows-core",
"windows-core 0.58.0",
"windows-targets 0.52.6",
]
[[package]]
name = "windows"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1"
dependencies = [
"windows-core 0.59.0",
"windows-targets 0.53.0",
]
[[package]]
name = "windows-core"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-strings",
"windows-implement 0.58.0",
"windows-interface 0.58.0",
"windows-result 0.2.0",
"windows-strings 0.1.0",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-core"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce"
dependencies = [
"windows-implement 0.59.0",
"windows-interface 0.59.1",
"windows-result 0.3.2",
"windows-strings 0.3.1",
"windows-targets 0.53.0",
]
[[package]]
name = "windows-implement"
version = "0.58.0"
@ -2000,6 +2023,17 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "windows-implement"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
]
[[package]]
name = "windows-interface"
version = "0.58.0"
@ -2011,6 +2045,23 @@ dependencies = [
"syn 2.0.100",
]
[[package]]
name = "windows-interface"
version = "0.59.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.100",
]
[[package]]
name = "windows-link"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
[[package]]
name = "windows-result"
version = "0.2.0"
@ -2020,16 +2071,34 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-result"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
dependencies = [
"windows-result",
"windows-result 0.2.0",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-strings"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-sys"
version = "0.48.0"
@ -2072,13 +2141,29 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
"windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6",
]
[[package]]
name = "windows-targets"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
dependencies = [
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
"windows_i686_gnullvm 0.53.0",
"windows_i686_msvc 0.53.0",
"windows_x86_64_gnu 0.53.0",
"windows_x86_64_gnullvm 0.53.0",
"windows_x86_64_msvc 0.53.0",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
@ -2091,6 +2176,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
@ -2103,6 +2194,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
@ -2115,12 +2212,24 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
@ -2133,6 +2242,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
@ -2145,6 +2260,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
@ -2157,6 +2278,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
@ -2169,6 +2296,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winnow"
version = "0.7.4"

View File

@ -75,7 +75,7 @@ lru = "0.12.3"
rbpf = { path = "crates/rbpf" }
printf-compat = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/printf-compat", rev = "5f5c9cc363", default-features = false }
static-keys = "=0.6.1"
static-keys = { version = "=0.7" }
defer = "0.2.1"
cfg-if = { version = "1.0.0" }

View File

@ -66,6 +66,16 @@ SECTIONS
}
. = ALIGN(32768);
trace_point_start_pa = .;
.tracepoint (trace_point_start_pa): AT(trace_point_start_pa - KERNEL_VMA)
{
_tracepoint = .;
*(.tracepoint)
*(.tracepoint.*)
_etracepoint = .;
}
. = ALIGN(32768);
init_proc_union_start_pa = .;
.data.init_proc_union (init_proc_union_start_pa):

View File

@ -68,6 +68,16 @@ SECTIONS
. = ALIGN(32768);
trace_point_start_pa = .;
.tracepoint (trace_point_start_pa): AT(trace_point_start_pa - KERNEL_VMA)
{
_tracepoint = .;
*(.tracepoint)
*(.tracepoint.*)
_etracepoint = .;
}
. = ALIGN(32768);
init_proc_union_start_pa = .;
.data.init_proc_union (init_proc_union_start_pa): AT(init_proc_union_start_pa - KERNEL_VMA)
{ *(.data.init_proc_union) }

View File

@ -67,6 +67,16 @@ SECTIONS
. = ALIGN(32768);
trace_point_start_pa = .;
.tracepoint (trace_point_start_pa): AT(trace_point_start_pa - KERNEL_VMA)
{
_tracepoint = .;
*(.tracepoint)
*(.tracepoint.*)
_etracepoint = .;
}
. = ALIGN(32768);
init_proc_union_start_pa = .;
.data.init_proc_union (init_proc_union_start_pa): AT(init_proc_union_start_pa - KERNEL_VMA)
{ *(.data.init_proc_union) }

View File

@ -1,2 +1,3 @@
gen_kallsyms
kallsyms.S
kallsyms.S
kallsyms

View File

@ -2,4 +2,6 @@ pub mod jump_label;
pub mod klog;
pub mod kprobe;
pub mod panic;
pub mod sysfs;
pub mod traceback;
pub mod tracing;

View File

@ -0,0 +1,28 @@
use crate::driver::base::kset::KSet;
use crate::init::initcall::INITCALL_POSTCORE;
use crate::misc::ksysfs::sys_kernel_kset;
use alloc::string::ToString;
use alloc::sync::Arc;
use system_error::SystemError;
use unified_init::macros::unified_init;
/// `/sys/kernel/debug`的kset
static mut SYS_KERNEL_DEBUG_KSET_INSTANCE: Option<Arc<KSet>> = None;
/// 初始化debug模块在sysfs中的目录
#[unified_init(INITCALL_POSTCORE)]
fn debugfs_init() -> Result<(), SystemError> {
let debug_kset = KSet::new("debug".to_string());
debug_kset
.register(Some(sys_kernel_kset()))
.expect("register debug kset failed");
unsafe {
SYS_KERNEL_DEBUG_KSET_INSTANCE = Some(debug_kset);
}
super::tracing::init_debugfs_tracing()?;
return Ok(());
}
pub fn debugfs_kset() -> Arc<KSet> {
unsafe { SYS_KERNEL_DEBUG_KSET_INSTANCE.clone().unwrap() }
}

View File

@ -0,0 +1,239 @@
use crate::debug::tracing::tracepoint::{CommonTracePointMeta, TracePoint};
use crate::debug::tracing::TracingDirCallBack;
use crate::filesystem::kernfs::callback::{KernCallbackData, KernFSCallback, KernInodePrivateData};
use crate::filesystem::kernfs::KernFSInode;
use crate::filesystem::vfs::syscall::ModeType;
use crate::filesystem::vfs::PollStatus;
use crate::libs::spinlock::SpinLock;
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
use alloc::sync::Arc;
use system_error::SystemError;
#[derive(Debug)]
pub struct TracingEventsManager {
root: Arc<KernFSInode>,
subsystems: SpinLock<BTreeMap<String, Arc<EventsSubsystem>>>,
}
impl TracingEventsManager {
pub fn new(root: Arc<KernFSInode>) -> Self {
Self {
root,
subsystems: SpinLock::new(BTreeMap::new()),
}
}
/// Create a subsystem by name
///
/// If the subsystem already exists, return the existing subsystem.
pub fn create_subsystem(
&self,
subsystem_name: &str,
) -> Result<Arc<EventsSubsystem>, SystemError> {
if self.subsystems.lock().contains_key(subsystem_name) {
return Ok(self.get_subsystem(subsystem_name).unwrap());
}
let dir = self.root.add_dir(
subsystem_name.to_string(),
ModeType::from_bits_truncate(0o755),
None,
Some(&TracingDirCallBack),
)?;
let subsystem = Arc::new(EventsSubsystem::new(dir));
self.subsystems
.lock()
.insert(subsystem_name.to_string(), subsystem.clone());
Ok(subsystem)
}
/// Get the subsystem by name
pub fn get_subsystem(&self, subsystem_name: &str) -> Option<Arc<EventsSubsystem>> {
self.subsystems.lock().get(subsystem_name).cloned()
}
}
#[derive(Debug)]
pub struct EventsSubsystem {
root: Arc<KernFSInode>,
events: SpinLock<BTreeMap<String, Arc<EventInfo>>>,
}
impl EventsSubsystem {
pub fn new(root: Arc<KernFSInode>) -> Self {
Self {
root,
events: SpinLock::new(BTreeMap::new()),
}
}
/// Insert a new event into the subsystem
pub fn insert_event(
&self,
event_name: &str,
event_info: Arc<EventInfo>,
) -> Result<(), SystemError> {
self.events
.lock()
.insert(event_name.to_string(), event_info);
Ok(())
}
/// Get the event by name
#[allow(unused)]
pub fn get_event(&self, event_name: &str) -> Option<Arc<EventInfo>> {
self.events.lock().get(event_name).cloned()
}
/// Get the root inode of the subsystem
pub fn root(&self) -> Arc<KernFSInode> {
self.root.clone()
}
}
#[derive(Debug)]
pub struct EventInfo {
#[allow(unused)]
enable: Arc<KernFSInode>,
// filter: Arc<KernFSInode>,
// trigger: Arc<KernFSInode>,
}
impl EventInfo {
pub fn new(tracepoint: &'static TracePoint, subsystem: Arc<KernFSInode>) -> Arc<Self> {
let trace_dir = subsystem
.add_dir(
tracepoint.name().to_string(),
ModeType::from_bits_truncate(0o755),
None,
Some(&TracingDirCallBack),
)
.expect("add tracepoint dir failed");
let enable_inode = trace_dir
.add_file(
"enable".to_string(),
ModeType::from_bits_truncate(0o644),
None,
Some(KernInodePrivateData::DebugFS(tracepoint)),
Some(&EnableCallBack),
)
.expect("add enable file failed");
Arc::new(Self {
enable: enable_inode,
})
}
}
impl Drop for EventInfo {
fn drop(&mut self) {}
}
#[derive(Debug)]
struct EnableCallBack;
impl KernFSCallback for EnableCallBack {
fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> {
Ok(())
}
fn read(
&self,
data: KernCallbackData,
buf: &mut [u8],
offset: usize,
) -> Result<usize, SystemError> {
if offset > 0 {
return Ok(0);
}
let pri_data = data.private_data();
match pri_data {
Some(pri_data) => {
let tracepoint = pri_data.debugfs_tracepoint().ok_or(SystemError::EINVAL)?;
let buf_value = if tracepoint.is_enabled() { b"1" } else { b"0" };
let len = buf.len().min(buf_value.len());
buf[..len].copy_from_slice(&buf_value[..len]);
Ok(len)
}
None => {
return Err(SystemError::EINVAL);
}
}
}
fn write(
&self,
data: KernCallbackData,
buf: &[u8],
_offset: usize,
) -> Result<usize, SystemError> {
let pri_data = data.private_data();
match pri_data {
Some(pri_data) => {
let tracepoint = pri_data.debugfs_tracepoint().ok_or(SystemError::EINVAL)?;
let value = core::str::from_utf8(buf)
.map_err(|_| SystemError::EINVAL)?
.trim();
match value {
"0" => {
tracepoint.disable();
}
"1" => {
tracepoint.enable();
}
_ => {
log::info!("EnableCallBack invalid value: {}", value);
return Err(SystemError::EINVAL);
}
}
Ok(buf.len())
}
None => {
return Err(SystemError::EINVAL);
}
}
}
fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> {
Err(SystemError::ENOSYS)
}
}
static mut TRACING_EVENTS_MANAGER: Option<TracingEventsManager> = None;
/// Initialize the tracing events
pub fn init_events(events_root: Arc<KernFSInode>) -> Result<(), SystemError> {
let events_manager = TracingEventsManager::new(events_root);
let tracepoint_data_start = _tracepoint as usize as *const CommonTracePointMeta;
let tracepoint_data_end = _etracepoint as usize as *const CommonTracePointMeta;
let tracepoint_data_len = (tracepoint_data_end as usize - tracepoint_data_start as usize)
/ size_of::<CommonTracePointMeta>();
let tracepoint_data =
unsafe { core::slice::from_raw_parts(tracepoint_data_start, tracepoint_data_len) };
for tracepoint_meta in tracepoint_data {
let tracepoint = tracepoint_meta.trace_point;
tracepoint.register(tracepoint_meta.print_func, Box::new(()));
log::info!(
"tracepoint name: {}, module path: {}",
tracepoint.name(),
tracepoint.module_path()
);
// kernel::{subsystem}::
let mut subsys_name = tracepoint.module_path().split("::");
let subsys_name = subsys_name.nth(1).ok_or(SystemError::EINVAL)?;
let subsys = events_manager.create_subsystem(subsys_name)?;
let event_info = EventInfo::new(tracepoint, subsys.root());
subsys.insert_event(tracepoint.name(), event_info)?;
}
unsafe {
TRACING_EVENTS_MANAGER = Some(events_manager);
}
Ok(())
}
extern "C" {
fn _tracepoint();
fn _etracepoint();
}

View File

@ -0,0 +1,97 @@
mod events;
pub mod trace_pipe;
pub mod tracepoint;
use crate::debug::sysfs::debugfs_kset;
use crate::debug::tracing::trace_pipe::TRACE_PIPE_MAX_RECORD;
use crate::driver::base::kobject::KObject;
use crate::filesystem::kernfs::callback::{KernCallbackData, KernFSCallback, KernInodePrivateData};
use crate::filesystem::kernfs::KernFSInode;
use crate::filesystem::vfs::syscall::ModeType;
use crate::filesystem::vfs::PollStatus;
use alloc::string::ToString;
use alloc::sync::Arc;
use system_error::SystemError;
use tracepoint::TracePoint;
static mut TRACING_ROOT_INODE: Option<Arc<KernFSInode>> = None;
#[allow(unused)]
fn tracing_root_inode() -> Arc<KernFSInode> {
unsafe { TRACING_ROOT_INODE.clone().unwrap() }
}
/// Initialize the debugfs tracing directory
pub fn init_debugfs_tracing() -> Result<(), SystemError> {
let debugfs = debugfs_kset();
let root_dir = debugfs.inode().ok_or(SystemError::ENOENT)?;
let tracing_root = root_dir.add_dir(
"tracing".to_string(),
ModeType::from_bits_truncate(0o555),
None,
Some(&TracingDirCallBack),
)?;
let events_root = tracing_root.add_dir(
"events".to_string(),
ModeType::from_bits_truncate(0o755),
None,
Some(&TracingDirCallBack),
)?;
tracing_root.add_file(
"trace_pipe".to_string(),
ModeType::from_bits_truncate(0o444),
Some(TRACE_PIPE_MAX_RECORD),
None,
Some(&trace_pipe::TracePipeCallBack),
)?;
trace_pipe::init_trace_pipe();
events::init_events(events_root)?;
unsafe {
TRACING_ROOT_INODE = Some(tracing_root);
}
Ok(())
}
#[derive(Debug)]
pub struct TracingDirCallBack;
impl KernFSCallback for TracingDirCallBack {
fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> {
Ok(())
}
fn read(
&self,
_data: KernCallbackData,
_buf: &mut [u8],
_offset: usize,
) -> Result<usize, SystemError> {
Err(SystemError::EISDIR)
}
fn write(
&self,
_data: KernCallbackData,
_buf: &[u8],
_offset: usize,
) -> Result<usize, SystemError> {
Err(SystemError::EISDIR)
}
fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> {
Err(SystemError::EISDIR)
}
}
impl KernInodePrivateData {
pub fn debugfs_tracepoint(&self) -> Option<&'static TracePoint> {
return match self {
KernInodePrivateData::DebugFS(tracepoint) => Some(tracepoint),
_ => None,
};
}
}

View File

@ -0,0 +1,123 @@
use crate::filesystem::kernfs::callback::{KernCallbackData, KernFSCallback};
use crate::filesystem::vfs::PollStatus;
use crate::libs::spinlock::SpinLock;
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt::Debug;
use system_error::SystemError;
static mut TRACE_PIPE: Option<TracePipe> = None;
pub const TRACE_PIPE_MAX_RECORD: usize = 4096;
pub fn init_trace_pipe() {
unsafe {
TRACE_PIPE = Some(TracePipe::new(TRACE_PIPE_MAX_RECORD));
}
}
pub fn trace_pipe() -> &'static TracePipe {
unsafe { TRACE_PIPE.as_ref().unwrap() }
}
/// Push a record to trace pipe
pub fn trace_pipe_push_record(record: String) {
trace_pipe().push_record(record);
}
pub struct TracePipe {
buf: SpinLock<TracePipeBuf>,
}
struct TracePipeBuf {
size: usize,
max_record: usize,
buf: Vec<String>,
}
impl TracePipeBuf {
pub const fn new(max_record: usize) -> Self {
Self {
max_record,
size: 0,
buf: Vec::new(),
}
}
pub fn push_str(&mut self, record: String) {
let record_size = record.len();
if self.size + record_size > self.max_record {
let mut i = 0;
while i < record_size {
let t = self.buf.pop().unwrap();
self.size -= t.len();
i += t.len();
}
}
self.buf.push(record);
self.size += record_size;
}
pub fn read_at(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
if offset == self.size {
return Ok(0);
}
if buf.len() < self.size {
return Err(SystemError::EINVAL);
}
let mut count = 0;
for line in self.buf.iter() {
let line = line.as_bytes();
buf[count..count + line.len()].copy_from_slice(line);
count += line.len();
}
Ok(count)
}
}
impl TracePipe {
pub const fn new(max_record: usize) -> Self {
Self {
buf: SpinLock::new(TracePipeBuf::new(max_record)),
}
}
pub fn push_record(&self, record: String) {
self.buf.lock().push_str(record);
}
pub fn read_at(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
self.buf.lock().read_at(buf, offset)
}
}
#[derive(Debug)]
pub struct TracePipeCallBack;
impl KernFSCallback for TracePipeCallBack {
fn open(&self, _data: KernCallbackData) -> Result<(), SystemError> {
Ok(())
}
fn read(
&self,
_data: KernCallbackData,
buf: &mut [u8],
offset: usize,
) -> Result<usize, SystemError> {
let trace_pipe = trace_pipe();
trace_pipe.read_at(buf, offset)
}
fn write(
&self,
_data: KernCallbackData,
_buf: &[u8],
_offset: usize,
) -> Result<usize, SystemError> {
Err(SystemError::EPERM)
}
fn poll(&self, _data: KernCallbackData) -> Result<PollStatus, SystemError> {
Ok(PollStatus::READ)
}
}

View File

@ -0,0 +1,187 @@
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)]
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);
}
}
};
}

View File

@ -1,3 +1,5 @@
use super::KernFSInode;
use crate::debug::tracing::tracepoint::TracePoint;
use crate::{
filesystem::{sysfs::SysFSKernPrivateData, vfs::PollStatus},
libs::spinlock::SpinLockGuard,
@ -6,8 +8,6 @@ use alloc::sync::Arc;
use core::fmt::Debug;
use system_error::SystemError;
use super::KernFSInode;
/// KernFS文件的回调接口
///
/// 当用户态程序打开、读取、写入、关闭文件时kernfs会调用相应的回调函数。
@ -86,24 +86,23 @@ impl<'a> KernCallbackData<'a> {
#[derive(Debug)]
pub enum KernInodePrivateData {
SysFS(SysFSKernPrivateData),
DebugFS(&'static TracePoint),
}
impl KernInodePrivateData {
#[inline(always)]
pub fn callback_read(&self, buf: &mut [u8], offset: usize) -> Result<usize, SystemError> {
match self {
KernInodePrivateData::SysFS(private_data) => {
return private_data.callback_read(buf, offset);
}
}
return match self {
KernInodePrivateData::SysFS(private_data) => private_data.callback_read(buf, offset),
_ => Err(SystemError::ENOSYS),
};
}
#[inline(always)]
pub fn callback_write(&self, buf: &[u8], offset: usize) -> Result<usize, SystemError> {
match self {
KernInodePrivateData::SysFS(private_data) => {
return private_data.callback_write(buf, offset);
}
}
return match self {
KernInodePrivateData::SysFS(private_data) => private_data.callback_write(buf, offset),
_ => Err(SystemError::ENOSYS),
};
}
}

View File

@ -5,6 +5,7 @@ use log::{error, info};
use system_error::SystemError;
use crate::{
define_event_trace, define_trace_point,
driver::base::block::{gendisk::GenDisk, manager::block_dev_manager},
filesystem::{
devfs::devfs_init,
@ -155,7 +156,7 @@ pub fn mount_root_fs() -> Result<(), SystemError> {
let fatfs: Arc<FATFileSystem> = fatfs.unwrap();
let r = migrate_virtual_filesystem(fatfs);
if r.is_err() {
error!("Failed to migrate virtual filesystem to FAT32!");
error!("Failed to migrate virtual filesyst em to FAT32!");
loop {
spin_loop();
}
@ -165,12 +166,15 @@ pub fn mount_root_fs() -> Result<(), SystemError> {
return Ok(());
}
define_event_trace!(DO_MKDIR_AT,(path:&str,mode:FileMode),
format_args!("mkdir at {} with mode {:?}",path, mode));
/// @brief 创建文件/文件夹
pub fn do_mkdir_at(
dirfd: i32,
path: &str,
mode: FileMode,
) -> Result<Arc<dyn IndexNode>, SystemError> {
TRACE_DO_MKDIR_AT(path, mode);
// debug!("Call do mkdir at");
let (mut current_inode, path) =
user_path_at(&ProcessManager::current_pcb(), dirfd, path.trim())?;