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