diff options
author | David S. Miller <davem@davemloft.net> | 2010-01-23 01:45:46 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-01-23 01:45:46 -0500 |
commit | 6be325719b3e54624397e413efd4b33a997e55a3 (patch) | |
tree | 57f321a56794cab2222e179b16731e0d76a4a68a /tools/perf/builtin-timechart.c | |
parent | 26d92f9276a56d55511a427fb70bd70886af647a (diff) | |
parent | 92dcffb916d309aa01778bf8963a6932e4014d07 (diff) |
Merge branch 'master' of /home/davem/src/GIT/linux-2.6/
Diffstat (limited to 'tools/perf/builtin-timechart.c')
-rw-r--r-- | tools/perf/builtin-timechart.c | 120 |
1 files changed, 45 insertions, 75 deletions
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index cb58b6605fcc..3f8bbcfb1e9b 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -30,15 +30,12 @@ | |||
30 | #include "util/parse-options.h" | 30 | #include "util/parse-options.h" |
31 | #include "util/parse-events.h" | 31 | #include "util/parse-events.h" |
32 | #include "util/event.h" | 32 | #include "util/event.h" |
33 | #include "util/data_map.h" | 33 | #include "util/session.h" |
34 | #include "util/svghelper.h" | 34 | #include "util/svghelper.h" |
35 | 35 | ||
36 | static char const *input_name = "perf.data"; | 36 | static char const *input_name = "perf.data"; |
37 | static char const *output_name = "output.svg"; | 37 | static char const *output_name = "output.svg"; |
38 | 38 | ||
39 | |||
40 | static u64 sample_type; | ||
41 | |||
42 | static unsigned int numcpus; | 39 | static unsigned int numcpus; |
43 | static u64 min_freq; /* Lowest CPU frequency seen */ | 40 | static u64 min_freq; /* Lowest CPU frequency seen */ |
44 | static u64 max_freq; /* Highest CPU frequency seen */ | 41 | static u64 max_freq; /* Highest CPU frequency seen */ |
@@ -281,33 +278,30 @@ static int cpus_cstate_state[MAX_CPUS]; | |||
281 | static u64 cpus_pstate_start_times[MAX_CPUS]; | 278 | static u64 cpus_pstate_start_times[MAX_CPUS]; |
282 | static u64 cpus_pstate_state[MAX_CPUS]; | 279 | static u64 cpus_pstate_state[MAX_CPUS]; |
283 | 280 | ||
284 | static int | 281 | static int process_comm_event(event_t *event, struct perf_session *session __used) |
285 | process_comm_event(event_t *event) | ||
286 | { | 282 | { |
287 | pid_set_comm(event->comm.pid, event->comm.comm); | 283 | pid_set_comm(event->comm.tid, event->comm.comm); |
288 | return 0; | 284 | return 0; |
289 | } | 285 | } |
290 | static int | 286 | |
291 | process_fork_event(event_t *event) | 287 | static int process_fork_event(event_t *event, struct perf_session *session __used) |
292 | { | 288 | { |
293 | pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); | 289 | pid_fork(event->fork.pid, event->fork.ppid, event->fork.time); |
294 | return 0; | 290 | return 0; |
295 | } | 291 | } |
296 | 292 | ||
297 | static int | 293 | static int process_exit_event(event_t *event, struct perf_session *session __used) |
298 | process_exit_event(event_t *event) | ||
299 | { | 294 | { |
300 | pid_exit(event->fork.pid, event->fork.time); | 295 | pid_exit(event->fork.pid, event->fork.time); |
301 | return 0; | 296 | return 0; |
302 | } | 297 | } |
303 | 298 | ||
304 | struct trace_entry { | 299 | struct trace_entry { |
305 | u32 size; | ||
306 | unsigned short type; | 300 | unsigned short type; |
307 | unsigned char flags; | 301 | unsigned char flags; |
308 | unsigned char preempt_count; | 302 | unsigned char preempt_count; |
309 | int pid; | 303 | int pid; |
310 | int tgid; | 304 | int lock_depth; |
311 | }; | 305 | }; |
312 | 306 | ||
313 | struct power_entry { | 307 | struct power_entry { |
@@ -481,46 +475,24 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te) | |||
481 | } | 475 | } |
482 | 476 | ||
483 | 477 | ||
484 | static int | 478 | static int process_sample_event(event_t *event, struct perf_session *session) |
485 | process_sample_event(event_t *event) | ||
486 | { | 479 | { |
487 | int cursor = 0; | 480 | struct sample_data data; |
488 | u64 addr = 0; | ||
489 | u64 stamp = 0; | ||
490 | u32 cpu = 0; | ||
491 | u32 pid = 0; | ||
492 | struct trace_entry *te; | 481 | struct trace_entry *te; |
493 | 482 | ||
494 | if (sample_type & PERF_SAMPLE_IP) | 483 | memset(&data, 0, sizeof(data)); |
495 | cursor++; | ||
496 | |||
497 | if (sample_type & PERF_SAMPLE_TID) { | ||
498 | pid = event->sample.array[cursor]>>32; | ||
499 | cursor++; | ||
500 | } | ||
501 | if (sample_type & PERF_SAMPLE_TIME) { | ||
502 | stamp = event->sample.array[cursor++]; | ||
503 | 484 | ||
504 | if (!first_time || first_time > stamp) | 485 | event__parse_sample(event, session->sample_type, &data); |
505 | first_time = stamp; | ||
506 | if (last_time < stamp) | ||
507 | last_time = stamp; | ||
508 | 486 | ||
487 | if (session->sample_type & PERF_SAMPLE_TIME) { | ||
488 | if (!first_time || first_time > data.time) | ||
489 | first_time = data.time; | ||
490 | if (last_time < data.time) | ||
491 | last_time = data.time; | ||
509 | } | 492 | } |
510 | if (sample_type & PERF_SAMPLE_ADDR) | ||
511 | addr = event->sample.array[cursor++]; | ||
512 | if (sample_type & PERF_SAMPLE_ID) | ||
513 | cursor++; | ||
514 | if (sample_type & PERF_SAMPLE_STREAM_ID) | ||
515 | cursor++; | ||
516 | if (sample_type & PERF_SAMPLE_CPU) | ||
517 | cpu = event->sample.array[cursor++] & 0xFFFFFFFF; | ||
518 | if (sample_type & PERF_SAMPLE_PERIOD) | ||
519 | cursor++; | ||
520 | |||
521 | te = (void *)&event->sample.array[cursor]; | ||
522 | 493 | ||
523 | if (sample_type & PERF_SAMPLE_RAW && te->size > 0) { | 494 | te = (void *)data.raw_data; |
495 | if (session->sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) { | ||
524 | char *event_str; | 496 | char *event_str; |
525 | struct power_entry *pe; | 497 | struct power_entry *pe; |
526 | 498 | ||
@@ -532,19 +504,19 @@ process_sample_event(event_t *event) | |||
532 | return 0; | 504 | return 0; |
533 | 505 | ||
534 | if (strcmp(event_str, "power:power_start") == 0) | 506 | if (strcmp(event_str, "power:power_start") == 0) |
535 | c_state_start(cpu, stamp, pe->value); | 507 | c_state_start(data.cpu, data.time, pe->value); |
536 | 508 | ||
537 | if (strcmp(event_str, "power:power_end") == 0) | 509 | if (strcmp(event_str, "power:power_end") == 0) |
538 | c_state_end(cpu, stamp); | 510 | c_state_end(data.cpu, data.time); |
539 | 511 | ||
540 | if (strcmp(event_str, "power:power_frequency") == 0) | 512 | if (strcmp(event_str, "power:power_frequency") == 0) |
541 | p_state_change(cpu, stamp, pe->value); | 513 | p_state_change(data.cpu, data.time, pe->value); |
542 | 514 | ||
543 | if (strcmp(event_str, "sched:sched_wakeup") == 0) | 515 | if (strcmp(event_str, "sched:sched_wakeup") == 0) |
544 | sched_wakeup(cpu, stamp, pid, te); | 516 | sched_wakeup(data.cpu, data.time, data.pid, te); |
545 | 517 | ||
546 | if (strcmp(event_str, "sched:sched_switch") == 0) | 518 | if (strcmp(event_str, "sched:sched_switch") == 0) |
547 | sched_switch(cpu, stamp, te); | 519 | sched_switch(data.cpu, data.time, te); |
548 | } | 520 | } |
549 | return 0; | 521 | return 0; |
550 | } | 522 | } |
@@ -597,16 +569,16 @@ static void end_sample_processing(void) | |||
597 | } | 569 | } |
598 | } | 570 | } |
599 | 571 | ||
600 | static u64 sample_time(event_t *event) | 572 | static u64 sample_time(event_t *event, const struct perf_session *session) |
601 | { | 573 | { |
602 | int cursor; | 574 | int cursor; |
603 | 575 | ||
604 | cursor = 0; | 576 | cursor = 0; |
605 | if (sample_type & PERF_SAMPLE_IP) | 577 | if (session->sample_type & PERF_SAMPLE_IP) |
606 | cursor++; | 578 | cursor++; |
607 | if (sample_type & PERF_SAMPLE_TID) | 579 | if (session->sample_type & PERF_SAMPLE_TID) |
608 | cursor++; | 580 | cursor++; |
609 | if (sample_type & PERF_SAMPLE_TIME) | 581 | if (session->sample_type & PERF_SAMPLE_TIME) |
610 | return event->sample.array[cursor]; | 582 | return event->sample.array[cursor]; |
611 | return 0; | 583 | return 0; |
612 | } | 584 | } |
@@ -616,8 +588,7 @@ static u64 sample_time(event_t *event) | |||
616 | * We first queue all events, sorted backwards by insertion. | 588 | * We first queue all events, sorted backwards by insertion. |
617 | * The order will get flipped later. | 589 | * The order will get flipped later. |
618 | */ | 590 | */ |
619 | static int | 591 | static int queue_sample_event(event_t *event, struct perf_session *session) |
620 | queue_sample_event(event_t *event) | ||
621 | { | 592 | { |
622 | struct sample_wrapper *copy, *prev; | 593 | struct sample_wrapper *copy, *prev; |
623 | int size; | 594 | int size; |
@@ -631,7 +602,7 @@ queue_sample_event(event_t *event) | |||
631 | memset(copy, 0, size); | 602 | memset(copy, 0, size); |
632 | 603 | ||
633 | copy->next = NULL; | 604 | copy->next = NULL; |
634 | copy->timestamp = sample_time(event); | 605 | copy->timestamp = sample_time(event, session); |
635 | 606 | ||
636 | memcpy(©->data, event, event->sample.header.size); | 607 | memcpy(©->data, event, event->sample.header.size); |
637 | 608 | ||
@@ -1043,7 +1014,7 @@ static void write_svg_file(const char *filename) | |||
1043 | svg_close(); | 1014 | svg_close(); |
1044 | } | 1015 | } |
1045 | 1016 | ||
1046 | static void process_samples(void) | 1017 | static void process_samples(struct perf_session *session) |
1047 | { | 1018 | { |
1048 | struct sample_wrapper *cursor; | 1019 | struct sample_wrapper *cursor; |
1049 | event_t *event; | 1020 | event_t *event; |
@@ -1054,15 +1025,13 @@ static void process_samples(void) | |||
1054 | while (cursor) { | 1025 | while (cursor) { |
1055 | event = (void *)&cursor->data; | 1026 | event = (void *)&cursor->data; |
1056 | cursor = cursor->next; | 1027 | cursor = cursor->next; |
1057 | process_sample_event(event); | 1028 | process_sample_event(event, session); |
1058 | } | 1029 | } |
1059 | } | 1030 | } |
1060 | 1031 | ||
1061 | static int sample_type_check(u64 type) | 1032 | static int sample_type_check(struct perf_session *session) |
1062 | { | 1033 | { |
1063 | sample_type = type; | 1034 | if (!(session->sample_type & PERF_SAMPLE_RAW)) { |
1064 | |||
1065 | if (!(sample_type & PERF_SAMPLE_RAW)) { | ||
1066 | fprintf(stderr, "No trace samples found in the file.\n" | 1035 | fprintf(stderr, "No trace samples found in the file.\n" |
1067 | "Have you used 'perf timechart record' to record it?\n"); | 1036 | "Have you used 'perf timechart record' to record it?\n"); |
1068 | return -1; | 1037 | return -1; |
@@ -1071,7 +1040,7 @@ static int sample_type_check(u64 type) | |||
1071 | return 0; | 1040 | return 0; |
1072 | } | 1041 | } |
1073 | 1042 | ||
1074 | static struct perf_file_handler file_handler = { | 1043 | static struct perf_event_ops event_ops = { |
1075 | .process_comm_event = process_comm_event, | 1044 | .process_comm_event = process_comm_event, |
1076 | .process_fork_event = process_fork_event, | 1045 | .process_fork_event = process_fork_event, |
1077 | .process_exit_event = process_exit_event, | 1046 | .process_exit_event = process_exit_event, |
@@ -1081,17 +1050,17 @@ static struct perf_file_handler file_handler = { | |||
1081 | 1050 | ||
1082 | static int __cmd_timechart(void) | 1051 | static int __cmd_timechart(void) |
1083 | { | 1052 | { |
1084 | struct perf_header *header; | 1053 | struct perf_session *session = perf_session__new(input_name, O_RDONLY, 0); |
1085 | int ret; | 1054 | int ret; |
1086 | 1055 | ||
1087 | register_perf_file_handler(&file_handler); | 1056 | if (session == NULL) |
1057 | return -ENOMEM; | ||
1088 | 1058 | ||
1089 | ret = mmap_dispatch_perf_file(&header, input_name, 0, 0, | 1059 | ret = perf_session__process_events(session, &event_ops); |
1090 | &event__cwdlen, &event__cwd); | ||
1091 | if (ret) | 1060 | if (ret) |
1092 | return EXIT_FAILURE; | 1061 | goto out_delete; |
1093 | 1062 | ||
1094 | process_samples(); | 1063 | process_samples(session); |
1095 | 1064 | ||
1096 | end_sample_processing(); | 1065 | end_sample_processing(); |
1097 | 1066 | ||
@@ -1101,8 +1070,9 @@ static int __cmd_timechart(void) | |||
1101 | 1070 | ||
1102 | pr_info("Written %2.1f seconds of trace to %s.\n", | 1071 | pr_info("Written %2.1f seconds of trace to %s.\n", |
1103 | (last_time - first_time) / 1000000000.0, output_name); | 1072 | (last_time - first_time) / 1000000000.0, output_name); |
1104 | 1073 | out_delete: | |
1105 | return EXIT_SUCCESS; | 1074 | perf_session__delete(session); |
1075 | return ret; | ||
1106 | } | 1076 | } |
1107 | 1077 | ||
1108 | static const char * const timechart_usage[] = { | 1078 | static const char * const timechart_usage[] = { |
@@ -1167,11 +1137,11 @@ static const struct option options[] = { | |||
1167 | 1137 | ||
1168 | int cmd_timechart(int argc, const char **argv, const char *prefix __used) | 1138 | int cmd_timechart(int argc, const char **argv, const char *prefix __used) |
1169 | { | 1139 | { |
1170 | symbol__init(0); | ||
1171 | |||
1172 | argc = parse_options(argc, argv, options, timechart_usage, | 1140 | argc = parse_options(argc, argv, options, timechart_usage, |
1173 | PARSE_OPT_STOP_AT_NON_OPTION); | 1141 | PARSE_OPT_STOP_AT_NON_OPTION); |
1174 | 1142 | ||
1143 | symbol__init(); | ||
1144 | |||
1175 | if (argc && !strncmp(argv[0], "rec", 3)) | 1145 | if (argc && !strncmp(argv[0], "rec", 3)) |
1176 | return __cmd_record(argc, argv); | 1146 | return __cmd_record(argc, argv); |
1177 | else if (argc) | 1147 | else if (argc) |