diff options
Diffstat (limited to 'kernel/trace/trace_sched_switch.c')
-rw-r--r-- | kernel/trace/trace_sched_switch.c | 121 |
1 files changed, 75 insertions, 46 deletions
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c index b8f56beb1a62..df175cb4564f 100644 --- a/kernel/trace/trace_sched_switch.c +++ b/kernel/trace/trace_sched_switch.c | |||
@@ -16,7 +16,8 @@ | |||
16 | 16 | ||
17 | static struct trace_array *ctx_trace; | 17 | static struct trace_array *ctx_trace; |
18 | static int __read_mostly tracer_enabled; | 18 | static int __read_mostly tracer_enabled; |
19 | static atomic_t sched_ref; | 19 | static int sched_ref; |
20 | static DEFINE_MUTEX(sched_register_mutex); | ||
20 | 21 | ||
21 | static void | 22 | static void |
22 | probe_sched_switch(struct rq *__rq, struct task_struct *prev, | 23 | probe_sched_switch(struct rq *__rq, struct task_struct *prev, |
@@ -27,7 +28,7 @@ probe_sched_switch(struct rq *__rq, struct task_struct *prev, | |||
27 | int cpu; | 28 | int cpu; |
28 | int pc; | 29 | int pc; |
29 | 30 | ||
30 | if (!atomic_read(&sched_ref)) | 31 | if (!sched_ref) |
31 | return; | 32 | return; |
32 | 33 | ||
33 | tracing_record_cmdline(prev); | 34 | tracing_record_cmdline(prev); |
@@ -48,7 +49,7 @@ probe_sched_switch(struct rq *__rq, struct task_struct *prev, | |||
48 | } | 49 | } |
49 | 50 | ||
50 | static void | 51 | static void |
51 | probe_sched_wakeup(struct rq *__rq, struct task_struct *wakee) | 52 | probe_sched_wakeup(struct rq *__rq, struct task_struct *wakee, int success) |
52 | { | 53 | { |
53 | struct trace_array_cpu *data; | 54 | struct trace_array_cpu *data; |
54 | unsigned long flags; | 55 | unsigned long flags; |
@@ -71,16 +72,6 @@ probe_sched_wakeup(struct rq *__rq, struct task_struct *wakee) | |||
71 | local_irq_restore(flags); | 72 | local_irq_restore(flags); |
72 | } | 73 | } |
73 | 74 | ||
74 | static void sched_switch_reset(struct trace_array *tr) | ||
75 | { | ||
76 | int cpu; | ||
77 | |||
78 | tr->time_start = ftrace_now(tr->cpu); | ||
79 | |||
80 | for_each_online_cpu(cpu) | ||
81 | tracing_reset(tr, cpu); | ||
82 | } | ||
83 | |||
84 | static int tracing_sched_register(void) | 75 | static int tracing_sched_register(void) |
85 | { | 76 | { |
86 | int ret; | 77 | int ret; |
@@ -123,20 +114,18 @@ static void tracing_sched_unregister(void) | |||
123 | 114 | ||
124 | static void tracing_start_sched_switch(void) | 115 | static void tracing_start_sched_switch(void) |
125 | { | 116 | { |
126 | long ref; | 117 | mutex_lock(&sched_register_mutex); |
127 | 118 | if (!(sched_ref++)) | |
128 | ref = atomic_inc_return(&sched_ref); | ||
129 | if (ref == 1) | ||
130 | tracing_sched_register(); | 119 | tracing_sched_register(); |
120 | mutex_unlock(&sched_register_mutex); | ||
131 | } | 121 | } |
132 | 122 | ||
133 | static void tracing_stop_sched_switch(void) | 123 | static void tracing_stop_sched_switch(void) |
134 | { | 124 | { |
135 | long ref; | 125 | mutex_lock(&sched_register_mutex); |
136 | 126 | if (!(--sched_ref)) | |
137 | ref = atomic_dec_and_test(&sched_ref); | ||
138 | if (ref) | ||
139 | tracing_sched_unregister(); | 127 | tracing_sched_unregister(); |
128 | mutex_unlock(&sched_register_mutex); | ||
140 | } | 129 | } |
141 | 130 | ||
142 | void tracing_start_cmdline_record(void) | 131 | void tracing_start_cmdline_record(void) |
@@ -149,40 +138,86 @@ void tracing_stop_cmdline_record(void) | |||
149 | tracing_stop_sched_switch(); | 138 | tracing_stop_sched_switch(); |
150 | } | 139 | } |
151 | 140 | ||
141 | /** | ||
142 | * tracing_start_sched_switch_record - start tracing context switches | ||
143 | * | ||
144 | * Turns on context switch tracing for a tracer. | ||
145 | */ | ||
146 | void tracing_start_sched_switch_record(void) | ||
147 | { | ||
148 | if (unlikely(!ctx_trace)) { | ||
149 | WARN_ON(1); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | tracing_start_sched_switch(); | ||
154 | |||
155 | mutex_lock(&sched_register_mutex); | ||
156 | tracer_enabled++; | ||
157 | mutex_unlock(&sched_register_mutex); | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * tracing_stop_sched_switch_record - start tracing context switches | ||
162 | * | ||
163 | * Turns off context switch tracing for a tracer. | ||
164 | */ | ||
165 | void tracing_stop_sched_switch_record(void) | ||
166 | { | ||
167 | mutex_lock(&sched_register_mutex); | ||
168 | tracer_enabled--; | ||
169 | WARN_ON(tracer_enabled < 0); | ||
170 | mutex_unlock(&sched_register_mutex); | ||
171 | |||
172 | tracing_stop_sched_switch(); | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * tracing_sched_switch_assign_trace - assign a trace array for ctx switch | ||
177 | * @tr: trace array pointer to assign | ||
178 | * | ||
179 | * Some tracers might want to record the context switches in their | ||
180 | * trace. This function lets those tracers assign the trace array | ||
181 | * to use. | ||
182 | */ | ||
183 | void tracing_sched_switch_assign_trace(struct trace_array *tr) | ||
184 | { | ||
185 | ctx_trace = tr; | ||
186 | } | ||
187 | |||
152 | static void start_sched_trace(struct trace_array *tr) | 188 | static void start_sched_trace(struct trace_array *tr) |
153 | { | 189 | { |
154 | sched_switch_reset(tr); | 190 | tracing_reset_online_cpus(tr); |
155 | tracing_start_cmdline_record(); | 191 | tracing_start_sched_switch_record(); |
156 | tracer_enabled = 1; | ||
157 | } | 192 | } |
158 | 193 | ||
159 | static void stop_sched_trace(struct trace_array *tr) | 194 | static void stop_sched_trace(struct trace_array *tr) |
160 | { | 195 | { |
161 | tracer_enabled = 0; | 196 | tracing_stop_sched_switch_record(); |
162 | tracing_stop_cmdline_record(); | ||
163 | } | 197 | } |
164 | 198 | ||
165 | static void sched_switch_trace_init(struct trace_array *tr) | 199 | static int sched_switch_trace_init(struct trace_array *tr) |
166 | { | 200 | { |
167 | ctx_trace = tr; | 201 | ctx_trace = tr; |
168 | 202 | start_sched_trace(tr); | |
169 | if (tr->ctrl) | 203 | return 0; |
170 | start_sched_trace(tr); | ||
171 | } | 204 | } |
172 | 205 | ||
173 | static void sched_switch_trace_reset(struct trace_array *tr) | 206 | static void sched_switch_trace_reset(struct trace_array *tr) |
174 | { | 207 | { |
175 | if (tr->ctrl) | 208 | if (sched_ref) |
176 | stop_sched_trace(tr); | 209 | stop_sched_trace(tr); |
177 | } | 210 | } |
178 | 211 | ||
179 | static void sched_switch_trace_ctrl_update(struct trace_array *tr) | 212 | static void sched_switch_trace_start(struct trace_array *tr) |
180 | { | 213 | { |
181 | /* When starting a new trace, reset the buffers */ | 214 | tracing_reset_online_cpus(tr); |
182 | if (tr->ctrl) | 215 | tracing_start_sched_switch(); |
183 | start_sched_trace(tr); | 216 | } |
184 | else | 217 | |
185 | stop_sched_trace(tr); | 218 | static void sched_switch_trace_stop(struct trace_array *tr) |
219 | { | ||
220 | tracing_stop_sched_switch(); | ||
186 | } | 221 | } |
187 | 222 | ||
188 | static struct tracer sched_switch_trace __read_mostly = | 223 | static struct tracer sched_switch_trace __read_mostly = |
@@ -190,7 +225,8 @@ static struct tracer sched_switch_trace __read_mostly = | |||
190 | .name = "sched_switch", | 225 | .name = "sched_switch", |
191 | .init = sched_switch_trace_init, | 226 | .init = sched_switch_trace_init, |
192 | .reset = sched_switch_trace_reset, | 227 | .reset = sched_switch_trace_reset, |
193 | .ctrl_update = sched_switch_trace_ctrl_update, | 228 | .start = sched_switch_trace_start, |
229 | .stop = sched_switch_trace_stop, | ||
194 | #ifdef CONFIG_FTRACE_SELFTEST | 230 | #ifdef CONFIG_FTRACE_SELFTEST |
195 | .selftest = trace_selftest_startup_sched_switch, | 231 | .selftest = trace_selftest_startup_sched_switch, |
196 | #endif | 232 | #endif |
@@ -198,14 +234,7 @@ static struct tracer sched_switch_trace __read_mostly = | |||
198 | 234 | ||
199 | __init static int init_sched_switch_trace(void) | 235 | __init static int init_sched_switch_trace(void) |
200 | { | 236 | { |
201 | int ret = 0; | ||
202 | |||
203 | if (atomic_read(&sched_ref)) | ||
204 | ret = tracing_sched_register(); | ||
205 | if (ret) { | ||
206 | pr_info("error registering scheduler trace\n"); | ||
207 | return ret; | ||
208 | } | ||
209 | return register_tracer(&sched_switch_trace); | 237 | return register_tracer(&sched_switch_trace); |
210 | } | 238 | } |
211 | device_initcall(init_sched_switch_trace); | 239 | device_initcall(init_sched_switch_trace); |
240 | |||