154 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2#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 defining8 * CREATE_TRACE_POINTS first. This will make the C code that9 * creates the handles for the trace points.10 */11#define CREATE_TRACE_POINTS12#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 do_simple_thread_func(int cnt, const char *fmt, ...)23{24 unsigned long bitmask[1] = {0xdeadbeefUL};25 va_list va;26 int array[6];27 int len = cnt % 5;28 int i;29 30 set_current_state(TASK_INTERRUPTIBLE);31 schedule_timeout(HZ);32 33 for (i = 0; i < len; i++)34 array[i] = i + 1;35 array[i] = 0;36 37 va_start(va, fmt);38 39 /* Silly tracepoints */40 trace_foo_bar("hello", cnt, array, random_strings[len],41 current->cpus_ptr, fmt, &va);42 43 va_end(va);44 45 trace_foo_with_template_simple("HELLO", cnt);46 47 trace_foo_bar_with_cond("Some times print", cnt);48 49 trace_foo_with_template_cond("prints other times", cnt);50 51 trace_foo_with_template_print("I have to be different", cnt);52 53 trace_foo_rel_loc("Hello __rel_loc", cnt, bitmask, current->cpus_ptr);54}55 56static void simple_thread_func(int cnt)57{58 do_simple_thread_func(cnt, "iter=%d", cnt);59}60 61static int simple_thread(void *arg)62{63 int cnt = 0;64 65 while (!kthread_should_stop())66 simple_thread_func(cnt++);67 68 return 0;69}70 71static struct task_struct *simple_tsk;72static struct task_struct *simple_tsk_fn;73 74static void simple_thread_func_fn(int cnt)75{76 set_current_state(TASK_INTERRUPTIBLE);77 schedule_timeout(HZ);78 79 /* More silly tracepoints */80 trace_foo_bar_with_fn("Look at me", cnt);81 trace_foo_with_template_fn("Look at me too", cnt);82}83 84static int simple_thread_fn(void *arg)85{86 int cnt = 0;87 88 while (!kthread_should_stop())89 simple_thread_func_fn(cnt++);90 91 return 0;92}93 94static DEFINE_MUTEX(thread_mutex);95static int simple_thread_cnt;96 97int foo_bar_reg(void)98{99 mutex_lock(&thread_mutex);100 if (simple_thread_cnt++)101 goto out;102 103 pr_info("Starting thread for foo_bar_fn\n");104 /*105 * We shouldn't be able to start a trace when the module is106 * unloading (there's other locks to prevent that). But107 * for consistency sake, we still take the thread_mutex.108 */109 simple_tsk_fn = kthread_run(simple_thread_fn, NULL, "event-sample-fn");110 out:111 mutex_unlock(&thread_mutex);112 return 0;113}114 115void foo_bar_unreg(void)116{117 mutex_lock(&thread_mutex);118 if (--simple_thread_cnt)119 goto out;120 121 pr_info("Killing thread for foo_bar_fn\n");122 if (simple_tsk_fn)123 kthread_stop(simple_tsk_fn);124 simple_tsk_fn = NULL;125 out:126 mutex_unlock(&thread_mutex);127}128 129static int __init trace_event_init(void)130{131 simple_tsk = kthread_run(simple_thread, NULL, "event-sample");132 if (IS_ERR(simple_tsk))133 return -1;134 135 return 0;136}137 138static void __exit trace_event_exit(void)139{140 kthread_stop(simple_tsk);141 mutex_lock(&thread_mutex);142 if (simple_tsk_fn)143 kthread_stop(simple_tsk_fn);144 simple_tsk_fn = NULL;145 mutex_unlock(&thread_mutex);146}147 148module_init(trace_event_init);149module_exit(trace_event_exit);150 151MODULE_AUTHOR("Steven Rostedt");152MODULE_DESCRIPTION("trace-events-sample");153MODULE_LICENSE("GPL");154