trace-events-sample.c (3034B)
1// SPDX-License-Identifier: GPL-2.0-only 2#include <linux/module.h> 3#include <linux/kthread.h> 4 5/* 6 * Any file that uses trace points, must include the header. 7 * But only one file, must include the header by defining 8 * CREATE_TRACE_POINTS first. This will make the C code that 9 * creates the handles for the trace points. 10 */ 11#define CREATE_TRACE_POINTS 12#include "trace-events-sample.h" 13 14static const char *random_strings[] = { 15 "Mother Goose", 16 "Snoopy", 17 "Gandalf", 18 "Frodo", 19 "One ring to rule them all" 20}; 21 22static void simple_thread_func(int cnt) 23{ 24 unsigned long bitmask[1] = {0xdeadbeefUL}; 25 int array[6]; 26 int len = cnt % 5; 27 int i; 28 29 set_current_state(TASK_INTERRUPTIBLE); 30 schedule_timeout(HZ); 31 32 for (i = 0; i < len; i++) 33 array[i] = i + 1; 34 array[i] = 0; 35 36 /* Silly tracepoints */ 37 trace_foo_bar("hello", cnt, array, random_strings[len], 38 current->cpus_ptr); 39 40 trace_foo_with_template_simple("HELLO", cnt); 41 42 trace_foo_bar_with_cond("Some times print", cnt); 43 44 trace_foo_with_template_cond("prints other times", cnt); 45 46 trace_foo_with_template_print("I have to be different", cnt); 47 48 trace_foo_rel_loc("Hello __rel_loc", cnt, bitmask); 49} 50 51static int simple_thread(void *arg) 52{ 53 int cnt = 0; 54 55 while (!kthread_should_stop()) 56 simple_thread_func(cnt++); 57 58 return 0; 59} 60 61static struct task_struct *simple_tsk; 62static struct task_struct *simple_tsk_fn; 63 64static void simple_thread_func_fn(int cnt) 65{ 66 set_current_state(TASK_INTERRUPTIBLE); 67 schedule_timeout(HZ); 68 69 /* More silly tracepoints */ 70 trace_foo_bar_with_fn("Look at me", cnt); 71 trace_foo_with_template_fn("Look at me too", cnt); 72} 73 74static int simple_thread_fn(void *arg) 75{ 76 int cnt = 0; 77 78 while (!kthread_should_stop()) 79 simple_thread_func_fn(cnt++); 80 81 return 0; 82} 83 84static DEFINE_MUTEX(thread_mutex); 85static int simple_thread_cnt; 86 87int foo_bar_reg(void) 88{ 89 mutex_lock(&thread_mutex); 90 if (simple_thread_cnt++) 91 goto out; 92 93 pr_info("Starting thread for foo_bar_fn\n"); 94 /* 95 * We shouldn't be able to start a trace when the module is 96 * unloading (there's other locks to prevent that). But 97 * for consistency sake, we still take the thread_mutex. 98 */ 99 simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn"); 100 out: 101 mutex_unlock(&thread_mutex); 102 return 0; 103} 104 105void foo_bar_unreg(void) 106{ 107 mutex_lock(&thread_mutex); 108 if (--simple_thread_cnt) 109 goto out; 110 111 pr_info("Killing thread for foo_bar_fn\n"); 112 if (simple_tsk_fn) 113 kthread_stop(simple_tsk_fn); 114 simple_tsk_fn = NULL; 115 out: 116 mutex_unlock(&thread_mutex); 117} 118 119static int __init trace_event_init(void) 120{ 121 simple_tsk = kthread_run(simple_thread, NULL, "event-sample"); 122 if (IS_ERR(simple_tsk)) 123 return -1; 124 125 return 0; 126} 127 128static void __exit trace_event_exit(void) 129{ 130 kthread_stop(simple_tsk); 131 mutex_lock(&thread_mutex); 132 if (simple_tsk_fn) 133 kthread_stop(simple_tsk_fn); 134 simple_tsk_fn = NULL; 135 mutex_unlock(&thread_mutex); 136} 137 138module_init(trace_event_init); 139module_exit(trace_event_exit); 140 141MODULE_AUTHOR("Steven Rostedt"); 142MODULE_DESCRIPTION("trace-events-sample"); 143MODULE_LICENSE("GPL");