mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-23 20:24:12 +08:00
tracing: Add TRACE_EVENT_FN example
If a function should be called before a tracepoint is enabled and/or after it is disabled, the TRACE_EVENT_FN() serves this purpose. But it is not well documented. Having it as a sample would help developers to know how to use it. Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
This commit is contained in:
parent
c4c7eb2938
commit
6adc13f8c0
@ -49,6 +49,52 @@ static int simple_thread(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct task_struct *simple_tsk;
|
static struct task_struct *simple_tsk;
|
||||||
|
static struct task_struct *simple_tsk_fn;
|
||||||
|
|
||||||
|
static void simple_thread_func_fn(int cnt)
|
||||||
|
{
|
||||||
|
set_current_state(TASK_INTERRUPTIBLE);
|
||||||
|
schedule_timeout(HZ);
|
||||||
|
|
||||||
|
/* More silly tracepoints */
|
||||||
|
trace_foo_bar_with_fn("Look at me", cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int simple_thread_fn(void *arg)
|
||||||
|
{
|
||||||
|
int cnt = 0;
|
||||||
|
|
||||||
|
while (!kthread_should_stop())
|
||||||
|
simple_thread_func_fn(cnt++);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFINE_MUTEX(thread_mutex);
|
||||||
|
|
||||||
|
void foo_bar_reg(void)
|
||||||
|
{
|
||||||
|
pr_info("Starting thread for foo_bar_fn\n");
|
||||||
|
/*
|
||||||
|
* We shouldn't be able to start a trace when the module is
|
||||||
|
* unloading (there's other locks to prevent that). But
|
||||||
|
* for consistency sake, we still take the thread_mutex.
|
||||||
|
*/
|
||||||
|
mutex_lock(&thread_mutex);
|
||||||
|
simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn");
|
||||||
|
mutex_unlock(&thread_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void foo_bar_unreg(void)
|
||||||
|
{
|
||||||
|
pr_info("Killing thread for foo_bar_fn\n");
|
||||||
|
/* protect against module unloading */
|
||||||
|
mutex_lock(&thread_mutex);
|
||||||
|
if (simple_tsk_fn)
|
||||||
|
kthread_stop(simple_tsk_fn);
|
||||||
|
simple_tsk_fn = NULL;
|
||||||
|
mutex_unlock(&thread_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
static int __init trace_event_init(void)
|
static int __init trace_event_init(void)
|
||||||
{
|
{
|
||||||
@ -62,6 +108,11 @@ static int __init trace_event_init(void)
|
|||||||
static void __exit trace_event_exit(void)
|
static void __exit trace_event_exit(void)
|
||||||
{
|
{
|
||||||
kthread_stop(simple_tsk);
|
kthread_stop(simple_tsk);
|
||||||
|
mutex_lock(&thread_mutex);
|
||||||
|
if (simple_tsk_fn)
|
||||||
|
kthread_stop(simple_tsk_fn);
|
||||||
|
simple_tsk_fn = NULL;
|
||||||
|
mutex_unlock(&thread_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(trace_event_init);
|
module_init(trace_event_init);
|
||||||
|
@ -270,6 +270,50 @@ TRACE_EVENT_CONDITION(foo_bar_with_cond,
|
|||||||
|
|
||||||
TP_printk("foo %s %d", __get_str(foo), __entry->bar)
|
TP_printk("foo %s %d", __get_str(foo), __entry->bar)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
void foo_bar_reg(void);
|
||||||
|
void foo_bar_unreg(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Now in the case that some function needs to be called when the
|
||||||
|
* tracepoint is enabled and/or when it is disabled, the
|
||||||
|
* TRACE_EVENT_FN() serves this purpose. This is just like TRACE_EVENT()
|
||||||
|
* but adds two more parameters at the end:
|
||||||
|
*
|
||||||
|
* TRACE_EVENT_FN( name, proto, args, struct, assign, printk, reg, unreg)
|
||||||
|
*
|
||||||
|
* reg and unreg are functions with the prototype of:
|
||||||
|
*
|
||||||
|
* void reg(void)
|
||||||
|
*
|
||||||
|
* The reg function gets called before the tracepoint is enabled, and
|
||||||
|
* the unreg function gets called after the tracepoint is disabled.
|
||||||
|
*
|
||||||
|
* Note, reg and unreg are allowed to be NULL. If you only need to
|
||||||
|
* call a function before enabling, or after disabling, just set one
|
||||||
|
* function and pass in NULL for the other parameter.
|
||||||
|
*/
|
||||||
|
TRACE_EVENT_FN(foo_bar_with_fn,
|
||||||
|
|
||||||
|
TP_PROTO(const char *foo, int bar),
|
||||||
|
|
||||||
|
TP_ARGS(foo, bar),
|
||||||
|
|
||||||
|
TP_STRUCT__entry(
|
||||||
|
__string( foo, foo )
|
||||||
|
__field( int, bar )
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_fast_assign(
|
||||||
|
__assign_str(foo, foo);
|
||||||
|
__entry->bar = bar;
|
||||||
|
),
|
||||||
|
|
||||||
|
TP_printk("foo %s %d", __get_str(foo), __entry->bar),
|
||||||
|
|
||||||
|
foo_bar_reg, foo_bar_unreg
|
||||||
|
);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***** NOTICE! The #if protection ends here. *****/
|
/***** NOTICE! The #if protection ends here. *****/
|
||||||
|
Loading…
Reference in New Issue
Block a user