diff options
author | Thomas Renninger <trenn@suse.de> | 2011-01-03 11:50:45 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2011-01-04 02:16:54 -0500 |
commit | 20c457b8587bee4644d998331d9e13be82e05b4c (patch) | |
tree | e1864952316ad24af3bea22d09753e043eb6ee75 /tools | |
parent | 25e41933b58777f2d020c3b0186b430ea004ec28 (diff) |
perf timechart: Adjust perf timechart to the new power events
builtin-timechart must only pass -e power:xy events if they are supported by
the running kernel, otherwise try to fetch the old power:power{start,end}
events.
For this I added the tiny helper function:
int is_valid_tracepoint(const char *event_string)
to parse-events.[hc], which could be more generic as an interface and support
hardware/software/... events, not only tracepoints, but someone else could
extend that if needed...
Signed-off-by: Thomas Renninger <trenn@suse.de>
Acked-by: Arjan van de Ven <arjan@linux.intel.com>
Acked-by: Jean Pihet <j-pihet@ti.com>
LKML-Reference: <1294073445-14812-4-git-send-email-trenn@suse.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-timechart.c | 94 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 41 | ||||
-rw-r--r-- | tools/perf/util/parse-events.h | 1 |
3 files changed, 118 insertions, 18 deletions
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index d75084bccdb7..746cf03cb05d 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c | |||
@@ -32,6 +32,10 @@ | |||
32 | #include "util/session.h" | 32 | #include "util/session.h" |
33 | #include "util/svghelper.h" | 33 | #include "util/svghelper.h" |
34 | 34 | ||
35 | #define SUPPORT_OLD_POWER_EVENTS 1 | ||
36 | #define PWR_EVENT_EXIT -1 | ||
37 | |||
38 | |||
35 | static char const *input_name = "perf.data"; | 39 | static char const *input_name = "perf.data"; |
36 | static char const *output_name = "output.svg"; | 40 | static char const *output_name = "output.svg"; |
37 | 41 | ||
@@ -301,12 +305,21 @@ struct trace_entry { | |||
301 | int lock_depth; | 305 | int lock_depth; |
302 | }; | 306 | }; |
303 | 307 | ||
304 | struct power_entry { | 308 | #ifdef SUPPORT_OLD_POWER_EVENTS |
309 | static int use_old_power_events; | ||
310 | struct power_entry_old { | ||
305 | struct trace_entry te; | 311 | struct trace_entry te; |
306 | u64 type; | 312 | u64 type; |
307 | u64 value; | 313 | u64 value; |
308 | u64 cpu_id; | 314 | u64 cpu_id; |
309 | }; | 315 | }; |
316 | #endif | ||
317 | |||
318 | struct power_processor_entry { | ||
319 | struct trace_entry te; | ||
320 | u32 state; | ||
321 | u32 cpu_id; | ||
322 | }; | ||
310 | 323 | ||
311 | #define TASK_COMM_LEN 16 | 324 | #define TASK_COMM_LEN 16 |
312 | struct wakeup_entry { | 325 | struct wakeup_entry { |
@@ -489,29 +502,49 @@ static int process_sample_event(event_t *event __used, | |||
489 | te = (void *)sample->raw_data; | 502 | te = (void *)sample->raw_data; |
490 | if (session->sample_type & PERF_SAMPLE_RAW && sample->raw_size > 0) { | 503 | if (session->sample_type & PERF_SAMPLE_RAW && sample->raw_size > 0) { |
491 | char *event_str; | 504 | char *event_str; |
492 | struct power_entry *pe; | 505 | #ifdef SUPPORT_OLD_POWER_EVENTS |
493 | 506 | struct power_entry_old *peo; | |
494 | pe = (void *)te; | 507 | peo = (void *)te; |
495 | 508 | #endif | |
496 | event_str = perf_header__find_event(te->type); | 509 | event_str = perf_header__find_event(te->type); |
497 | 510 | ||
498 | if (!event_str) | 511 | if (!event_str) |
499 | return 0; | 512 | return 0; |
500 | 513 | ||
501 | if (strcmp(event_str, "power:power_start") == 0) | 514 | if (strcmp(event_str, "power:cpu_idle") == 0) { |
502 | c_state_start(pe->cpu_id, sample->time, pe->value); | 515 | struct power_processor_entry *ppe = (void *)te; |
503 | 516 | if (ppe->state == (u32)PWR_EVENT_EXIT) | |
504 | if (strcmp(event_str, "power:power_end") == 0) | 517 | c_state_end(ppe->cpu_id, sample->time); |
505 | c_state_end(pe->cpu_id, sample->time); | 518 | else |
506 | 519 | c_state_start(ppe->cpu_id, sample->time, | |
507 | if (strcmp(event_str, "power:power_frequency") == 0) | 520 | ppe->state); |
508 | p_state_change(pe->cpu_id, sample->time, pe->value); | 521 | } |
522 | else if (strcmp(event_str, "power:cpu_frequency") == 0) { | ||
523 | struct power_processor_entry *ppe = (void *)te; | ||
524 | p_state_change(ppe->cpu_id, sample->time, ppe->state); | ||
525 | } | ||
509 | 526 | ||
510 | if (strcmp(event_str, "sched:sched_wakeup") == 0) | 527 | else if (strcmp(event_str, "sched:sched_wakeup") == 0) |
511 | sched_wakeup(sample->cpu, sample->time, sample->pid, te); | 528 | sched_wakeup(sample->cpu, sample->time, sample->pid, te); |
512 | 529 | ||
513 | if (strcmp(event_str, "sched:sched_switch") == 0) | 530 | else if (strcmp(event_str, "sched:sched_switch") == 0) |
514 | sched_switch(sample->cpu, sample->time, te); | 531 | sched_switch(sample->cpu, sample->time, te); |
532 | |||
533 | #ifdef SUPPORT_OLD_POWER_EVENTS | ||
534 | if (use_old_power_events) { | ||
535 | if (strcmp(event_str, "power:power_start") == 0) | ||
536 | c_state_start(peo->cpu_id, sample->time, | ||
537 | peo->value); | ||
538 | |||
539 | else if (strcmp(event_str, "power:power_end") == 0) | ||
540 | c_state_end(sample->cpu, sample->time); | ||
541 | |||
542 | else if (strcmp(event_str, | ||
543 | "power:power_frequency") == 0) | ||
544 | p_state_change(peo->cpu_id, sample->time, | ||
545 | peo->value); | ||
546 | } | ||
547 | #endif | ||
515 | } | 548 | } |
516 | return 0; | 549 | return 0; |
517 | } | 550 | } |
@@ -969,7 +1002,8 @@ static const char * const timechart_usage[] = { | |||
969 | NULL | 1002 | NULL |
970 | }; | 1003 | }; |
971 | 1004 | ||
972 | static const char *record_args[] = { | 1005 | #ifdef SUPPORT_OLD_POWER_EVENTS |
1006 | static const char * const record_old_args[] = { | ||
973 | "record", | 1007 | "record", |
974 | "-a", | 1008 | "-a", |
975 | "-R", | 1009 | "-R", |
@@ -981,19 +1015,43 @@ static const char *record_args[] = { | |||
981 | "-e", "sched:sched_wakeup", | 1015 | "-e", "sched:sched_wakeup", |
982 | "-e", "sched:sched_switch", | 1016 | "-e", "sched:sched_switch", |
983 | }; | 1017 | }; |
1018 | #endif | ||
1019 | |||
1020 | static const char * const record_new_args[] = { | ||
1021 | "record", | ||
1022 | "-a", | ||
1023 | "-R", | ||
1024 | "-f", | ||
1025 | "-c", "1", | ||
1026 | "-e", "power:cpu_frequency", | ||
1027 | "-e", "power:cpu_idle", | ||
1028 | "-e", "sched:sched_wakeup", | ||
1029 | "-e", "sched:sched_switch", | ||
1030 | }; | ||
984 | 1031 | ||
985 | static int __cmd_record(int argc, const char **argv) | 1032 | static int __cmd_record(int argc, const char **argv) |
986 | { | 1033 | { |
987 | unsigned int rec_argc, i, j; | 1034 | unsigned int rec_argc, i, j; |
988 | const char **rec_argv; | 1035 | const char **rec_argv; |
1036 | const char * const *record_args = record_new_args; | ||
1037 | unsigned int record_elems = ARRAY_SIZE(record_new_args); | ||
1038 | |||
1039 | #ifdef SUPPORT_OLD_POWER_EVENTS | ||
1040 | if (!is_valid_tracepoint("power:cpu_idle") && | ||
1041 | is_valid_tracepoint("power:power_start")) { | ||
1042 | use_old_power_events = 1; | ||
1043 | record_args = record_old_args; | ||
1044 | record_elems = ARRAY_SIZE(record_old_args); | ||
1045 | } | ||
1046 | #endif | ||
989 | 1047 | ||
990 | rec_argc = ARRAY_SIZE(record_args) + argc - 1; | 1048 | rec_argc = record_elems + argc - 1; |
991 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); | 1049 | rec_argv = calloc(rec_argc + 1, sizeof(char *)); |
992 | 1050 | ||
993 | if (rec_argv == NULL) | 1051 | if (rec_argv == NULL) |
994 | return -ENOMEM; | 1052 | return -ENOMEM; |
995 | 1053 | ||
996 | for (i = 0; i < ARRAY_SIZE(record_args); i++) | 1054 | for (i = 0; i < record_elems; i++) |
997 | rec_argv[i] = strdup(record_args[i]); | 1055 | rec_argv[i] = strdup(record_args[i]); |
998 | 1056 | ||
999 | for (j = 1; j < (unsigned int)argc; j++, i++) | 1057 | for (j = 1; j < (unsigned int)argc; j++, i++) |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 3a142e90d609..649083f27e08 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -913,6 +913,47 @@ static void print_tracepoint_events(void) | |||
913 | } | 913 | } |
914 | 914 | ||
915 | /* | 915 | /* |
916 | * Check whether event is in <debugfs_mount_point>/tracing/events | ||
917 | */ | ||
918 | |||
919 | int is_valid_tracepoint(const char *event_string) | ||
920 | { | ||
921 | DIR *sys_dir, *evt_dir; | ||
922 | struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; | ||
923 | char evt_path[MAXPATHLEN]; | ||
924 | char dir_path[MAXPATHLEN]; | ||
925 | |||
926 | if (debugfs_valid_mountpoint(debugfs_path)) | ||
927 | return 0; | ||
928 | |||
929 | sys_dir = opendir(debugfs_path); | ||
930 | if (!sys_dir) | ||
931 | return 0; | ||
932 | |||
933 | for_each_subsystem(sys_dir, sys_dirent, sys_next) { | ||
934 | |||
935 | snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, | ||
936 | sys_dirent.d_name); | ||
937 | evt_dir = opendir(dir_path); | ||
938 | if (!evt_dir) | ||
939 | continue; | ||
940 | |||
941 | for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { | ||
942 | snprintf(evt_path, MAXPATHLEN, "%s:%s", | ||
943 | sys_dirent.d_name, evt_dirent.d_name); | ||
944 | if (!strcmp(evt_path, event_string)) { | ||
945 | closedir(evt_dir); | ||
946 | closedir(sys_dir); | ||
947 | return 1; | ||
948 | } | ||
949 | } | ||
950 | closedir(evt_dir); | ||
951 | } | ||
952 | closedir(sys_dir); | ||
953 | return 0; | ||
954 | } | ||
955 | |||
956 | /* | ||
916 | * Print the help text for the event symbols: | 957 | * Print the help text for the event symbols: |
917 | */ | 958 | */ |
918 | void print_events(void) | 959 | void print_events(void) |
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index 0a0abc1d10eb..1c9043ccd173 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h | |||
@@ -36,6 +36,7 @@ extern int parse_filter(const struct option *opt, const char *str, int unset); | |||
36 | #define EVENTS_HELP_MAX (128*1024) | 36 | #define EVENTS_HELP_MAX (128*1024) |
37 | 37 | ||
38 | extern void print_events(void); | 38 | extern void print_events(void); |
39 | extern int is_valid_tracepoint(const char *event_string); | ||
39 | 40 | ||
40 | extern char debugfs_path[]; | 41 | extern char debugfs_path[]; |
41 | extern int valid_debugfs_mount(const char *debugfs); | 42 | extern int valid_debugfs_mount(const char *debugfs); |