aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorThomas Renninger <trenn@suse.de>2011-01-03 11:50:45 -0500
committerIngo Molnar <mingo@elte.hu>2011-01-04 02:16:54 -0500
commit20c457b8587bee4644d998331d9e13be82e05b4c (patch)
treee1864952316ad24af3bea22d09753e043eb6ee75 /tools
parent25e41933b58777f2d020c3b0186b430ea004ec28 (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.c94
-rw-r--r--tools/perf/util/parse-events.c41
-rw-r--r--tools/perf/util/parse-events.h1
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
35static char const *input_name = "perf.data"; 39static char const *input_name = "perf.data";
36static char const *output_name = "output.svg"; 40static 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
304struct power_entry { 308#ifdef SUPPORT_OLD_POWER_EVENTS
309static int use_old_power_events;
310struct 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
318struct 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
312struct wakeup_entry { 325struct 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
972static const char *record_args[] = { 1005#ifdef SUPPORT_OLD_POWER_EVENTS
1006static 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
1020static 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
985static int __cmd_record(int argc, const char **argv) 1032static 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
919int 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 */
918void print_events(void) 959void 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
38extern void print_events(void); 38extern void print_events(void);
39extern int is_valid_tracepoint(const char *event_string);
39 40
40extern char debugfs_path[]; 41extern char debugfs_path[];
41extern int valid_debugfs_mount(const char *debugfs); 42extern int valid_debugfs_mount(const char *debugfs);