#[macro_export]
macro_rules! define_event_trace{
(
$name:ident,
TP_lock($lock:path),
TP_kops($kops:path),
TP_system($system:ident),
TP_PROTO($($arg:ident:$arg_type:ty),+ $(,)?),
TP_STRUCT__entry{$($entry:ident:$entry_type:ty),+ $(,)?},
TP_fast_assign{$($assign:ident:$value:expr),+ $(,)?},
TP_ident($tp_ident:ident),
TP_printk($fmt_expr: expr)
) => {
$crate::paste!{
static_keys::define_static_key_false_generic!([<__ $name _KEY>], $crate::KernelCodeManipulator<$kops>);
#[allow(non_upper_case_globals)]
#[used]
static [<__ $name>]: $crate::TracePoint<$lock, $kops> = $crate::TracePoint::new(&[<__ $name _KEY>],stringify!($name), stringify!($system),[<trace_fmt_ $name>], [<trace_fmt_show $name>]);
#[inline(always)]
#[allow(non_snake_case)]
pub fn [<trace_ $name>]( $($arg:$arg_type),* ){
if static_keys::static_branch_unlikely!([<__ $name _KEY>]){
let mut f = |trace_func: &$crate::TracePointFunc |{
let func = trace_func.func;
let data = trace_func.data.as_ref();
let func = unsafe{core::mem::transmute::<fn(),fn(& (dyn core::any::Any+Send+Sync), $($arg_type),*)>(func)};
func(data $(,$arg)*);
};
let trace_point = &[<__ $name>];
trace_point.callback_list(&mut f);
}
}
#[allow(non_snake_case)]
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>){
let func = unsafe{core::mem::transmute::<fn(& (dyn core::any::Any+Send+Sync), $($arg_type),*), fn()>(func)};
[<__ $name>].register(func,data);
}
#[allow(non_snake_case)]
pub fn [<unregister_trace_ $name>](func: fn(& (dyn core::any::Any+Send+Sync), $($arg_type),*)){
let func = unsafe{core::mem::transmute::<fn(& (dyn core::any::Any+Send+Sync), $($arg_type),*), fn()>(func)};
[<__ $name>].unregister(func);
}
#[derive(Debug)]
#[repr(C)]
#[allow(non_snake_case,non_camel_case_types)]
struct [<__ $name _TracePointMeta>]{
trace_point: &'static $crate::TracePoint<$lock, $kops>,
print_func: fn(&mut (dyn core::any::Any+Send+Sync), $($arg_type),*),
}
#[allow(non_upper_case_globals)]
#[unsafe(link_section = ".tracepoint")]
#[used]
static [<__ $name _meta>]: [<__ $name _TracePointMeta>] = [<__ $name _TracePointMeta>]{
trace_point:& [<__ $name>],
print_func:[<trace_default_ $name>]::<$kops>,
};
#[allow(non_snake_case)]
pub fn [<trace_default_ $name>]<F:$crate::KernelTraceOps>(_data:&mut (dyn core::any::Any+Send+Sync), $($arg:$arg_type),* ){
#[repr(C)]
struct Entry {
$($entry: $entry_type,)*
}
#[repr(C)]
struct FullEntry {
common: $crate::TraceEntry,
entry: Entry,
}
let entry = Entry {
$($assign: $value,)*
};
let pid = F::current_pid();
let common = $crate::TraceEntry {
type_: [<__ $name>].id() as _,
flags: [<__ $name>].flags(),
preempt_count: 0,
pid: pid as i32,
};
let full_entry = FullEntry {
common,
entry,
};
let event_buf = unsafe {
core::slice::from_raw_parts(
&full_entry as *const FullEntry as *const u8,
core::mem::size_of::<FullEntry>(),
)
};
let func = |f:&alloc::boxed::Box<dyn $crate::TracePointCallBackFunc>|{
f.call(event_buf);
};
[<__ $name>].raw_callback_list(&func);
F::trace_cmdline_push(pid);
F::trace_pipe_push_raw_record(event_buf);
}
#[allow(non_snake_case)]
pub fn [<trace_fmt_ $name>](buf: &[u8]) -> alloc::string::String {
#[repr(C)]
struct Entry {
$($entry: $entry_type,)*
}
let $tp_ident = unsafe {
&*(buf.as_ptr() as *const Entry)
};
let fmt = alloc::format!("{}", $fmt_expr);
fmt
}
#[allow(non_snake_case)]
pub fn [<trace_fmt_show $name>]()-> alloc::string::String {
let mut fmt = alloc::format!("format:
\tfield: u16 common_type; offset: 0; size: 2; signed: 0;
\tfield: u8 common_flags; offset: 2; size: 1; signed: 0;
\tfield: u8 common_preempt_count; offset: 3; size: 1; signed: 0;
\tfield: i32 common_pid; offset: 4; size: 4; signed: 1;
");
fn is_signed<T>() -> bool {
match core::any::type_name::<T>() {
"i8" | "i16" | "i32" | "i64" | "i128" | "isize" => true,
_ => false,
}
}
#[repr(C)]
struct Entry {
$($entry: $entry_type,)*
}
#[repr(C)]
struct FullEntry {
common: $crate::TraceEntry,
entry: Entry,
}
$(
let mut offset = core::mem::offset_of!(FullEntry, entry.$entry);
fmt.push_str(&alloc::format!("\tfield: {} {} offset: {}; size: {}; signed: {};\n",
stringify!($entry_type), stringify!($entry), offset, core::mem::size_of::<$entry_type>(), if is_signed::<$entry_type>() { 1 } else { 0 }));
)*
fmt.push_str(&alloc::format!("\nprint fmt: \"{}\"", stringify!($fmt_expr)));
fmt
}
}
};
}