Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6adc13f8 authored by Steven Rostedt (Red Hat)'s avatar Steven Rostedt (Red Hat) Committed by Steven Rostedt
Browse files

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: default avatarSteven Rostedt <rostedt@goodmis.org>
parent c4c7eb29
Loading
Loading
Loading
Loading
+51 −0
Original line number Diff line number Diff line
@@ -49,6 +49,52 @@ static int simple_thread(void *arg)
}

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)
{
@@ -62,6 +108,11 @@ static int __init trace_event_init(void)
static void __exit trace_event_exit(void)
{
	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);
+44 −0
Original line number Diff line number Diff line
@@ -270,6 +270,50 @@ TRACE_EVENT_CONDITION(foo_bar_with_cond,

	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

/***** NOTICE! The #if protection ends here. *****/