Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
35e8e302 SR |
2 | /* |
3 | * trace context switch | |
4 | * | |
5 | * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com> | |
6 | * | |
7 | */ | |
8 | #include <linux/module.h> | |
35e8e302 SR |
9 | #include <linux/kallsyms.h> |
10 | #include <linux/uaccess.h> | |
35e8e302 | 11 | #include <linux/ftrace.h> |
ad8d75ff | 12 | #include <trace/events/sched.h> |
35e8e302 SR |
13 | |
14 | #include "trace.h" | |
15 | ||
d914ba37 JF |
16 | #define RECORD_CMDLINE 1 |
17 | #define RECORD_TGID 2 | |
18 | ||
19 | static int sched_cmdline_ref; | |
20 | static int sched_tgid_ref; | |
efade6e7 | 21 | static DEFINE_MUTEX(sched_register_mutex); |
82e04af4 | 22 | |
e309b41d | 23 | static void |
c73464b1 | 24 | probe_sched_switch(void *ignore, bool preempt, |
9c2136be DK |
25 | struct task_struct *prev, struct task_struct *next, |
26 | unsigned int prev_state) | |
35e8e302 | 27 | { |
d914ba37 JF |
28 | int flags; |
29 | ||
30 | flags = (RECORD_TGID * !!sched_tgid_ref) + | |
31 | (RECORD_CMDLINE * !!sched_cmdline_ref); | |
b07c3f19 | 32 | |
d914ba37 JF |
33 | if (!flags) |
34 | return; | |
35 | tracing_record_taskinfo_sched_switch(prev, next, flags); | |
35e8e302 SR |
36 | } |
37 | ||
4e655519 | 38 | static void |
fbd705a0 | 39 | probe_sched_wakeup(void *ignore, struct task_struct *wakee) |
57422797 | 40 | { |
d914ba37 JF |
41 | int flags; |
42 | ||
43 | flags = (RECORD_TGID * !!sched_tgid_ref) + | |
44 | (RECORD_CMDLINE * !!sched_cmdline_ref); | |
57422797 | 45 | |
d914ba37 JF |
46 | if (!flags) |
47 | return; | |
55bc8384 | 48 | tracing_record_taskinfo_sched_switch(current, wakee, flags); |
57422797 IM |
49 | } |
50 | ||
5b82a1b0 MD |
51 | static int tracing_sched_register(void) |
52 | { | |
53 | int ret; | |
54 | ||
38516ab5 | 55 | ret = register_trace_sched_wakeup(probe_sched_wakeup, NULL); |
5b82a1b0 | 56 | if (ret) { |
b07c3f19 | 57 | pr_info("wakeup trace: Couldn't activate tracepoint" |
5b82a1b0 MD |
58 | " probe to kernel_sched_wakeup\n"); |
59 | return ret; | |
60 | } | |
61 | ||
38516ab5 | 62 | ret = register_trace_sched_wakeup_new(probe_sched_wakeup, NULL); |
5b82a1b0 | 63 | if (ret) { |
b07c3f19 | 64 | pr_info("wakeup trace: Couldn't activate tracepoint" |
5b82a1b0 MD |
65 | " probe to kernel_sched_wakeup_new\n"); |
66 | goto fail_deprobe; | |
67 | } | |
68 | ||
38516ab5 | 69 | ret = register_trace_sched_switch(probe_sched_switch, NULL); |
5b82a1b0 | 70 | if (ret) { |
b07c3f19 | 71 | pr_info("sched trace: Couldn't activate tracepoint" |
73d8b8bc | 72 | " probe to kernel_sched_switch\n"); |
5b82a1b0 MD |
73 | goto fail_deprobe_wake_new; |
74 | } | |
75 | ||
76 | return ret; | |
77 | fail_deprobe_wake_new: | |
38516ab5 | 78 | unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL); |
5b82a1b0 | 79 | fail_deprobe: |
38516ab5 | 80 | unregister_trace_sched_wakeup(probe_sched_wakeup, NULL); |
5b82a1b0 MD |
81 | return ret; |
82 | } | |
83 | ||
84 | static void tracing_sched_unregister(void) | |
85 | { | |
38516ab5 SR |
86 | unregister_trace_sched_switch(probe_sched_switch, NULL); |
87 | unregister_trace_sched_wakeup_new(probe_sched_wakeup, NULL); | |
88 | unregister_trace_sched_wakeup(probe_sched_wakeup, NULL); | |
5b82a1b0 MD |
89 | } |
90 | ||
d914ba37 | 91 | static void tracing_start_sched_switch(int ops) |
5b82a1b0 | 92 | { |
64ae572b MD |
93 | bool sched_register; |
94 | ||
efade6e7 | 95 | mutex_lock(&sched_register_mutex); |
64ae572b | 96 | sched_register = (!sched_cmdline_ref && !sched_tgid_ref); |
d914ba37 JF |
97 | |
98 | switch (ops) { | |
99 | case RECORD_CMDLINE: | |
100 | sched_cmdline_ref++; | |
101 | break; | |
102 | ||
103 | case RECORD_TGID: | |
104 | sched_tgid_ref++; | |
105 | break; | |
106 | } | |
107 | ||
108 | if (sched_register && (sched_cmdline_ref || sched_tgid_ref)) | |
5b82a1b0 | 109 | tracing_sched_register(); |
efade6e7 | 110 | mutex_unlock(&sched_register_mutex); |
5b82a1b0 MD |
111 | } |
112 | ||
d914ba37 | 113 | static void tracing_stop_sched_switch(int ops) |
5b82a1b0 | 114 | { |
efade6e7 | 115 | mutex_lock(&sched_register_mutex); |
d914ba37 JF |
116 | |
117 | switch (ops) { | |
118 | case RECORD_CMDLINE: | |
119 | sched_cmdline_ref--; | |
120 | break; | |
121 | ||
122 | case RECORD_TGID: | |
123 | sched_tgid_ref--; | |
124 | break; | |
125 | } | |
126 | ||
127 | if (!sched_cmdline_ref && !sched_tgid_ref) | |
5b82a1b0 | 128 | tracing_sched_unregister(); |
efade6e7 | 129 | mutex_unlock(&sched_register_mutex); |
5b82a1b0 MD |
130 | } |
131 | ||
41bc8144 SR |
132 | void tracing_start_cmdline_record(void) |
133 | { | |
d914ba37 | 134 | tracing_start_sched_switch(RECORD_CMDLINE); |
41bc8144 SR |
135 | } |
136 | ||
137 | void tracing_stop_cmdline_record(void) | |
138 | { | |
d914ba37 JF |
139 | tracing_stop_sched_switch(RECORD_CMDLINE); |
140 | } | |
141 | ||
142 | void tracing_start_tgid_record(void) | |
143 | { | |
144 | tracing_start_sched_switch(RECORD_TGID); | |
145 | } | |
146 | ||
147 | void tracing_stop_tgid_record(void) | |
148 | { | |
149 | tracing_stop_sched_switch(RECORD_TGID); | |
41bc8144 | 150 | } |