function-graph: add proper initialization for init task
[deliverable/linux.git] / kernel / trace / trace_sched_switch.c
CommitLineData
35e8e302
SR
1/*
2 * trace context switch
3 *
4 * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com>
5 *
6 */
7#include <linux/module.h>
8#include <linux/fs.h>
9#include <linux/debugfs.h>
10#include <linux/kallsyms.h>
11#include <linux/uaccess.h>
35e8e302 12#include <linux/ftrace.h>
b07c3f19 13#include <trace/sched.h>
35e8e302
SR
14
15#include "trace.h"
16
17static struct trace_array *ctx_trace;
18static int __read_mostly tracer_enabled;
efade6e7
FW
19static int sched_ref;
20static DEFINE_MUTEX(sched_register_mutex);
5fec6ddc 21static int sched_stopped;
35e8e302 22
e309b41d 23static void
b07c3f19 24probe_sched_switch(struct rq *__rq, struct task_struct *prev,
5b82a1b0 25 struct task_struct *next)
35e8e302 26{
35e8e302
SR
27 struct trace_array_cpu *data;
28 unsigned long flags;
35e8e302 29 int cpu;
38697053 30 int pc;
35e8e302 31
5fec6ddc 32 if (!sched_ref || sched_stopped)
b07c3f19
MD
33 return;
34
41bc8144
SR
35 tracing_record_cmdline(prev);
36 tracing_record_cmdline(next);
37
35e8e302
SR
38 if (!tracer_enabled)
39 return;
40
38697053 41 pc = preempt_count();
18cef379 42 local_irq_save(flags);
35e8e302 43 cpu = raw_smp_processor_id();
b07c3f19 44 data = ctx_trace->data[cpu];
35e8e302 45
3ea2e6d7 46 if (likely(!atomic_read(&data->disabled)))
7be42151 47 tracing_sched_switch_trace(ctx_trace, prev, next, flags, pc);
35e8e302 48
18cef379 49 local_irq_restore(flags);
35e8e302
SR
50}
51
4e655519 52static void
468a15bb 53probe_sched_wakeup(struct rq *__rq, struct task_struct *wakee, int success)
57422797 54{
57422797
IM
55 struct trace_array_cpu *data;
56 unsigned long flags;
38697053 57 int cpu, pc;
57422797 58
b07c3f19 59 if (!likely(tracer_enabled))
57422797
IM
60 return;
61
38697053 62 pc = preempt_count();
b07c3f19 63 tracing_record_cmdline(current);
d9af56fb 64
57422797
IM
65 local_irq_save(flags);
66 cpu = raw_smp_processor_id();
b07c3f19 67 data = ctx_trace->data[cpu];
57422797 68
3ea2e6d7 69 if (likely(!atomic_read(&data->disabled)))
7be42151 70 tracing_sched_wakeup_trace(ctx_trace, wakee, current,
38697053 71 flags, pc);
57422797 72
57422797
IM
73 local_irq_restore(flags);
74}
75
5b82a1b0
MD
76static int tracing_sched_register(void)
77{
78 int ret;
79
b07c3f19 80 ret = register_trace_sched_wakeup(probe_sched_wakeup);
5b82a1b0 81 if (ret) {
b07c3f19 82 pr_info("wakeup trace: Couldn't activate tracepoint"
5b82a1b0
MD
83 " probe to kernel_sched_wakeup\n");
84 return ret;
85 }
86
b07c3f19 87 ret = register_trace_sched_wakeup_new(probe_sched_wakeup);
5b82a1b0 88 if (ret) {
b07c3f19 89 pr_info("wakeup trace: Couldn't activate tracepoint"
5b82a1b0
MD
90 " probe to kernel_sched_wakeup_new\n");
91 goto fail_deprobe;
92 }
93
b07c3f19 94 ret = register_trace_sched_switch(probe_sched_switch);
5b82a1b0 95 if (ret) {
b07c3f19 96 pr_info("sched trace: Couldn't activate tracepoint"
73d8b8bc 97 " probe to kernel_sched_switch\n");
5b82a1b0
MD
98 goto fail_deprobe_wake_new;
99 }
100
101 return ret;
102fail_deprobe_wake_new:
b07c3f19 103 unregister_trace_sched_wakeup_new(probe_sched_wakeup);
5b82a1b0 104fail_deprobe:
b07c3f19 105 unregister_trace_sched_wakeup(probe_sched_wakeup);
5b82a1b0
MD
106 return ret;
107}
108
109static void tracing_sched_unregister(void)
110{
b07c3f19
MD
111 unregister_trace_sched_switch(probe_sched_switch);
112 unregister_trace_sched_wakeup_new(probe_sched_wakeup);
113 unregister_trace_sched_wakeup(probe_sched_wakeup);
5b82a1b0
MD
114}
115
f2252935 116static void tracing_start_sched_switch(void)
5b82a1b0 117{
efade6e7 118 mutex_lock(&sched_register_mutex);
e168e051 119 if (!(sched_ref++))
5b82a1b0 120 tracing_sched_register();
efade6e7 121 mutex_unlock(&sched_register_mutex);
5b82a1b0
MD
122}
123
f2252935 124static void tracing_stop_sched_switch(void)
5b82a1b0 125{
efade6e7 126 mutex_lock(&sched_register_mutex);
e168e051 127 if (!(--sched_ref))
5b82a1b0 128 tracing_sched_unregister();
efade6e7 129 mutex_unlock(&sched_register_mutex);
5b82a1b0
MD
130}
131
41bc8144
SR
132void tracing_start_cmdline_record(void)
133{
134 tracing_start_sched_switch();
135}
136
137void tracing_stop_cmdline_record(void)
138{
139 tracing_stop_sched_switch();
140}
141
75f5c47d 142/**
e168e051
SR
143 * tracing_start_sched_switch_record - start tracing context switches
144 *
145 * Turns on context switch tracing for a tracer.
146 */
147void tracing_start_sched_switch_record(void)
148{
149 if (unlikely(!ctx_trace)) {
150 WARN_ON(1);
151 return;
152 }
153
154 tracing_start_sched_switch();
155
156 mutex_lock(&sched_register_mutex);
157 tracer_enabled++;
158 mutex_unlock(&sched_register_mutex);
159}
160
161/**
162 * tracing_stop_sched_switch_record - start tracing context switches
163 *
164 * Turns off context switch tracing for a tracer.
165 */
166void tracing_stop_sched_switch_record(void)
167{
168 mutex_lock(&sched_register_mutex);
169 tracer_enabled--;
170 WARN_ON(tracer_enabled < 0);
171 mutex_unlock(&sched_register_mutex);
172
173 tracing_stop_sched_switch();
174}
175
176/**
177 * tracing_sched_switch_assign_trace - assign a trace array for ctx switch
75f5c47d
SR
178 * @tr: trace array pointer to assign
179 *
180 * Some tracers might want to record the context switches in their
181 * trace. This function lets those tracers assign the trace array
182 * to use.
183 */
e168e051 184void tracing_sched_switch_assign_trace(struct trace_array *tr)
75f5c47d
SR
185{
186 ctx_trace = tr;
187}
188
e309b41d 189static void stop_sched_trace(struct trace_array *tr)
35e8e302 190{
e168e051 191 tracing_stop_sched_switch_record();
35e8e302
SR
192}
193
1c80025a 194static int sched_switch_trace_init(struct trace_array *tr)
35e8e302
SR
195{
196 ctx_trace = tr;
5fec6ddc 197 tracing_reset_online_cpus(tr);
b6f11df2 198 tracing_start_sched_switch_record();
1c80025a 199 return 0;
35e8e302
SR
200}
201
e309b41d 202static void sched_switch_trace_reset(struct trace_array *tr)
35e8e302 203{
c76f0694 204 if (sched_ref)
35e8e302
SR
205 stop_sched_trace(tr);
206}
207
9036990d
SR
208static void sched_switch_trace_start(struct trace_array *tr)
209{
5fec6ddc 210 sched_stopped = 0;
9036990d
SR
211}
212
213static void sched_switch_trace_stop(struct trace_array *tr)
214{
5fec6ddc 215 sched_stopped = 1;
9036990d
SR
216}
217
75f5c47d 218static struct tracer sched_switch_trace __read_mostly =
35e8e302
SR
219{
220 .name = "sched_switch",
221 .init = sched_switch_trace_init,
222 .reset = sched_switch_trace_reset,
9036990d
SR
223 .start = sched_switch_trace_start,
224 .stop = sched_switch_trace_stop,
6eaaa5d5 225 .wait_pipe = poll_wait_pipe,
60a11774
SR
226#ifdef CONFIG_FTRACE_SELFTEST
227 .selftest = trace_selftest_startup_sched_switch,
228#endif
35e8e302
SR
229};
230
231__init static int init_sched_switch_trace(void)
232{
233 return register_tracer(&sched_switch_trace);
234}
235device_initcall(init_sched_switch_trace);
c71dd42d 236
This page took 0.080626 seconds and 5 git commands to generate.