aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-11-06 01:43:47 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-06 01:43:47 -0500
commit79c81d220c8e25163f56edcdfaf23f83a4c88e6b (patch)
tree8748e39e968aacebbf150b81cbc845582b382a47
parent3299b4dd1180762da831be5eb6adc44553eaec26 (diff)
parent79a9d461fd521f133f0e66485aa9ed09c21f5191 (diff)
Merge branch 'tracing/fastboot' into tracing/ftrace
-rw-r--r--include/linux/ftrace.h24
-rw-r--r--init/main.c4
-rw-r--r--kernel/trace/trace.c2
-rw-r--r--kernel/trace/trace.h1
-rw-r--r--kernel/trace/trace_boot.c36
-rw-r--r--kernel/trace/trace_sched_switch.c37
6 files changed, 66 insertions, 38 deletions
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index e46a7b34037c..4642959e5bda 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -234,6 +234,11 @@ ftrace_init_module(unsigned long *start, unsigned long *end) { }
234#endif 234#endif
235 235
236 236
237/*
238 * Structure which defines the trace of an initcall.
239 * You don't have to fill the func field since it is
240 * only used internally by the tracer.
241 */
237struct boot_trace { 242struct boot_trace {
238 pid_t caller; 243 pid_t caller;
239 char func[KSYM_NAME_LEN]; 244 char func[KSYM_NAME_LEN];
@@ -244,13 +249,28 @@ struct boot_trace {
244}; 249};
245 250
246#ifdef CONFIG_BOOT_TRACER 251#ifdef CONFIG_BOOT_TRACER
252/* Append the trace on the ring-buffer */
247extern void trace_boot(struct boot_trace *it, initcall_t fn); 253extern void trace_boot(struct boot_trace *it, initcall_t fn);
254
255/* Tells the tracer that smp_pre_initcall is finished.
256 * So we can start the tracing
257 */
248extern void start_boot_trace(void); 258extern void start_boot_trace(void);
249extern void stop_boot_trace(void); 259
260/* Resume the tracing of other necessary events
261 * such as sched switches
262 */
263extern void enable_boot_trace(void);
264
265/* Suspend this tracing. Actually, only sched_switches tracing have
266 * to be suspended. Initcalls doesn't need it.)
267 */
268extern void disable_boot_trace(void);
250#else 269#else
251static inline void trace_boot(struct boot_trace *it, initcall_t fn) { } 270static inline void trace_boot(struct boot_trace *it, initcall_t fn) { }
252static inline void start_boot_trace(void) { } 271static inline void start_boot_trace(void) { }
253static inline void stop_boot_trace(void) { } 272static inline void enable_boot_trace(void) { }
273static inline void disable_boot_trace(void) { }
254#endif 274#endif
255 275
256 276
diff --git a/init/main.c b/init/main.c
index 7e117a231af1..4b03cd5656ca 100644
--- a/init/main.c
+++ b/init/main.c
@@ -711,6 +711,7 @@ int do_one_initcall(initcall_t fn)
711 it.caller = task_pid_nr(current); 711 it.caller = task_pid_nr(current);
712 printk("calling %pF @ %i\n", fn, it.caller); 712 printk("calling %pF @ %i\n", fn, it.caller);
713 it.calltime = ktime_get(); 713 it.calltime = ktime_get();
714 enable_boot_trace();
714 } 715 }
715 716
716 it.result = fn(); 717 it.result = fn();
@@ -722,6 +723,7 @@ int do_one_initcall(initcall_t fn)
722 printk("initcall %pF returned %d after %Ld usecs\n", fn, 723 printk("initcall %pF returned %d after %Ld usecs\n", fn,
723 it.result, it.duration); 724 it.result, it.duration);
724 trace_boot(&it, fn); 725 trace_boot(&it, fn);
726 disable_boot_trace();
725 } 727 }
726 728
727 msgbuf[0] = 0; 729 msgbuf[0] = 0;
@@ -882,7 +884,7 @@ static int __init kernel_init(void * unused)
882 * we're essentially up and running. Get rid of the 884 * we're essentially up and running. Get rid of the
883 * initmem segments and start the user-mode stuff.. 885 * initmem segments and start the user-mode stuff..
884 */ 886 */
885 stop_boot_trace(); 887
886 init_post(); 888 init_post();
887 return 0; 889 return 0;
888} 890}
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index d576dbd6defe..29ab40a764c8 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -3285,6 +3285,8 @@ __init static int tracer_alloc_buffers(void)
3285 3285
3286 register_tracer(&nop_trace); 3286 register_tracer(&nop_trace);
3287#ifdef CONFIG_BOOT_TRACER 3287#ifdef CONFIG_BOOT_TRACER
3288 /* We don't want to launch sched_switch tracer yet */
3289 global_trace.ctrl = 0;
3288 register_tracer(&boot_tracer); 3290 register_tracer(&boot_tracer);
3289 current_trace = &boot_tracer; 3291 current_trace = &boot_tracer;
3290 current_trace->init(&global_trace); 3292 current_trace->init(&global_trace);
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index bb547e933af7..cc14a6bc1094 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -49,6 +49,7 @@ struct ftrace_entry {
49 unsigned long parent_ip; 49 unsigned long parent_ip;
50}; 50};
51extern struct tracer boot_tracer; 51extern struct tracer boot_tracer;
52extern struct tracer sched_switch_trace; /* Used by the boot tracer */
52 53
53/* 54/*
54 * Context switch trace entry - which task (and prio) we switched from/to: 55 * Context switch trace entry - which task (and prio) we switched from/to:
diff --git a/kernel/trace/trace_boot.c b/kernel/trace/trace_boot.c
index d0a5e50eeff2..bd5046c9deb7 100644
--- a/kernel/trace/trace_boot.c
+++ b/kernel/trace/trace_boot.c
@@ -13,23 +13,33 @@
13#include "trace.h" 13#include "trace.h"
14 14
15static struct trace_array *boot_trace; 15static struct trace_array *boot_trace;
16static int trace_boot_enabled; 16static bool pre_initcalls_finished;
17 17
18 18/* Tells the boot tracer that the pre_smp_initcalls are finished.
19/* Should be started after do_pre_smp_initcalls() in init/main.c */ 19 * So we are ready .
20 * It doesn't enable sched events tracing however.
21 * You have to call enable_boot_trace to do so.
22 */
20void start_boot_trace(void) 23void start_boot_trace(void)
21{ 24{
22 trace_boot_enabled = 1; 25 pre_initcalls_finished = true;
23} 26}
24 27
25void stop_boot_trace(void) 28void enable_boot_trace(void)
26{ 29{
27 trace_boot_enabled = 0; 30 if (pre_initcalls_finished)
31 tracing_start_cmdline_record();
28} 32}
29 33
30void reset_boot_trace(struct trace_array *tr) 34void disable_boot_trace(void)
31{ 35{
32 stop_boot_trace(); 36 if (pre_initcalls_finished)
37 tracing_stop_cmdline_record();
38}
39
40static void reset_boot_trace(struct trace_array *tr)
41{
42 sched_switch_trace.reset(tr);
33} 43}
34 44
35static void boot_trace_init(struct trace_array *tr) 45static void boot_trace_init(struct trace_array *tr)
@@ -37,18 +47,18 @@ static void boot_trace_init(struct trace_array *tr)
37 int cpu; 47 int cpu;
38 boot_trace = tr; 48 boot_trace = tr;
39 49
40 trace_boot_enabled = 0;
41
42 for_each_cpu_mask(cpu, cpu_possible_map) 50 for_each_cpu_mask(cpu, cpu_possible_map)
43 tracing_reset(tr, cpu); 51 tracing_reset(tr, cpu);
52
53 sched_switch_trace.init(tr);
44} 54}
45 55
46static void boot_trace_ctrl_update(struct trace_array *tr) 56static void boot_trace_ctrl_update(struct trace_array *tr)
47{ 57{
48 if (tr->ctrl) 58 if (tr->ctrl)
49 start_boot_trace(); 59 enable_boot_trace();
50 else 60 else
51 stop_boot_trace(); 61 disable_boot_trace();
52} 62}
53 63
54static enum print_line_t initcall_print_line(struct trace_iterator *iter) 64static enum print_line_t initcall_print_line(struct trace_iterator *iter)
@@ -99,7 +109,7 @@ void trace_boot(struct boot_trace *it, initcall_t fn)
99 unsigned long irq_flags; 109 unsigned long irq_flags;
100 struct trace_array *tr = boot_trace; 110 struct trace_array *tr = boot_trace;
101 111
102 if (!trace_boot_enabled) 112 if (!pre_initcalls_finished)
103 return; 113 return;
104 114
105 /* Get its name now since this function could 115 /* Get its name now since this function could
diff --git a/kernel/trace/trace_sched_switch.c b/kernel/trace/trace_sched_switch.c
index b8f56beb1a62..888944d3409d 100644
--- a/kernel/trace/trace_sched_switch.c
+++ b/kernel/trace/trace_sched_switch.c
@@ -16,7 +16,8 @@
16 16
17static struct trace_array *ctx_trace; 17static struct trace_array *ctx_trace;
18static int __read_mostly tracer_enabled; 18static int __read_mostly tracer_enabled;
19static atomic_t sched_ref; 19static int sched_ref;
20static DEFINE_MUTEX(sched_register_mutex);
20 21
21static void 22static void
22probe_sched_switch(struct rq *__rq, struct task_struct *prev, 23probe_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);
@@ -123,20 +124,22 @@ static void tracing_sched_unregister(void)
123 124
124static void tracing_start_sched_switch(void) 125static void tracing_start_sched_switch(void)
125{ 126{
126 long ref; 127 mutex_lock(&sched_register_mutex);
127 128 if (!(sched_ref++)) {
128 ref = atomic_inc_return(&sched_ref); 129 tracer_enabled = 1;
129 if (ref == 1)
130 tracing_sched_register(); 130 tracing_sched_register();
131 }
132 mutex_unlock(&sched_register_mutex);
131} 133}
132 134
133static void tracing_stop_sched_switch(void) 135static void tracing_stop_sched_switch(void)
134{ 136{
135 long ref; 137 mutex_lock(&sched_register_mutex);
136 138 if (!(--sched_ref)) {
137 ref = atomic_dec_and_test(&sched_ref);
138 if (ref)
139 tracing_sched_unregister(); 139 tracing_sched_unregister();
140 tracer_enabled = 0;
141 }
142 mutex_unlock(&sched_register_mutex);
140} 143}
141 144
142void tracing_start_cmdline_record(void) 145void tracing_start_cmdline_record(void)
@@ -153,12 +156,10 @@ static void start_sched_trace(struct trace_array *tr)
153{ 156{
154 sched_switch_reset(tr); 157 sched_switch_reset(tr);
155 tracing_start_cmdline_record(); 158 tracing_start_cmdline_record();
156 tracer_enabled = 1;
157} 159}
158 160
159static void stop_sched_trace(struct trace_array *tr) 161static void stop_sched_trace(struct trace_array *tr)
160{ 162{
161 tracer_enabled = 0;
162 tracing_stop_cmdline_record(); 163 tracing_stop_cmdline_record();
163} 164}
164 165
@@ -172,7 +173,7 @@ static void sched_switch_trace_init(struct trace_array *tr)
172 173
173static void sched_switch_trace_reset(struct trace_array *tr) 174static void sched_switch_trace_reset(struct trace_array *tr)
174{ 175{
175 if (tr->ctrl) 176 if (tr->ctrl && sched_ref)
176 stop_sched_trace(tr); 177 stop_sched_trace(tr);
177} 178}
178 179
@@ -185,7 +186,7 @@ static void sched_switch_trace_ctrl_update(struct trace_array *tr)
185 stop_sched_trace(tr); 186 stop_sched_trace(tr);
186} 187}
187 188
188static struct tracer sched_switch_trace __read_mostly = 189struct tracer sched_switch_trace __read_mostly =
189{ 190{
190 .name = "sched_switch", 191 .name = "sched_switch",
191 .init = sched_switch_trace_init, 192 .init = sched_switch_trace_init,
@@ -198,14 +199,6 @@ static struct tracer sched_switch_trace __read_mostly =
198 199
199__init static int init_sched_switch_trace(void) 200__init static int init_sched_switch_trace(void)
200{ 201{
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); 202 return register_tracer(&sched_switch_trace);
210} 203}
211device_initcall(init_sched_switch_trace); 204device_initcall(init_sched_switch_trace);