diff options
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 d75084bccdb..746cf03cb05 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 3a142e90d60..649083f27e0 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 0a0abc1d10e..1c9043ccd17 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); |
