diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-11-06 01:43:47 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-06 01:43:47 -0500 |
commit | 79c81d220c8e25163f56edcdfaf23f83a4c88e6b (patch) | |
tree | 8748e39e968aacebbf150b81cbc845582b382a47 | |
parent | 3299b4dd1180762da831be5eb6adc44553eaec26 (diff) | |
parent | 79a9d461fd521f133f0e66485aa9ed09c21f5191 (diff) |
Merge branch 'tracing/fastboot' into tracing/ftrace
-rw-r--r-- | include/linux/ftrace.h | 24 | ||||
-rw-r--r-- | init/main.c | 4 | ||||
-rw-r--r-- | kernel/trace/trace.c | 2 | ||||
-rw-r--r-- | kernel/trace/trace.h | 1 | ||||
-rw-r--r-- | kernel/trace/trace_boot.c | 36 | ||||
-rw-r--r-- | kernel/trace/trace_sched_switch.c | 37 |
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 | */ | ||
237 | struct boot_trace { | 242 | struct 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 */ | ||
247 | extern void trace_boot(struct boot_trace *it, initcall_t fn); | 253 | extern 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 | */ | ||
248 | extern void start_boot_trace(void); | 258 | extern void start_boot_trace(void); |
249 | extern void stop_boot_trace(void); | 259 | |
260 | /* Resume the tracing of other necessary events | ||
261 | * such as sched switches | ||
262 | */ | ||
263 | extern 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 | */ | ||
268 | extern void disable_boot_trace(void); | ||
250 | #else | 269 | #else |
251 | static inline void trace_boot(struct boot_trace *it, initcall_t fn) { } | 270 | static inline void trace_boot(struct boot_trace *it, initcall_t fn) { } |
252 | static inline void start_boot_trace(void) { } | 271 | static inline void start_boot_trace(void) { } |
253 | static inline void stop_boot_trace(void) { } | 272 | static inline void enable_boot_trace(void) { } |
273 | static 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 | }; |
51 | extern struct tracer boot_tracer; | 51 | extern struct tracer boot_tracer; |
52 | extern 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 | ||
15 | static struct trace_array *boot_trace; | 15 | static struct trace_array *boot_trace; |
16 | static int trace_boot_enabled; | 16 | static 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 | */ | ||
20 | void start_boot_trace(void) | 23 | void start_boot_trace(void) |
21 | { | 24 | { |
22 | trace_boot_enabled = 1; | 25 | pre_initcalls_finished = true; |
23 | } | 26 | } |
24 | 27 | ||
25 | void stop_boot_trace(void) | 28 | void 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 | ||
30 | void reset_boot_trace(struct trace_array *tr) | 34 | void disable_boot_trace(void) |
31 | { | 35 | { |
32 | stop_boot_trace(); | 36 | if (pre_initcalls_finished) |
37 | tracing_stop_cmdline_record(); | ||
38 | } | ||
39 | |||
40 | static void reset_boot_trace(struct trace_array *tr) | ||
41 | { | ||
42 | sched_switch_trace.reset(tr); | ||
33 | } | 43 | } |
34 | 44 | ||
35 | static void boot_trace_init(struct trace_array *tr) | 45 | static 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 | ||
46 | static void boot_trace_ctrl_update(struct trace_array *tr) | 56 | static 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 | ||
54 | static enum print_line_t initcall_print_line(struct trace_iterator *iter) | 64 | static 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 | ||
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); |
@@ -123,20 +124,22 @@ static void tracing_sched_unregister(void) | |||
123 | 124 | ||
124 | static void tracing_start_sched_switch(void) | 125 | static 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 | ||
133 | static void tracing_stop_sched_switch(void) | 135 | static 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 | ||
142 | void tracing_start_cmdline_record(void) | 145 | void 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 | ||
159 | static void stop_sched_trace(struct trace_array *tr) | 161 | static 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 | ||
173 | static void sched_switch_trace_reset(struct trace_array *tr) | 174 | static 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 | ||
188 | static struct tracer sched_switch_trace __read_mostly = | 189 | struct 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 | } |
211 | device_initcall(init_sched_switch_trace); | 204 | device_initcall(init_sched_switch_trace); |