1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <linux/module.h> 3 #include <linux/kthread.h> 4 #include <linux/trace.h> 5 #include <linux/trace_events.h> 6 #include <linux/timer.h> 7 #include <linux/err.h> 8 #include <linux/jiffies.h> 9 10 /* 11 * Any file that uses trace points, must include the header. 12 * But only one file, must include the header by defining 13 * CREATE_TRACE_POINTS first. This will make the C code that 14 * creates the handles for the trace points. 15 */ 16 #define CREATE_TRACE_POINTS 17 #include "sample-trace-array.h" 18 19 struct trace_array *tr; 20 static void mytimer_handler(struct timer_list *unused); 21 static struct task_struct *simple_tsk; 22 23 /* 24 * mytimer: Timer setup to disable tracing for event "sample_event". This 25 * timer is only for the purposes of the sample module to demonstrate access of 26 * Ftrace instances from within kernel. 27 */ 28 static DEFINE_TIMER(mytimer, mytimer_handler); 29 30 static void mytimer_handler(struct timer_list *unused) 31 { 32 /* 33 * Disable tracing for event "sample_event". 34 */ 35 trace_array_set_clr_event(tr, "sample-subsystem", "sample_event", 36 false); 37 } 38 39 static void simple_thread_func(int count) 40 { 41 set_current_state(TASK_INTERRUPTIBLE); 42 schedule_timeout(HZ); 43 44 /* 45 * Printing count value using trace_array_printk() - trace_printk() 46 * equivalent for the instance buffers. 47 */ 48 trace_array_printk(tr, _THIS_IP_, "trace_array_printk: count=%d\n", 49 count); 50 /* 51 * Tracepoint for event "sample_event". This will print the 52 * current value of count and current jiffies. 53 */ 54 trace_sample_event(count, jiffies); 55 } 56 57 static int simple_thread(void *arg) 58 { 59 int count = 0; 60 unsigned long delay = msecs_to_jiffies(5000); 61 62 /* 63 * Enable tracing for "sample_event". 64 */ 65 trace_array_set_clr_event(tr, "sample-subsystem", "sample_event", true); 66 67 /* 68 * Adding timer - mytimer. This timer will disable tracing after 69 * delay seconds. 70 * 71 */ 72 add_timer(&mytimer); 73 mod_timer(&mytimer, jiffies+delay); 74 75 while (!kthread_should_stop()) 76 simple_thread_func(count++); 77 78 del_timer(&mytimer); 79 80 /* 81 * trace_array_put() decrements the reference counter associated with 82 * the trace array - "tr". We are done using the trace array, hence 83 * decrement the reference counter so that it can be destroyed using 84 * trace_array_destroy(). 85 */ 86 trace_array_put(tr); 87 88 return 0; 89 } 90 91 static int __init sample_trace_array_init(void) 92 { 93 /* 94 * Return a pointer to the trace array with name "sample-instance" if it 95 * exists, else create a new trace array. 96 * 97 * NOTE: This function increments the reference counter 98 * associated with the trace array - "tr". 99 */ 100 tr = trace_array_get_by_name("sample-instance"); 101 102 if (!tr) 103 return -1; 104 /* 105 * If context specific per-cpu buffers havent already been allocated. 106 */ 107 trace_printk_init_buffers(); 108 109 simple_tsk = kthread_run(simple_thread, NULL, "sample-instance"); 110 if (IS_ERR(simple_tsk)) 111 return -1; 112 return 0; 113 } 114 115 static void __exit sample_trace_array_exit(void) 116 { 117 kthread_stop(simple_tsk); 118 119 /* 120 * We are unloading our module and no longer require the trace array. 121 * Remove/destroy "tr" using trace_array_destroy() 122 */ 123 trace_array_destroy(tr); 124 } 125 126 module_init(sample_trace_array_init); 127 module_exit(sample_trace_array_exit); 128 129 MODULE_AUTHOR("Divya Indi"); 130 MODULE_DESCRIPTION("Sample module for kernel access to Ftrace instances"); 131 MODULE_LICENSE("GPL"); 132