tracepoint.rs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. use crate::libs::spinlock::{SpinLock, SpinLockGuard};
  2. use alloc::boxed::Box;
  3. use alloc::collections::BTreeMap;
  4. use core::any::Any;
  5. use core::fmt::Debug;
  6. use static_keys::StaticFalseKey;
  7. pub struct TracePoint {
  8. name: &'static str,
  9. module_path: &'static str,
  10. key: &'static StaticFalseKey,
  11. register: Option<fn()>,
  12. unregister: Option<fn()>,
  13. callback: SpinLock<BTreeMap<usize, TracePointFunc>>,
  14. }
  15. impl Debug for TracePoint {
  16. fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
  17. f.debug_struct("TracePoint")
  18. .field("name", &self.name)
  19. .finish()
  20. }
  21. }
  22. #[derive(Debug)]
  23. #[repr(C)]
  24. pub struct CommonTracePointMeta {
  25. pub trace_point: &'static TracePoint,
  26. pub print_func: fn(),
  27. }
  28. #[derive(Debug)]
  29. pub struct TracePointFunc {
  30. pub func: fn(),
  31. pub data: Box<dyn Any + Send + Sync>,
  32. }
  33. impl TracePoint {
  34. pub const fn new(
  35. key: &'static StaticFalseKey,
  36. name: &'static str,
  37. module_path: &'static str,
  38. register: Option<fn()>,
  39. unregister: Option<fn()>,
  40. ) -> Self {
  41. Self {
  42. name,
  43. module_path,
  44. key,
  45. register,
  46. unregister,
  47. callback: SpinLock::new(BTreeMap::new()),
  48. }
  49. }
  50. pub fn name(&self) -> &'static str {
  51. self.name
  52. }
  53. pub fn module_path(&self) -> &'static str {
  54. self.module_path
  55. }
  56. /// Register a callback function to the tracepoint
  57. pub fn register(&self, func: fn(), data: Box<dyn Any + Sync + Send>) {
  58. let trace_point_func = TracePointFunc { func, data };
  59. let mut funcs = self.callback.lock();
  60. if let Some(register) = self.register {
  61. register();
  62. }
  63. let ptr = func as usize;
  64. funcs.entry(ptr).or_insert(trace_point_func);
  65. }
  66. /// Unregister a callback function from the tracepoint
  67. pub fn unregister(&self, func: fn()) {
  68. let mut funcs = self.callback.lock();
  69. if let Some(unregister) = self.unregister {
  70. unregister();
  71. }
  72. let func_ptr = func as usize;
  73. funcs.remove(&func_ptr);
  74. }
  75. /// Get the callback list
  76. pub fn callback_list(&self) -> SpinLockGuard<BTreeMap<usize, TracePointFunc>> {
  77. self.callback.lock()
  78. }
  79. /// Enable the tracepoint
  80. pub fn enable(&self) {
  81. unsafe {
  82. self.key.enable();
  83. }
  84. }
  85. /// Disable the tracepoint
  86. pub fn disable(&self) {
  87. unsafe {
  88. self.key.disable();
  89. }
  90. }
  91. /// Check if the tracepoint is enabled
  92. pub fn is_enabled(&self) -> bool {
  93. self.key.is_enabled()
  94. }
  95. }
  96. /// Define a tracepoint
  97. ///
  98. /// User should call register_trace_\$name to register a callback function to the tracepoint and
  99. /// call trace_\$name to trigger the callback function
  100. #[macro_export]
  101. macro_rules! define_trace_point {
  102. ($name:ident $(,$arg:ident:$arg_type:ty),*) => {
  103. paste::paste!{
  104. static_keys::define_static_key_false!([<__ $name _KEY>]);
  105. #[allow(non_upper_case_globals)]
  106. #[used]
  107. static [<__ $name>]: $crate::debug::tracing::tracepoint::TracePoint = $crate::debug::tracing::tracepoint::TracePoint::new(&[<__ $name _KEY>],stringify!($name), module_path!(),None,None);
  108. #[inline(always)]
  109. #[allow(non_snake_case)]
  110. pub fn [<TRACE_ $name>]( $($arg:$arg_type),* ){
  111. if static_keys::static_branch_unlikely!([<__ $name _KEY>]){
  112. let mut funcs = [<__ $name>].callback_list();
  113. for trace_func in funcs.values_mut(){
  114. let func = trace_func.func;
  115. let data = trace_func.data.as_mut();
  116. let func = unsafe{core::mem::transmute::<fn(),fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*)>(func)};
  117. func(data $(,$arg)*);
  118. }
  119. }
  120. }
  121. #[allow(unused,non_snake_case)]
  122. 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>){
  123. let func = unsafe{core::mem::transmute::<fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),fn()>(func)};
  124. [<__ $name>].register(func,data);
  125. }
  126. #[allow(unused,non_snake_case)]
  127. pub fn [<unregister_trace_ $name>](func:fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*)){
  128. let func = unsafe{core::mem::transmute::<fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),fn()>(func)};
  129. [<__ $name>].unregister(func);
  130. }
  131. }
  132. };
  133. }
  134. #[macro_export]
  135. macro_rules! define_event_trace{
  136. ($name:ident,
  137. ($($arg:ident:$arg_type:ty),*),
  138. $fmt:expr) =>{
  139. define_trace_point!($name $(,$arg:$arg_type),*);
  140. paste::paste!{
  141. #[derive(Debug)]
  142. #[repr(C)]
  143. #[allow(non_snake_case)]
  144. #[allow(non_camel_case_types)]
  145. struct [<__ $name _TracePointMeta>]{
  146. trace_point: &'static $crate::debug::tracing::tracepoint::TracePoint,
  147. print_func: fn(&mut (dyn core::any::Any+Send+Sync),$($arg_type),*),
  148. }
  149. #[allow(non_upper_case_globals)]
  150. #[link_section = ".tracepoint"]
  151. #[used]
  152. static [<__ $name _meta>]: [<__ $name _TracePointMeta>] = [<__ $name _TracePointMeta>]{
  153. trace_point:&[<__ $name>],
  154. print_func:[<TRACE_PRINT_ $name>],
  155. };
  156. #[allow(non_snake_case)]
  157. pub fn [<TRACE_PRINT_ $name>](_data:&mut (dyn core::any::Any+Send+Sync),$($arg:$arg_type),* ){
  158. let time = $crate::time::Instant::now();
  159. let cpu_id = $crate::arch::cpu::current_cpu_id().data();
  160. let current_pid = $crate::process::ProcessManager::current_pcb().pid().data();
  161. let format = format!("[{}][{}][{}] {}\n",time,cpu_id,current_pid,$fmt);
  162. $crate::debug::tracing::trace_pipe::trace_pipe_push_record(format);
  163. }
  164. }
  165. };
  166. }