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