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