diff options
| author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2015-02-09 16:32:19 -0500 |
|---|---|---|
| committer | Steven Rostedt <rostedt@goodmis.org> | 2015-02-09 18:05:39 -0500 |
| commit | 6adc13f8c096736957444ffa2aa11421b5671aef (patch) | |
| tree | 705f6ba74c25d29405f80e339a6562c81d145018 /samples/trace_events | |
| parent | c4c7eb29382c456b9be9858c357a490ae0ccd0f6 (diff) | |
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>
Diffstat (limited to 'samples/trace_events')
| -rw-r--r-- | samples/trace_events/trace-events-sample.c | 51 | ||||
| -rw-r--r-- | samples/trace_events/trace-events-sample.h | 44 |
2 files changed, 95 insertions, 0 deletions
diff --git a/samples/trace_events/trace-events-sample.c b/samples/trace_events/trace-events-sample.c index c396a49b5d78..39d4484aef53 100644 --- a/samples/trace_events/trace-events-sample.c +++ b/samples/trace_events/trace-events-sample.c | |||
| @@ -49,6 +49,52 @@ static int simple_thread(void *arg) | |||
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | static struct task_struct *simple_tsk; | 51 | static struct task_struct *simple_tsk; |
| 52 | static struct task_struct *simple_tsk_fn; | ||
| 53 | |||
| 54 | static void simple_thread_func_fn(int cnt) | ||
| 55 | { | ||
| 56 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 57 | schedule_timeout(HZ); | ||
| 58 | |||
| 59 | /* More silly tracepoints */ | ||
| 60 | trace_foo_bar_with_fn("Look at me", cnt); | ||
| 61 | } | ||
| 62 | |||
| 63 | static int simple_thread_fn(void *arg) | ||
| 64 | { | ||
| 65 | int cnt = 0; | ||
| 66 | |||
| 67 | while (!kthread_should_stop()) | ||
| 68 | simple_thread_func_fn(cnt++); | ||
| 69 | |||
| 70 | return 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static DEFINE_MUTEX(thread_mutex); | ||
| 74 | |||
| 75 | void foo_bar_reg(void) | ||
| 76 | { | ||
| 77 | pr_info("Starting thread for foo_bar_fn\n"); | ||
| 78 | /* | ||
| 79 | * We shouldn't be able to start a trace when the module is | ||
| 80 | * unloading (there's other locks to prevent that). But | ||
| 81 | * for consistency sake, we still take the thread_mutex. | ||
| 82 | */ | ||
| 83 | mutex_lock(&thread_mutex); | ||
| 84 | simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn"); | ||
| 85 | mutex_unlock(&thread_mutex); | ||
| 86 | } | ||
| 87 | |||
| 88 | void foo_bar_unreg(void) | ||
| 89 | { | ||
| 90 | pr_info("Killing thread for foo_bar_fn\n"); | ||
| 91 | /* protect against module unloading */ | ||
| 92 | mutex_lock(&thread_mutex); | ||
| 93 | if (simple_tsk_fn) | ||
| 94 | kthread_stop(simple_tsk_fn); | ||
| 95 | simple_tsk_fn = NULL; | ||
| 96 | mutex_unlock(&thread_mutex); | ||
| 97 | } | ||
| 52 | 98 | ||
| 53 | static int __init trace_event_init(void) | 99 | static int __init trace_event_init(void) |
| 54 | { | 100 | { |
| @@ -62,6 +108,11 @@ static int __init trace_event_init(void) | |||
| 62 | static void __exit trace_event_exit(void) | 108 | static void __exit trace_event_exit(void) |
| 63 | { | 109 | { |
| 64 | kthread_stop(simple_tsk); | 110 | kthread_stop(simple_tsk); |
| 111 | mutex_lock(&thread_mutex); | ||
| 112 | if (simple_tsk_fn) | ||
| 113 | kthread_stop(simple_tsk_fn); | ||
| 114 | simple_tsk_fn = NULL; | ||
| 115 | mutex_unlock(&thread_mutex); | ||
| 65 | } | 116 | } |
| 66 | 117 | ||
| 67 | module_init(trace_event_init); | 118 | module_init(trace_event_init); |
diff --git a/samples/trace_events/trace-events-sample.h b/samples/trace_events/trace-events-sample.h index c3232340914d..d0be8411b527 100644 --- a/samples/trace_events/trace-events-sample.h +++ b/samples/trace_events/trace-events-sample.h | |||
| @@ -270,6 +270,50 @@ TRACE_EVENT_CONDITION(foo_bar_with_cond, | |||
| 270 | 270 | ||
| 271 | TP_printk("foo %s %d", __get_str(foo), __entry->bar) | 271 | TP_printk("foo %s %d", __get_str(foo), __entry->bar) |
| 272 | ); | 272 | ); |
| 273 | |||
| 274 | void foo_bar_reg(void); | ||
| 275 | void foo_bar_unreg(void); | ||
| 276 | |||
| 277 | /* | ||
| 278 | * Now in the case that some function needs to be called when the | ||
| 279 | * tracepoint is enabled and/or when it is disabled, the | ||
| 280 | * TRACE_EVENT_FN() serves this purpose. This is just like TRACE_EVENT() | ||
| 281 | * but adds two more parameters at the end: | ||
| 282 | * | ||
| 283 | * TRACE_EVENT_FN( name, proto, args, struct, assign, printk, reg, unreg) | ||
| 284 | * | ||
| 285 | * reg and unreg are functions with the prototype of: | ||
| 286 | * | ||
| 287 | * void reg(void) | ||
| 288 | * | ||
| 289 | * The reg function gets called before the tracepoint is enabled, and | ||
| 290 | * the unreg function gets called after the tracepoint is disabled. | ||
| 291 | * | ||
| 292 | * Note, reg and unreg are allowed to be NULL. If you only need to | ||
| 293 | * call a function before enabling, or after disabling, just set one | ||
| 294 | * function and pass in NULL for the other parameter. | ||
| 295 | */ | ||
| 296 | TRACE_EVENT_FN(foo_bar_with_fn, | ||
| 297 | |||
| 298 | TP_PROTO(const char *foo, int bar), | ||
| 299 | |||
| 300 | TP_ARGS(foo, bar), | ||
| 301 | |||
| 302 | TP_STRUCT__entry( | ||
| 303 | __string( foo, foo ) | ||
| 304 | __field( int, bar ) | ||
| 305 | ), | ||
| 306 | |||
| 307 | TP_fast_assign( | ||
| 308 | __assign_str(foo, foo); | ||
| 309 | __entry->bar = bar; | ||
| 310 | ), | ||
| 311 | |||
| 312 | TP_printk("foo %s %d", __get_str(foo), __entry->bar), | ||
| 313 | |||
| 314 | foo_bar_reg, foo_bar_unreg | ||
| 315 | ); | ||
| 316 | |||
| 273 | #endif | 317 | #endif |
| 274 | 318 | ||
| 275 | /***** NOTICE! The #if protection ends here. *****/ | 319 | /***** NOTICE! The #if protection ends here. *****/ |
