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