basic_macro.rs 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /// Define a tracepoint with the given parameters.
  2. ///
  3. /// This macro generates a tracepoint with the specified name, arguments, entry structure, assignment logic, identifier, and print format.
  4. /// # Parameters
  5. /// - `name`: The name of the tracepoint.
  6. /// - `TP_system`: The subsystem or system to which the tracepoint belongs.
  7. /// - `TP_PROTO`: The prototype of the tracepoint function.
  8. /// - `TP_STRUCT__entry`: The structure of the tracepoint entry.
  9. /// - `TP_fast_assign`: The assignment logic for the tracepoint entry.
  10. /// - `TP_ident`: The identifier for the tracepoint entry.
  11. /// - `TP_printk`: The print format for the tracepoint.
  12. ///
  13. /// # Example
  14. /// ```rust
  15. /// define_event_trace!(
  16. /// TEST2,
  17. /// TP_PROTO(a: u32, b: u32),
  18. /// TP_STRUCT__entry{
  19. /// a: u32,
  20. /// b: u32,
  21. /// },
  22. /// TP_fast_assign{
  23. /// a:a,
  24. /// b:{
  25. /// // do something with b
  26. /// b
  27. /// }
  28. /// },
  29. /// TP_ident(__entry),
  30. /// TP_printk({
  31. /// // do something with __entry
  32. /// format!("Hello from tracepoint! a={}, b={}", __entry.a, __entry.b)
  33. /// })
  34. /// );
  35. /// ```
  36. #[macro_export]
  37. macro_rules! define_event_trace{
  38. (
  39. $name:ident,
  40. TP_system($system:ident),
  41. TP_PROTO($($arg:ident:$arg_type:ty),*),
  42. TP_STRUCT__entry{$($entry:ident:$entry_type:ty,)*},
  43. TP_fast_assign{$($assign:ident:$value:expr,)*},
  44. TP_ident($tp_ident:ident),
  45. TP_printk($fmt_expr: expr)
  46. ) => {
  47. paste::paste!{
  48. static_keys::define_static_key_false!([<__ $name _KEY>]);
  49. #[allow(non_upper_case_globals)]
  50. #[used]
  51. static [<__ $name>]: $crate::tracepoint::TracePoint = $crate::tracepoint::TracePoint::new(&[<__ $name _KEY>],stringify!($name), stringify!($system),[<trace_fmt_ $name>], [<trace_fmt_show $name>]);
  52. #[inline(always)]
  53. #[allow(non_snake_case)]
  54. pub fn [<trace_ $name>]( $($arg:$arg_type),* ){
  55. if static_keys::static_branch_unlikely!([<__ $name _KEY>]){
  56. let mut f = |trace_func: &$crate::tracepoint::TracePointFunc |{
  57. let func = trace_func.func;
  58. let data = trace_func.data.as_ref();
  59. let func = unsafe{core::mem::transmute::<fn(),fn(& (dyn core::any::Any+Send+Sync), $($arg_type),*)>(func)};
  60. func(data $(,$arg)*);
  61. };
  62. let trace_point = &[<__ $name>];
  63. trace_point.callback_list(&mut f);
  64. }
  65. }
  66. #[allow(unused,non_snake_case)]
  67. pub fn [<register_trace_ $name>](func: fn(& (dyn core::any::Any+Send+Sync), $($arg_type),*), data: alloc::boxed::Box<dyn core::any::Any+Send+Sync>){
  68. let func = unsafe{core::mem::transmute::<fn(& (dyn core::any::Any+Send+Sync), $($arg_type),*), fn()>(func)};
  69. [<__ $name>].register(func,data);
  70. }
  71. #[allow(unused,non_snake_case)]
  72. pub fn [<unregister_trace_ $name>](func: fn(& (dyn core::any::Any+Send+Sync), $($arg_type),*)){
  73. let func = unsafe{core::mem::transmute::<fn(& (dyn core::any::Any+Send+Sync), $($arg_type),*), fn()>(func)};
  74. [<__ $name>].unregister(func);
  75. }
  76. #[derive(Debug)]
  77. #[repr(C)]
  78. #[allow(non_snake_case,non_camel_case_types)]
  79. struct [<__ $name _TracePointMeta>]{
  80. trace_point: &'static $crate::tracepoint::TracePoint,
  81. print_func: fn(&mut (dyn core::any::Any+Send+Sync), $($arg_type),*),
  82. }
  83. #[allow(non_upper_case_globals)]
  84. #[link_section = ".tracepoint"]
  85. #[used]
  86. static [<__ $name _meta>]: [<__ $name _TracePointMeta>] = [<__ $name _TracePointMeta>]{
  87. trace_point:& [<__ $name>],
  88. print_func:[<trace_default_ $name>],
  89. };
  90. #[allow(unused,non_snake_case)]
  91. #[allow(clippy::redundant_field_names)]
  92. pub fn [<trace_default_ $name>](_data:&mut (dyn core::any::Any+Send+Sync), $($arg:$arg_type),* ){
  93. #[repr(C, packed)]
  94. struct Entry {
  95. $($entry: $entry_type,)*
  96. }
  97. #[repr(C, packed)]
  98. struct FullEntry {
  99. common: $crate::tracepoint::TraceEntry,
  100. entry: Entry,
  101. }
  102. let entry = Entry {
  103. $($assign: $value,)*
  104. };
  105. let process = $crate::process::ProcessManager::current_pcb();
  106. let pid = process.pid().data() as _;
  107. let common = $crate::tracepoint::TraceEntry {
  108. type_: [<__ $name>].id() as _,
  109. flags: [<__ $name>].flags(),
  110. preempt_count: 0,
  111. pid,
  112. };
  113. let full_entry = FullEntry {
  114. common,
  115. entry,
  116. };
  117. let event_buf = unsafe {
  118. core::slice::from_raw_parts(
  119. &full_entry as *const FullEntry as *const u8,
  120. core::mem::size_of::<FullEntry>(),
  121. )
  122. };
  123. let func = |f:&alloc::boxed::Box<dyn $crate::tracepoint::TracePointCallBackFunc>|{
  124. f.call(event_buf);
  125. };
  126. [<__ $name>].raw_callback_list(&func);
  127. $crate::debug::tracing::trace_cmdline_push(pid as u32);
  128. $crate::debug::tracing::trace_pipe_push_raw_record(event_buf);
  129. }
  130. #[allow(unused,non_snake_case)]
  131. pub fn [<trace_fmt_ $name>](buf: &[u8]) -> alloc::string::String {
  132. #[repr(C)]
  133. struct Entry {
  134. $($entry: $entry_type,)*
  135. }
  136. let $tp_ident = unsafe {
  137. &*(buf.as_ptr() as *const Entry)
  138. };
  139. let fmt = format!("{}", $fmt_expr);
  140. fmt
  141. }
  142. #[allow(unused,non_snake_case)]
  143. pub fn [<trace_fmt_show $name>]()-> alloc::string::String {
  144. let mut fmt = format!("format:
  145. \tfield: u16 common_type; offset: 0; size: 2; signed: 0;
  146. \tfield: u8 common_flags; offset: 2; size: 1; signed: 0;
  147. \tfield: u8 common_preempt_count; offset: 3; size: 1; signed: 0;
  148. \tfield: i32 common_pid; offset: 4; size: 4; signed: 1;
  149. ");
  150. fn is_signed<T>() -> bool {
  151. match core::any::type_name::<T>() {
  152. "i8" | "i16" | "i32" | "i64" | "i128" | "isize" => true,
  153. _ => false,
  154. }
  155. }
  156. let mut offset = 8;
  157. $(
  158. fmt.push_str(&format!("\tfield: {} {} offset: {}; size: {}; signed: {};\n",
  159. stringify!($entry_type), stringify!($entry), offset, core::mem::size_of::<$entry_type>(), if is_signed::<$entry_type>() { 1 } else { 0 }));
  160. offset += core::mem::size_of::<$entry_type>();
  161. )*
  162. fmt.push_str(&format!("\nprint fmt: \"{}\"", stringify!($fmt_expr)));
  163. fmt
  164. }
  165. }
  166. };
  167. }