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 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 48static 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 58static struct task_struct *simple_tsk; 59static struct task_struct *simple_tsk_fn; 60 61static 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 71static 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 81static DEFINE_MUTEX(thread_mutex); 82static int simple_thread_cnt; 83 84int 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 102void 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 116static 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 125static 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 135module_init(trace_event_init); 136module_exit(trace_event_exit); 137 138MODULE_AUTHOR("Steven Rostedt"); 139MODULE_DESCRIPTION("trace-events-sample"); 140MODULE_LICENSE("GPL"); 141