From patchwork Thu Oct 28 09:02:59 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Renninger X-Patchwork-Id: 287162 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id o9S9373V024085 for ; Thu, 28 Oct 2010 09:03:07 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752660Ab0J1JDF (ORCPT ); Thu, 28 Oct 2010 05:03:05 -0400 Received: from cantor2.suse.de ([195.135.220.15]:52690 "EHLO mx2.suse.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752383Ab0J1JDD (ORCPT ); Thu, 28 Oct 2010 05:03:03 -0400 Received: from relay2.suse.de (charybdis-ext.suse.de [195.135.221.2]) by mx2.suse.de (Postfix) with ESMTP id 66BAF8F29D; Thu, 28 Oct 2010 11:03:01 +0200 (CEST) From: Thomas Renninger To: trenn@suse.de, linux-omap@vger.kernel.org, linux-pm@lists.linux-foundation.org, linux-trace-users@vger.kernel.org, jean.pihet@newoldbits.com, arjan@linux.intel.com, mingo@elte.hu, rjw@sisk.pl Subject: [PATCH 3/3] PERF(userspace): Adjust perf timechart to the new power events Date: Thu, 28 Oct 2010 11:02:59 +0200 Message-Id: <1288256579-22957-4-git-send-email-trenn@suse.de> X-Mailer: git-send-email 1.6.3 In-Reply-To: <1288256579-22957-1-git-send-email-trenn@suse.de> References: <1288256579-22957-1-git-send-email-trenn@suse.de> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Thu, 28 Oct 2010 09:03:07 +0000 (UTC) diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c index 9bcc38f..1d15228 100644 --- a/tools/perf/builtin-timechart.c +++ b/tools/perf/builtin-timechart.c @@ -32,6 +32,10 @@ #include "util/session.h" #include "util/svghelper.h" +#define SUPPORT_OLD_POWER_EVENTS 1 +#define PWR_EVENT_EXIT -1 + + static char const *input_name = "perf.data"; static char const *output_name = "output.svg"; @@ -298,12 +302,21 @@ struct trace_entry { int lock_depth; }; -struct power_entry { +#if defined(SUPPORT_OLD_POWER_EVENTS) +static int use_old_power_events; +struct power_entry_old { struct trace_entry te; u64 type; u64 value; u64 cpu_id; }; +#endif + +struct power_processor_entry { + struct trace_entry te; + u32 state; + u32 cpu_id; +}; #define TASK_COMM_LEN 16 struct wakeup_entry { @@ -489,29 +502,48 @@ static int process_sample_event(event_t *event, struct perf_session *session) te = (void *)data.raw_data; if (session->sample_type & PERF_SAMPLE_RAW && data.raw_size > 0) { char *event_str; - struct power_entry *pe; - - pe = (void *)te; +#if defined(SUPPORT_OLD_POWER_EVENTS) + struct power_entry_old *peo; + peo = (void *)te; +#endif event_str = perf_header__find_event(te->type); if (!event_str) return 0; - if (strcmp(event_str, "power:power_start") == 0) - c_state_start(pe->cpu_id, data.time, pe->value); - - if (strcmp(event_str, "power:power_end") == 0) - c_state_end(pe->cpu_id, data.time); + if (strcmp(event_str, "power:cpu_idle") == 0) { + struct power_processor_entry *ppe = (void *)te; + if (ppe->state == (u32)PWR_EVENT_EXIT) + c_state_end(ppe->cpu_id, data.time); + else + c_state_start(ppe->cpu_id, data.time, + ppe->state); + } - if (strcmp(event_str, "power:power_frequency") == 0) - p_state_change(pe->cpu_id, data.time, pe->value); + else if (strcmp(event_str, "power:cpu_frequency") == 0) { + struct power_processor_entry *ppe = (void *)te; + p_state_change(ppe->cpu_id, data.time, ppe->state); + } - if (strcmp(event_str, "sched:sched_wakeup") == 0) + else if (strcmp(event_str, "sched:sched_wakeup") == 0) sched_wakeup(data.cpu, data.time, data.pid, te); - if (strcmp(event_str, "sched:sched_switch") == 0) + else if (strcmp(event_str, "sched:sched_switch") == 0) sched_switch(data.cpu, data.time, te); + +#if defined(SUPPORT_OLD_POWER_EVENTS) + if (use_old_power_events) { + if (strcmp(event_str, "power:power_start") == 0) + c_state_start(peo->cpu_id, data.time, peo->value); + + else if (strcmp(event_str, "power:power_end") == 0) + c_state_end(peo->cpu_id, data.time); + + else if (strcmp(event_str, "power:power_frequency") == 0) + p_state_change(peo->cpu_id, data.time, peo->value); + } +#endif } return 0; } @@ -968,7 +1000,8 @@ static const char * const timechart_usage[] = { NULL }; -static const char *record_args[] = { +#if defined(SUPPORT_OLD_POWER_EVENTS) +static const char *record_old_args[] = { "record", "-a", "-R", @@ -980,16 +1013,40 @@ static const char *record_args[] = { "-e", "sched:sched_wakeup", "-e", "sched:sched_switch", }; +#endif + +static const char *record_new_args[] = { + "record", + "-a", + "-R", + "-f", + "-c", "1", + "-e", "power:cpu_frequency", + "-e", "power:cpu_idle", + "-e", "sched:sched_wakeup", + "-e", "sched:sched_switch", +}; static int __cmd_record(int argc, const char **argv) { unsigned int rec_argc, i, j; const char **rec_argv; - - rec_argc = ARRAY_SIZE(record_args) + argc - 1; + const char **record_args = record_new_args; + unsigned int record_elems = ARRAY_SIZE(record_new_args); + +#if defined(SUPPORT_OLD_POWER_EVENTS) + if (!is_valid_tracepoint("power:cpu_idle") && + is_valid_tracepoint("power:power_start")) { + use_old_power_events = 1; + record_args = record_old_args; + record_elems = ARRAY_SIZE(record_old_args); + } +#endif + + rec_argc = record_elems + argc - 1; rec_argv = calloc(rec_argc + 1, sizeof(char *)); - for (i = 0; i < ARRAY_SIZE(record_args); i++) + for (i = 0; i < record_elems; i++) rec_argv[i] = strdup(record_args[i]); 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 4af5bd5..35e3dea 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c @@ -906,6 +906,47 @@ static void print_tracepoint_events(void) } /* + * Check whether event is in /tracing/events + */ + +int is_valid_tracepoint(const char *event_string) +{ + DIR *sys_dir, *evt_dir; + struct dirent *sys_next, *evt_next, sys_dirent, evt_dirent; + char evt_path[MAXPATHLEN]; + char dir_path[MAXPATHLEN]; + + if (debugfs_valid_mountpoint(debugfs_path)) + return 0; + + sys_dir = opendir(debugfs_path); + if (!sys_dir) + return 0; + + for_each_subsystem(sys_dir, sys_dirent, sys_next) { + + snprintf(dir_path, MAXPATHLEN, "%s/%s", debugfs_path, + sys_dirent.d_name); + evt_dir = opendir(dir_path); + if (!evt_dir) + continue; + + for_each_event(sys_dirent, evt_dir, evt_dirent, evt_next) { + snprintf(evt_path, MAXPATHLEN, "%s:%s", + sys_dirent.d_name, evt_dirent.d_name); + if (!strcmp(evt_path, event_string)) { + closedir(evt_dir); + closedir(sys_dir); + return 1; + } + } + closedir(evt_dir); + } + closedir(sys_dir); + return 0; +} + +/* * Print the help text for the event symbols: */ void print_events(void) diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h index fc4ab3f..7ab4685 100644 --- a/tools/perf/util/parse-events.h +++ b/tools/perf/util/parse-events.h @@ -29,6 +29,7 @@ extern int parse_filter(const struct option *opt, const char *str, int unset); #define EVENTS_HELP_MAX (128*1024) extern void print_events(void); +extern int is_valid_tracepoint(const char *event_string); extern char debugfs_path[]; extern int valid_debugfs_mount(const char *debugfs);