diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-11-28 09:50:41 -0500 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2013-12-02 07:22:46 -0500 |
commit | 5e22f6d22bae494ffc23da4032c477c54fd7c2d9 (patch) | |
tree | 7eea81634c22e2c46cd03d3dece6e7b864a531b1 /tools | |
parent | 985b12e633246750b5424f0a28d5f8cea04de07a (diff) |
perf timechart: Move all_data per_pid list to 'struct timechart'
Removing another global variable.
This one tho would be better done by using the machine infrastructure,
searching for the 'struct thread' with a pid, then using thread->priv,
etc.
TODO list material for now.
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stanislav Fomichev <stfomichev@yandex-team.ru>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-yyfpudgjvr6mev4bue9u72a2@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-timechart.c | 113 |
1 files changed, 59 insertions, 54 deletions
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index e2d62f1a96e4..0c955acc08a2 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -41,8 +41,11 @@ | |||
41 | #define SUPPORT_OLD_POWER_EVENTS 1 | 41 | #define SUPPORT_OLD_POWER_EVENTS 1 |
42 | #define PWR_EVENT_EXIT -1 | 42 | #define PWR_EVENT_EXIT -1 |
43 | 43 | ||
44 | struct per_pid; | ||
45 | |||
44 | struct timechart { | 46 | struct timechart { |
45 | struct perf_tool tool; | 47 | struct perf_tool tool; |
48 | struct per_pid *all_data; | ||
46 | int proc_num; | 49 | int proc_num; |
47 | unsigned int numcpus; | 50 | unsigned int numcpus; |
48 | u64 min_freq, /* Lowest CPU frequency seen */ | 51 | u64 min_freq, /* Lowest CPU frequency seen */ |
@@ -123,8 +126,6 @@ struct cpu_sample { | |||
123 | const char *backtrace; | 126 | const char *backtrace; |
124 | }; | 127 | }; |
125 | 128 | ||
126 | static struct per_pid *all_data; | ||
127 | |||
128 | #define CSTATE 1 | 129 | #define CSTATE 1 |
129 | #define PSTATE 2 | 130 | #define PSTATE 2 |
130 | 131 | ||
@@ -157,9 +158,9 @@ struct process_filter { | |||
157 | static struct process_filter *process_filter; | 158 | static struct process_filter *process_filter; |
158 | 159 | ||
159 | 160 | ||
160 | static struct per_pid *find_create_pid(int pid) | 161 | static struct per_pid *find_create_pid(struct timechart *tchart, int pid) |
161 | { | 162 | { |
162 | struct per_pid *cursor = all_data; | 163 | struct per_pid *cursor = tchart->all_data; |
163 | 164 | ||
164 | while (cursor) { | 165 | while (cursor) { |
165 | if (cursor->pid == pid) | 166 | if (cursor->pid == pid) |
@@ -169,16 +170,16 @@ static struct per_pid *find_create_pid(int pid) | |||
169 | cursor = zalloc(sizeof(*cursor)); | 170 | cursor = zalloc(sizeof(*cursor)); |
170 | assert(cursor != NULL); | 171 | assert(cursor != NULL); |
171 | cursor->pid = pid; | 172 | cursor->pid = pid; |
172 | cursor->next = all_data; | 173 | cursor->next = tchart->all_data; |
173 | all_data = cursor; | 174 | tchart->all_data = cursor; |
174 | return cursor; | 175 | return cursor; |
175 | } | 176 | } |
176 | 177 | ||
177 | static void pid_set_comm(int pid, char *comm) | 178 | static void pid_set_comm(struct timechart *tchart, int pid, char *comm) |
178 | { | 179 | { |
179 | struct per_pid *p; | 180 | struct per_pid *p; |
180 | struct per_pidcomm *c; | 181 | struct per_pidcomm *c; |
181 | p = find_create_pid(pid); | 182 | p = find_create_pid(tchart, pid); |
182 | c = p->all; | 183 | c = p->all; |
183 | while (c) { | 184 | while (c) { |
184 | if (c->comm && strcmp(c->comm, comm) == 0) { | 185 | if (c->comm && strcmp(c->comm, comm) == 0) { |
@@ -200,14 +201,14 @@ static void pid_set_comm(int pid, char *comm) | |||
200 | p->all = c; | 201 | p->all = c; |
201 | } | 202 | } |
202 | 203 | ||
203 | static void pid_fork(int pid, int ppid, u64 timestamp) | 204 | static void pid_fork(struct timechart *tchart, int pid, int ppid, u64 timestamp) |
204 | { | 205 | { |
205 | struct per_pid *p, *pp; | 206 | struct per_pid *p, *pp; |
206 | p = find_create_pid(pid); | 207 | p = find_create_pid(tchart, pid); |
207 | pp = find_create_pid(ppid); | 208 | pp = find_create_pid(tchart, ppid); |
208 | p->ppid = ppid; | 209 | p->ppid = ppid; |
209 | if (pp->current && pp->current->comm && !p->current) | 210 | if (pp->current && pp->current->comm && !p->current) |
210 | pid_set_comm(pid, pp->current->comm); | 211 | pid_set_comm(tchart, pid, pp->current->comm); |
211 | 212 | ||
212 | p->start_time = timestamp; | 213 | p->start_time = timestamp; |
213 | if (p->current) { | 214 | if (p->current) { |
@@ -216,24 +217,24 @@ static void pid_fork(int pid, int ppid, u64 timestamp) | |||
216 | } | 217 | } |
217 | } | 218 | } |
218 | 219 | ||
219 | static void pid_exit(int pid, u64 timestamp) | 220 | static void pid_exit(struct timechart *tchart, int pid, u64 timestamp) |
220 | { | 221 | { |
221 | struct per_pid *p; | 222 | struct per_pid *p; |
222 | p = find_create_pid(pid); | 223 | p = find_create_pid(tchart, pid); |
223 | p->end_time = timestamp; | 224 | p->end_time = timestamp; |
224 | if (p->current) | 225 | if (p->current) |
225 | p->current->end_time = timestamp; | 226 | p->current->end_time = timestamp; |
226 | } | 227 | } |
227 | 228 | ||
228 | static void | 229 | static void pid_put_sample(struct timechart *tchart, int pid, int type, |
229 | pid_put_sample(int pid, int type, unsigned int cpu, u64 start, u64 end, | 230 | unsigned int cpu, u64 start, u64 end, |
230 | const char *backtrace) | 231 | const char *backtrace) |
231 | { | 232 | { |
232 | struct per_pid *p; | 233 | struct per_pid *p; |
233 | struct per_pidcomm *c; | 234 | struct per_pidcomm *c; |
234 | struct cpu_sample *sample; | 235 | struct cpu_sample *sample; |
235 | 236 | ||
236 | p = find_create_pid(pid); | 237 | p = find_create_pid(tchart, pid); |
237 | c = p->current; | 238 | c = p->current; |
238 | if (!c) { | 239 | if (!c) { |
239 | c = zalloc(sizeof(*c)); | 240 | c = zalloc(sizeof(*c)); |
@@ -271,30 +272,33 @@ static int cpus_cstate_state[MAX_CPUS]; | |||
271 | static u64 cpus_pstate_start_times[MAX_CPUS]; | 272 | static u64 cpus_pstate_start_times[MAX_CPUS]; |
272 | static u64 cpus_pstate_state[MAX_CPUS]; | 273 | static u64 cpus_pstate_state[MAX_CPUS]; |
273 | 274 | ||
274 | static int process_comm_event(struct perf_tool *tool __maybe_unused, | 275 | static int process_comm_event(struct perf_tool *tool, |
275 | union perf_event *event, | 276 | union perf_event *event, |
276 | struct perf_sample *sample __maybe_unused, | 277 | struct perf_sample *sample __maybe_unused, |
277 | struct machine *machine __maybe_unused) | 278 | struct machine *machine __maybe_unused) |
278 | { | 279 | { |
279 | pid_set_comm(event->comm.tid, event->comm.comm); | 280 | struct timechart *tchart = container_of(tool, struct timechart, tool); |
281 | pid_set_comm(tchart, event->comm.tid, event->comm.comm); | ||
280 | return 0; | 282 | return 0; |
281 | } | 283 | } |
282 | 284 | ||
283 | static int process_fork_event(struct perf_tool *tool __maybe_unused, | 285 | static int process_fork_event(struct perf_tool *tool, |
284 | union perf_event *event, | 286 | union perf_event *event, |
285 | struct perf_sample *sample __maybe_unused, | 287 | struct perf_sample *sample __maybe_unused, |
286 | struct machine *machine __maybe_unused) | 288 | struct machine *machine __maybe_unused) |
287 | { | 289 | { |
288 | pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); | 290 | struct timechart *tchart = container_of(tool, struct timechart, tool); |
291 | pid_fork(tchart, event->fork.pid, event->fork.ppid, event->fork.time); | ||
289 | return 0; | 292 | return 0; |
290 | } | 293 | } |
291 | 294 | ||
292 | static int process_exit_event(struct perf_tool *tool __maybe_unused, | 295 | static int process_exit_event(struct perf_tool *tool, |
293 | union perf_event *event, | 296 | union perf_event *event, |
294 | struct perf_sample *sample __maybe_unused, | 297 | struct perf_sample *sample __maybe_unused, |
295 | struct machine *machine __maybe_unused) | 298 | struct machine *machine __maybe_unused) |
296 | { | 299 | { |
297 | pid_exit(event->fork.pid, event->fork.time); | 300 | struct timechart *tchart = container_of(tool, struct timechart, tool); |
301 | pid_exit(tchart, event->fork.pid, event->fork.time); | ||
298 | return 0; | 302 | return 0; |
299 | } | 303 | } |
300 | 304 | ||
@@ -361,8 +365,8 @@ static void p_state_change(struct timechart *tchart, int cpu, u64 timestamp, u64 | |||
361 | tchart->turbo_frequency = tchart->max_freq; | 365 | tchart->turbo_frequency = tchart->max_freq; |
362 | } | 366 | } |
363 | 367 | ||
364 | static void sched_wakeup(int cpu, u64 timestamp, int waker, int wakee, | 368 | static void sched_wakeup(struct timechart *tchart, int cpu, u64 timestamp, |
365 | u8 flags, const char *backtrace) | 369 | int waker, int wakee, u8 flags, const char *backtrace) |
366 | { | 370 | { |
367 | struct per_pid *p; | 371 | struct per_pid *p; |
368 | struct wake_event *we = zalloc(sizeof(*we)); | 372 | struct wake_event *we = zalloc(sizeof(*we)); |
@@ -380,36 +384,37 @@ static void sched_wakeup(int cpu, u64 timestamp, int waker, int wakee, | |||
380 | we->wakee = wakee; | 384 | we->wakee = wakee; |
381 | we->next = wake_events; | 385 | we->next = wake_events; |
382 | wake_events = we; | 386 | wake_events = we; |
383 | p = find_create_pid(we->wakee); | 387 | p = find_create_pid(tchart, we->wakee); |
384 | 388 | ||
385 | if (p && p->current && p->current->state == TYPE_NONE) { | 389 | if (p && p->current && p->current->state == TYPE_NONE) { |
386 | p->current->state_since = timestamp; | 390 | p->current->state_since = timestamp; |
387 | p->current->state = TYPE_WAITING; | 391 | p->current->state = TYPE_WAITING; |
388 | } | 392 | } |
389 | if (p && p->current && p->current->state == TYPE_BLOCKED) { | 393 | if (p && p->current && p->current->state == TYPE_BLOCKED) { |
390 | pid_put_sample(p->pid, p->current->state, cpu, | 394 | pid_put_sample(tchart, p->pid, p->current->state, cpu, |
391 | p->current->state_since, timestamp, NULL); | 395 | p->current->state_since, timestamp, NULL); |
392 | p->current->state_since = timestamp; | 396 | p->current->state_since = timestamp; |
393 | p->current->state = TYPE_WAITING; | 397 | p->current->state = TYPE_WAITING; |
394 | } | 398 | } |
395 | } | 399 | } |
396 | 400 | ||
397 | static void sched_switch(int cpu, u64 timestamp, int prev_pid, int next_pid, | 401 | static void sched_switch(struct timechart *tchart, int cpu, u64 timestamp, |
398 | u64 prev_state, const char *backtrace) | 402 | int prev_pid, int next_pid, u64 prev_state, |
403 | const char *backtrace) | ||
399 | { | 404 | { |
400 | struct per_pid *p = NULL, *prev_p; | 405 | struct per_pid *p = NULL, *prev_p; |
401 | 406 | ||
402 | prev_p = find_create_pid(prev_pid); | 407 | prev_p = find_create_pid(tchart, prev_pid); |
403 | 408 | ||
404 | p = find_create_pid(next_pid); | 409 | p = find_create_pid(tchart, next_pid); |
405 | 410 | ||
406 | if (prev_p->current && prev_p->current->state != TYPE_NONE) | 411 | if (prev_p->current && prev_p->current->state != TYPE_NONE) |
407 | pid_put_sample(prev_pid, TYPE_RUNNING, cpu, | 412 | pid_put_sample(tchart, prev_pid, TYPE_RUNNING, cpu, |
408 | prev_p->current->state_since, timestamp, | 413 | prev_p->current->state_since, timestamp, |
409 | backtrace); | 414 | backtrace); |
410 | if (p && p->current) { | 415 | if (p && p->current) { |
411 | if (p->current->state != TYPE_NONE) | 416 | if (p->current->state != TYPE_NONE) |
412 | pid_put_sample(next_pid, p->current->state, cpu, | 417 | pid_put_sample(tchart, next_pid, p->current->state, cpu, |
413 | p->current->state_since, timestamp, | 418 | p->current->state_since, timestamp, |
414 | backtrace); | 419 | backtrace); |
415 | 420 | ||
@@ -566,7 +571,7 @@ process_sample_cpu_frequency(struct timechart *tchart, | |||
566 | } | 571 | } |
567 | 572 | ||
568 | static int | 573 | static int |
569 | process_sample_sched_wakeup(struct timechart *tchart __maybe_unused, | 574 | process_sample_sched_wakeup(struct timechart *tchart, |
570 | struct perf_evsel *evsel, | 575 | struct perf_evsel *evsel, |
571 | struct perf_sample *sample, | 576 | struct perf_sample *sample, |
572 | const char *backtrace) | 577 | const char *backtrace) |
@@ -575,12 +580,12 @@ process_sample_sched_wakeup(struct timechart *tchart __maybe_unused, | |||
575 | int waker = perf_evsel__intval(evsel, sample, "common_pid"); | 580 | int waker = perf_evsel__intval(evsel, sample, "common_pid"); |
576 | int wakee = perf_evsel__intval(evsel, sample, "pid"); | 581 | int wakee = perf_evsel__intval(evsel, sample, "pid"); |
577 | 582 | ||
578 | sched_wakeup(sample->cpu, sample->time, waker, wakee, flags, backtrace); | 583 | sched_wakeup(tchart, sample->cpu, sample->time, waker, wakee, flags, backtrace); |
579 | return 0; | 584 | return 0; |
580 | } | 585 | } |
581 | 586 | ||
582 | static int | 587 | static int |
583 | process_sample_sched_switch(struct timechart *tchart __maybe_unused, | 588 | process_sample_sched_switch(struct timechart *tchart, |
584 | struct perf_evsel *evsel, | 589 | struct perf_evsel *evsel, |
585 | struct perf_sample *sample, | 590 | struct perf_sample *sample, |
586 | const char *backtrace) | 591 | const char *backtrace) |
@@ -589,8 +594,8 @@ process_sample_sched_switch(struct timechart *tchart __maybe_unused, | |||
589 | int next_pid = perf_evsel__intval(evsel, sample, "next_pid"); | 594 | int next_pid = perf_evsel__intval(evsel, sample, "next_pid"); |
590 | u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state"); | 595 | u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state"); |
591 | 596 | ||
592 | sched_switch(sample->cpu, sample->time, prev_pid, next_pid, prev_state, | 597 | sched_switch(tchart, sample->cpu, sample->time, prev_pid, next_pid, |
593 | backtrace); | 598 | prev_state, backtrace); |
594 | return 0; | 599 | return 0; |
595 | } | 600 | } |
596 | 601 | ||
@@ -681,16 +686,16 @@ static void end_sample_processing(struct timechart *tchart) | |||
681 | /* | 686 | /* |
682 | * Sort the pid datastructure | 687 | * Sort the pid datastructure |
683 | */ | 688 | */ |
684 | static void sort_pids(void) | 689 | static void sort_pids(struct timechart *tchart) |
685 | { | 690 | { |
686 | struct per_pid *new_list, *p, *cursor, *prev; | 691 | struct per_pid *new_list, *p, *cursor, *prev; |
687 | /* sort by ppid first, then by pid, lowest to highest */ | 692 | /* sort by ppid first, then by pid, lowest to highest */ |
688 | 693 | ||
689 | new_list = NULL; | 694 | new_list = NULL; |
690 | 695 | ||
691 | while (all_data) { | 696 | while (tchart->all_data) { |
692 | p = all_data; | 697 | p = tchart->all_data; |
693 | all_data = p->next; | 698 | tchart->all_data = p->next; |
694 | p->next = NULL; | 699 | p->next = NULL; |
695 | 700 | ||
696 | if (new_list == NULL) { | 701 | if (new_list == NULL) { |
@@ -723,7 +728,7 @@ static void sort_pids(void) | |||
723 | prev->next = p; | 728 | prev->next = p; |
724 | } | 729 | } |
725 | } | 730 | } |
726 | all_data = new_list; | 731 | tchart->all_data = new_list; |
727 | } | 732 | } |
728 | 733 | ||
729 | 734 | ||
@@ -752,7 +757,7 @@ static void draw_c_p_states(struct timechart *tchart) | |||
752 | } | 757 | } |
753 | } | 758 | } |
754 | 759 | ||
755 | static void draw_wakeups(void) | 760 | static void draw_wakeups(struct timechart *tchart) |
756 | { | 761 | { |
757 | struct wake_event *we; | 762 | struct wake_event *we; |
758 | struct per_pid *p; | 763 | struct per_pid *p; |
@@ -764,7 +769,7 @@ static void draw_wakeups(void) | |||
764 | char *task_from = NULL, *task_to = NULL; | 769 | char *task_from = NULL, *task_to = NULL; |
765 | 770 | ||
766 | /* locate the column of the waker and wakee */ | 771 | /* locate the column of the waker and wakee */ |
767 | p = all_data; | 772 | p = tchart->all_data; |
768 | while (p) { | 773 | while (p) { |
769 | if (p->pid == we->waker || p->pid == we->wakee) { | 774 | if (p->pid == we->waker || p->pid == we->wakee) { |
770 | c = p->all; | 775 | c = p->all; |
@@ -820,12 +825,12 @@ static void draw_wakeups(void) | |||
820 | } | 825 | } |
821 | } | 826 | } |
822 | 827 | ||
823 | static void draw_cpu_usage(void) | 828 | static void draw_cpu_usage(struct timechart *tchart) |
824 | { | 829 | { |
825 | struct per_pid *p; | 830 | struct per_pid *p; |
826 | struct per_pidcomm *c; | 831 | struct per_pidcomm *c; |
827 | struct cpu_sample *sample; | 832 | struct cpu_sample *sample; |
828 | p = all_data; | 833 | p = tchart->all_data; |
829 | while (p) { | 834 | while (p) { |
830 | c = p->all; | 835 | c = p->all; |
831 | while (c) { | 836 | while (c) { |
@@ -851,7 +856,7 @@ static void draw_process_bars(struct timechart *tchart) | |||
851 | 856 | ||
852 | Y = 2 * tchart->numcpus + 2; | 857 | Y = 2 * tchart->numcpus + 2; |
853 | 858 | ||
854 | p = all_data; | 859 | p = tchart->all_data; |
855 | while (p) { | 860 | while (p) { |
856 | c = p->all; | 861 | c = p->all; |
857 | while (c) { | 862 | while (c) { |
@@ -937,7 +942,7 @@ static int determine_display_tasks_filtered(struct timechart *tchart) | |||
937 | struct per_pidcomm *c; | 942 | struct per_pidcomm *c; |
938 | int count = 0; | 943 | int count = 0; |
939 | 944 | ||
940 | p = all_data; | 945 | p = tchart->all_data; |
941 | while (p) { | 946 | while (p) { |
942 | p->display = 0; | 947 | p->display = 0; |
943 | if (p->start_time == 1) | 948 | if (p->start_time == 1) |
@@ -980,7 +985,7 @@ static int determine_display_tasks(struct timechart *tchart, u64 threshold) | |||
980 | if (process_filter) | 985 | if (process_filter) |
981 | return determine_display_tasks_filtered(tchart); | 986 | return determine_display_tasks_filtered(tchart); |
982 | 987 | ||
983 | p = all_data; | 988 | p = tchart->all_data; |
984 | while (p) { | 989 | while (p) { |
985 | p->display = 0; | 990 | p->display = 0; |
986 | if (p->start_time == 1) | 991 | if (p->start_time == 1) |
@@ -1045,13 +1050,13 @@ static void write_svg_file(struct timechart *tchart, const char *filename) | |||
1045 | for (i = 0; i < tchart->numcpus; i++) | 1050 | for (i = 0; i < tchart->numcpus; i++) |
1046 | svg_cpu_box(i, tchart->max_freq, tchart->turbo_frequency); | 1051 | svg_cpu_box(i, tchart->max_freq, tchart->turbo_frequency); |
1047 | 1052 | ||
1048 | draw_cpu_usage(); | 1053 | draw_cpu_usage(tchart); |
1049 | if (tchart->proc_num) | 1054 | if (tchart->proc_num) |
1050 | draw_process_bars(tchart); | 1055 | draw_process_bars(tchart); |
1051 | if (!tchart->tasks_only) | 1056 | if (!tchart->tasks_only) |
1052 | draw_c_p_states(tchart); | 1057 | draw_c_p_states(tchart); |
1053 | if (tchart->proc_num) | 1058 | if (tchart->proc_num) |
1054 | draw_wakeups(); | 1059 | draw_wakeups(tchart); |
1055 | 1060 | ||
1056 | svg_close(); | 1061 | svg_close(); |
1057 | } | 1062 | } |
@@ -1096,7 +1101,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name) | |||
1096 | 1101 | ||
1097 | end_sample_processing(tchart); | 1102 | end_sample_processing(tchart); |
1098 | 1103 | ||
1099 | sort_pids(); | 1104 | sort_pids(tchart); |
1100 | 1105 | ||
1101 | write_svg_file(tchart, output_name); | 1106 | write_svg_file(tchart, output_name); |
1102 | 1107 | ||