* [PATCH 3/8] X86/perf: fix power:cpu_idle double end events and throw cpu_idle events from the cpuidle layer
[not found] ` <1291308148-28628-3-git-send-email-trenn@suse.de>
@ 2010-12-02 16:42 ` Thomas Renninger
[not found] ` <1291308148-28628-5-git-send-email-trenn@suse.de>
0 siblings, 1 reply; 4+ messages in thread
From: Thomas Renninger @ 2010-12-02 16:42 UTC (permalink / raw)
Cc: Thomas Renninger, Robert Schoene, Jean Pihet, Arjan van de Ven,
Ingo Molnar, Len Brown, linux-pm, linux-acpi, linux-kernel,
linux-perf-users, linux-omap
Currently intel_idle and acpi_idle driver show double cpu_idle "exit idle"
events -> this patch fixes it and makes cpu_idle events throwing less complex.
It also introduces cpu_idle events for all architectures which use
the cpuidle subsystem, namely:
- arch/arm/mach-at91/cpuidle.c
- arch/arm/mach-davinci/cpuidle.c
- arch/arm/mach-kirkwood/cpuidle.c
- arch/arm/mach-omap2/cpuidle34xx.c
- arch/drivers/acpi/processor_idle.c (for all cases, not only mwait)
- arch/x86/kernel/process.c (did throw events before, but was a mess)
- drivers/idle/intel_idle.c (did throw events before)
Convention should be:
Fire cpu_idle events inside the current pm_idle function (not somewhere
down the the callee tree) to keep things easy.
Current possible pm_idle functions in X86:
c1e_idle, poll_idle, cpuidle_idle_call, mwait_idle, default_idle
-> this is really easy is now.
This affects userspace:
The type field of the cpu_idle power event can now direclty get
mapped to:
/sys/devices/system/cpu/cpuX/cpuidle/stateX/{name,desc,usage,time,...}
instead of throwing very CPU/mwait specific values.
This change is not visible for the intel_idle driver.
For the acpi_idle driver it should only be visible if the vendor
misses out C-states in his BIOS.
Another (perf timechart) patch reads out cpuidle info of cpu_idle
events from:
/sys/.../cpuidle/stateX/*, then the cpuidle events are mapped
to the correct C-/cpuidle state again, even if e.g. vendors miss
out C-states in their BIOS and for example only export C1 and C3.
-> everything is fine.
Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: Robert Schoene <robert.schoene@tu-dresden.de>
CC: Jean Pihet <j-pihet@ti.com>
CC: Arjan van de Ven <arjan@linux.intel.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: Len Brown <lenb@kernel.org>
CC: linux-pm@lists.linux-foundation.org
CC: linux-acpi@vger.kernel.org
CC: linux-kernel@vger.kernel.org
CC: linux-perf-users@vger.kernel.org
CC: linux-omap@vger.kernel.org
---
arch/x86/kernel/process.c | 6 ++++--
arch/x86/kernel/process_32.c | 4 ----
arch/x86/kernel/process_64.c | 6 ------
drivers/cpuidle/cpuidle.c | 10 ++++++++--
drivers/idle/intel_idle.c | 2 --
5 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 155d975..b618548 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -387,6 +387,8 @@ void default_idle(void)
else
local_irq_enable();
current_thread_info()->status |= TS_POLLING;
+ trace_power_end(smp_processor_id());
+ trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
} else {
local_irq_enable();
/* loop is done by the caller */
@@ -444,8 +446,6 @@ EXPORT_SYMBOL_GPL(cpu_idle_wait);
*/
void mwait_idle_with_hints(unsigned long ax, unsigned long cx)
{
- trace_power_start(POWER_CSTATE, (ax>>4)+1, smp_processor_id());
- trace_cpu_idle((ax>>4)+1, smp_processor_id());
if (!need_resched()) {
if (cpu_has(¤t_cpu_data, X86_FEATURE_CLFLUSH_MONITOR))
clflush((void *)¤t_thread_info()->flags);
@@ -472,6 +472,8 @@ static void mwait_idle(void)
__sti_mwait(0, 0);
else
local_irq_enable();
+ trace_power_end(smp_processor_id());
+ trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
} else
local_irq_enable();
}
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index 4b9befa..8d12878 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -57,8 +57,6 @@
#include <asm/syscalls.h>
#include <asm/debugreg.h>
-#include <trace/events/power.h>
-
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
/*
@@ -113,8 +111,6 @@ void cpu_idle(void)
stop_critical_timings();
pm_idle();
start_critical_timings();
- trace_power_end(smp_processor_id());
- trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
}
tick_nohz_restart_sched_tick();
preempt_enable_no_resched();
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 4c818a7..bd387e8 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -51,8 +51,6 @@
#include <asm/syscalls.h>
#include <asm/debugreg.h>
-#include <trace/events/power.h>
-
asmlinkage extern void ret_from_fork(void);
DEFINE_PER_CPU(unsigned long, old_rsp);
@@ -141,10 +139,6 @@ void cpu_idle(void)
pm_idle();
start_critical_timings();
- trace_power_end(smp_processor_id());
- trace_cpu_idle(PWR_EVENT_EXIT,
- smp_processor_id());
-
/* In many cases the interrupt that ended idle
has already called exit_idle. But some idle
loops can be woken up without interrupt. */
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 99cc8fc..4649495 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -96,7 +96,15 @@ static void cpuidle_idle_call(void)
/* enter the state and update stats */
dev->last_state = target_state;
+
+ trace_power_start(POWER_CSTATE, next_state, dev->cpu);
+ trace_cpu_idle(next_state, dev->cpu);
+
dev->last_residency = target_state->enter(dev, target_state);
+
+ trace_power_end(dev->cpu);
+ trace_cpu_idle(PWR_EVENT_EXIT, dev->cpu);
+
if (dev->last_state)
target_state = dev->last_state;
@@ -106,8 +114,6 @@ static void cpuidle_idle_call(void)
/* give the governor an opportunity to reflect on the outcome */
if (cpuidle_curr_governor->reflect)
cpuidle_curr_governor->reflect(dev);
- trace_power_end(smp_processor_id());
- trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
}
/**
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index ba5134f..60414ae 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -220,8 +220,6 @@ static int intel_idle(struct cpuidle_device *dev, struct cpuidle_state *state)
kt_before = ktime_get_real();
stop_critical_timings();
- trace_power_start(POWER_CSTATE, (eax >> 4) + 1, cpu);
- trace_cpu_idle((eax >> 4) + 1, cpu);
if (!need_resched()) {
__monitor((void *)¤t_thread_info()->flags, 0, 0);
--
1.6.0.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 7/8] perf timechart: Map power:cpu_idle events to the corresponding cpuidle state
[not found] ` <1291308148-28628-7-git-send-email-trenn@suse.de>
@ 2010-12-02 16:42 ` Thomas Renninger
2010-12-02 16:42 ` [PATCH 8/8] perf: timechart: Fix memleak Thomas Renninger
2010-12-02 16:51 ` [PATCH 7/8] perf timechart: Map power:cpu_idle events to the corresponding cpuidle state Thomas Renninger
0 siblings, 2 replies; 4+ messages in thread
From: Thomas Renninger @ 2010-12-02 16:42 UTC (permalink / raw)
Cc: Thomas Renninger, lenb, linux-acpi, linux-pm, Arjan van de Ven,
Ingo Molnar, linux-kernel, linux-perf-users, linux-omap
Before, power:cpu_idle events were very specific X86 Intel mwait events.
This got fixed with previous patches and cpu_idle events are now thrown by
all cpuidle drivers and can be mapped to the corresponding cpuidle state
in /sys.
This patch reads out the corresponding cpuidle name of a cpu_idle event
and uses it in the title line of the chart (c-states Cx in x86, omap2
- DDR self refresh states for various arm archs).
It also reads out the corresponding abbr(eviation) and uses the string
to draw the cpu idle occurences. This needs a short (3 letter) string
to keep the overview in the chart.
Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: lenb@kernel.org
CC: linux-acpi@vger.kernel.org
CC: linux-pm@lists.linux-foundation.org
CC: Arjan van de Ven <arjan@linux.intel.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: linux-kernel@vger.kernel.org
CC: linux-perf-users@vger.kernel.org
CC: linux-omap@vger.kernel.org
---
tools/perf/builtin-timechart.c | 26 ++++++-
tools/perf/util/svghelper.c | 156 +++++++++++++++++++++++++++++++++++-----
2 files changed, 163 insertions(+), 19 deletions(-)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 148dc5e..391e475 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -31,6 +31,7 @@
#include "util/event.h"
#include "util/session.h"
#include "util/svghelper.h"
+#include "util/debug.h"
#define SUPPORT_OLD_POWER_EVENTS 1
#define PWR_EVENT_EXIT -1
@@ -379,6 +380,10 @@ static void c_state_end(int cpu, u64 timestamp)
pwr->next = power_events;
power_events = pwr;
+ if (verbose)
+ printf("CPU: %d - start_time: %llu - end_time: %llu\n",
+ power_events->cpu, power_events->start_time,
+ power_events->end_time);
}
static void p_state_change(int cpu, u64 timestamp, u64 new_freq)
@@ -657,8 +662,25 @@ static void draw_c_p_states(void)
* two pass drawing so that the P state bars are on top of the C state blocks
*/
while (pwr) {
- if (pwr->type == CSTATE)
- svg_cstate(pwr->cpu, pwr->start_time, pwr->end_time, pwr->state);
+ if (pwr->type == CSTATE) {
+ if (verbose) {
+ printf("CPU: %d, Start: %llu, End: %llu, type:"
+ " %d\n", pwr->cpu, pwr->start_time,
+ pwr->end_time, pwr->state);
+ }
+ /* trenn: Looks like there is a dummy c-state entry of
+ * type==0, start_time==0, end_time==highest_timestamp
+ * for each CPU at the end of the list, this one should
+ * better be filtered out before -> ignore it here.
+ */
+ if ((pwr->state == 0 && pwr->start_time == 0)) {
+ pwr = pwr->next;
+ continue;
+ }
+
+ svg_cstate(pwr->cpu, pwr->start_time, pwr->end_time,
+ pwr->state);
+ }
pwr = pwr->next;
}
diff --git a/tools/perf/util/svghelper.c b/tools/perf/util/svghelper.c
index b3637db..20c02fc 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -16,8 +16,13 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <linux/cpuidle.h>
#include "svghelper.h"
+#include "debug.h"
static u64 first_time, last_time;
static u64 turbo_frequency, max_freq;
@@ -43,11 +48,11 @@ static double cpu2y(int cpu)
return cpu2slot(cpu) * SLOT_MULT;
}
-static double time2pixels(u64 time)
+static double time2pixels(u64 __time)
{
double X;
- X = 1.0 * svg_page_width * (time - first_time) / (last_time - first_time);
+ X = 1.0 * svg_page_width * (__time - first_time) / (last_time - first_time);
return X;
}
@@ -107,12 +112,14 @@ void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end)
fprintf(svgfile, " rect.WAITING { fill:rgb(255,214, 48); fill-opacity:0.6; stroke-width:0; stroke:rgb( 0, 0, 0); } \n");
fprintf(svgfile, " rect.cpu { fill:rgb(192,192,192); fill-opacity:0.2; stroke-width:0.5; stroke:rgb(128,128,128); } \n");
fprintf(svgfile, " rect.pstate { fill:rgb(128,128,128); fill-opacity:0.8; stroke-width:0; } \n");
- fprintf(svgfile, " rect.c1 { fill:rgb(255,214,214); fill-opacity:0.5; stroke-width:0; } \n");
- fprintf(svgfile, " rect.c2 { fill:rgb(255,172,172); fill-opacity:0.5; stroke-width:0; } \n");
- fprintf(svgfile, " rect.c3 { fill:rgb(255,130,130); fill-opacity:0.5; stroke-width:0; } \n");
- fprintf(svgfile, " rect.c4 { fill:rgb(255, 88, 88); fill-opacity:0.5; stroke-width:0; } \n");
- fprintf(svgfile, " rect.c5 { fill:rgb(255, 44, 44); fill-opacity:0.5; stroke-width:0; } \n");
- fprintf(svgfile, " rect.c6 { fill:rgb(255, 0, 0); fill-opacity:0.5; stroke-width:0; } \n");
+ fprintf(svgfile, " rect.c0 { fill:rgb(102,255,102); fill-opacity:0.5; stroke-width:0; } \n");
+ fprintf(svgfile, " rect.c1 { fill:rgb(102,255, 0); fill-opacity:0.5; stroke-width:0; } \n");
+ fprintf(svgfile, " rect.c2 { fill:rgb( 0,255,102); fill-opacity:0.5; stroke-width:0; } \n");
+ fprintf(svgfile, " rect.c3 { fill:rgb( 51,255, 51); fill-opacity:0.5; stroke-width:0; } \n");
+ fprintf(svgfile, " rect.c4 { fill:rgb( 51,255, 0); fill-opacity:0.5; stroke-width:0; } \n");
+ fprintf(svgfile, " rect.c5 { fill:rgb( 0,255, 51); fill-opacity:0.5; stroke-width:0; } \n");
+ fprintf(svgfile, " rect.c6 { fill:rgb( 0,204, 0); fill-opacity:0.5; stroke-width:0; } \n");
+ fprintf(svgfile, " rect.c7 { fill:rgb( 0,153, 0); fill-opacity:0.5; stroke-width:0; } \n");
fprintf(svgfile, " line.pstate { stroke:rgb(255,255, 0); stroke-opacity:0.8; stroke-width:2; } \n");
fprintf(svgfile, " ]]>\n </style>\n</defs>\n");
@@ -199,6 +206,81 @@ void svg_waiting(int Yslot, u64 start, u64 end)
fprintf(svgfile, "</g>\n");
}
+/* Cpuidle info from sysfs ***************************/
+struct cpuidle_state cpuidle_states[CPUIDLE_STATE_MAX];
+unsigned int cpuidle_info_max;
+
+static void debug_dump_cpuidle_states(void)
+{
+ unsigned int state;
+
+ if (cpuidle_info_max == 0) {
+ printf("No cpuidle info retrieved from /sys\n");
+ return;
+ }
+ printf("cpuidle_info_max: %u\n", cpuidle_info_max);
+ for (state = 0; state < cpuidle_info_max; state++) {
+ printf("CPUIDLE[%u]:\n", state);
+ printf("Name: %s\n", cpuidle_states[state].name);
+ printf("Abbr: %s\n", cpuidle_states[state].abbr);
+ }
+}
+static int get_sysfs_string(const char *path, char *string,
+ int max_string_size)
+{
+ int fd;
+ size_t numread, i;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ numread = read(fd, string, max_string_size-1);
+ if (numread < 1) {
+ close(fd);
+ return -1;
+ }
+ for (i = 0; i < numread; i++)
+ if (string[i] == '\n')
+ string[i] = '\0';
+ string[numread] = '\0';
+ close(fd);
+ return 0;
+}
+
+#define PERF_CPUIDLE_SYS_PATH "/sys/devices/system/cpu/cpu0/cpuidle/state%u/"
+#define PERF_SYSFS_PATH_MAX 255
+
+/*
+ * Fills up cpuidle_states[CPUIDLE_STATE_MAX] info from
+ * /sys/devices/system/cpu/cpu0/cpuidle/stateX/ and sets cpuidle_info_max
+ * to found states
+ */
+static int retrieve_cpuidle_info(void)
+{
+ char path[PERF_SYSFS_PATH_MAX];
+ int state, ret;
+
+ for (state = 0; state < CPUIDLE_STATE_MAX; state++) {
+ snprintf(path, sizeof(path), PERF_CPUIDLE_SYS_PATH "name",
+ state);
+ ret = get_sysfs_string(path, cpuidle_states[state].name,
+ CPUIDLE_NAME_LEN + 1);
+ if (ret)
+ break;
+
+ snprintf(path, sizeof(path), PERF_CPUIDLE_SYS_PATH "abbr",
+ state);
+ ret = get_sysfs_string(path, cpuidle_states[state].abbr,
+ CPUIDLE_ABBR_LEN + 1);
+ if (ret)
+ break;
+ }
+ cpuidle_info_max = state;
+ return state;
+}
+/* Cpuidle info from sysfs ***************************/
+
static char *cpu_model(void)
{
static char cpu_m[255];
@@ -278,17 +360,33 @@ void svg_process(int cpu, u64 start, u64 end, const char *type, const char *name
fprintf(svgfile, "</g>\n");
}
+/*
+ * Svg util and kernel supported max cpuidle states may differ.
+ * Cmp. with tools/perf/utils/include/linux/cpuidle.h
+ * and include/linux/cpuidle.h
+ * Currently cpuidle kernel interface and this svg tool, both support 8 states
+ */
+#define PERF_SVG_CPUIDLE_STATE_MAX 8
+
void svg_cstate(int cpu, u64 start, u64 end, int type)
{
double width;
char style[128];
+ static bool max_states_exceed_msg;
if (!svgfile)
return;
+ if (type > PERF_SVG_CPUIDLE_STATE_MAX) {
+ if (verbose || max_states_exceed_msg == false) {
+ max_states_exceed_msg = true;
+ printf("cpuidle state (%d) exceeding max supported "
+ "states (%d).. ignoring\n",
+ type, PERF_SVG_CPUIDLE_STATE_MAX);
+ return;
+ }
+ }
- if (type > 6)
- type = 6;
sprintf(style, "c%i", type);
fprintf(svgfile, "<rect class=\"%s\" x=\"%4.8f\" width=\"%4.8f\" y=\"%4.1f\" height=\"%4.1f\"/>\n",
@@ -451,16 +549,40 @@ static void svg_legenda_box(int X, const char *text, const char *style)
void svg_legenda(void)
{
+ unsigned int cstate, offset = 500;
+ char class[3];
+
+ retrieve_cpuidle_info();
+ /* perf timechart does not implement a verbose (-v) param yet
+ remove below comment if you want to be more verbose. */
+ /* verbose = 1; */
+ if (verbose)
+ debug_dump_cpuidle_states();
+
if (!svgfile)
return;
- svg_legenda_box(0, "Running", "sample");
- svg_legenda_box(100, "Idle","rect.c1");
- svg_legenda_box(200, "Deeper Idle", "rect.c3");
- svg_legenda_box(350, "Deepest Idle", "rect.c6");
- svg_legenda_box(550, "Sleeping", "process2");
- svg_legenda_box(650, "Waiting for cpu", "waiting");
- svg_legenda_box(800, "Blocked on IO", "blocked");
+ svg_legenda_box(0, "Running", "sample");
+ svg_legenda_box(100, "Sleeping", "process2");
+ svg_legenda_box(200, "Waiting for cpu", "waiting");
+ svg_legenda_box(350, "Blocked on IO", "blocked");
+ /* trenn: Arch specific events. Only C1 exists on x86 if
+ no cpuidle driver registered. Deeper and Deepest can get
+ removed. Also C1 events may only get fired through cpuidle
+ driver at some time. */
+ if (cpuidle_info_max == 0) {
+ svg_legenda_box(500, "Idle", "c1");
+ } else {
+ for (cstate = 0; cstate < cpuidle_info_max; cstate++) {
+ sprintf(class, "c%u", cstate);
+ svg_legenda_box(offset, cpuidle_states[cstate].name,
+ class);
+ /* The box */
+ offset += 20;
+ /* The text */
+ offset += (strlen(cpuidle_states[cstate].name) * 10);
+ }
+ }
}
void svg_time_grid(void)
--
1.6.0.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 8/8] perf: timechart: Fix memleak
2010-12-02 16:42 ` [PATCH 7/8] perf timechart: Map power:cpu_idle events to the corresponding cpuidle state Thomas Renninger
@ 2010-12-02 16:42 ` Thomas Renninger
2010-12-02 16:51 ` [PATCH 7/8] perf timechart: Map power:cpu_idle events to the corresponding cpuidle state Thomas Renninger
1 sibling, 0 replies; 4+ messages in thread
From: Thomas Renninger @ 2010-12-02 16:42 UTC (permalink / raw)
Cc: Thomas Renninger, Arjan van de Ven, Ingo Molnar, linux-perf-users,
linux-kernel
There are others, but these are not worth it, e.g. built
up power event list which gets destroyed on program exit anyway or
some bytes when trace events get parsed.
This one showed by far the biggest memory waste, was easy to
fix and could help when parsing huge trace event records.
Signed-off-by: Thomas Renninger <trenn@suse.de>
CC: Arjan van de Ven <arjan@linux.intel.com>
CC: Ingo Molnar <mingo@elte.hu>
CC: linux-perf-users@vger.kernel.org
CC: linux-kernel@vger.kernel.org
Found with valgrind, fixes:
==43509== 1,402 bytes in 251 blocks are definitely lost in loss record 61 of 74
==43509== at 0x4C261D7: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==43509== by 0x61573B1: strdup (in /lib64/libc-2.11.1.so)
==43509== by 0x41DD3D: draw_wakeups (builtin-timechart.c:706)
==43509== by 0x41E7C9: write_svg_file (builtin-timechart.c:957)
==43509== by 0x41E87E: __cmd_timechart (builtin-timechart.c:989)
==43509== by 0x41EB3C: cmd_timechart (builtin-timechart.c:1097)
==43509== by 0x40D776: run_builtin (perf.c:286)
==43509== by 0x40D993: handle_internal_command (perf.c:357)
==43509== by 0x40DAD2: run_argv (perf.c:401)
==43509== by 0x40DCB3: main (perf.c:487)
==43509==
==43509== 2,826 bytes in 429 blocks are definitely lost in loss record 63 of 74
==43509== at 0x4C261D7: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==43509== by 0x61573B1: strdup (in /lib64/libc-2.11.1.so)
==43509== by 0x41DD70: draw_wakeups (builtin-timechart.c:710)
==43509== by 0x41E7C9: write_svg_file (builtin-timechart.c:957)
==43509== by 0x41E87E: __cmd_timechart (builtin-timechart.c:989)
==43509== by 0x41EB3C: cmd_timechart (builtin-timechart.c:1097)
==43509== by 0x40D776: run_builtin (perf.c:286)
==43509== by 0x40D993: handle_internal_command (perf.c:357)
==43509== by 0x40DAD2: run_argv (perf.c:401)
==43509== by 0x40DCB3: main (perf.c:487)
---
tools/perf/builtin-timechart.c | 8 ++++++++
1 files changed, 8 insertions(+), 0 deletions(-)
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 391e475..c6e0a00 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -715,10 +715,14 @@ static void draw_wakeups(void)
if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
if (p->pid == we->waker && !from) {
from = c->Y;
+ if (task_from)
+ free(task_from);
task_from = strdup(c->comm);
}
if (p->pid == we->wakee && !to) {
to = c->Y;
+ if (task_to)
+ free(task_to);
task_to = strdup(c->comm);
}
}
@@ -728,10 +732,14 @@ static void draw_wakeups(void)
while (c) {
if (p->pid == we->waker && !from) {
from = c->Y;
+ if (task_from)
+ free(task_from);
task_from = strdup(c->comm);
}
if (p->pid == we->wakee && !to) {
to = c->Y;
+ if (task_to)
+ free(task_to);
task_to = strdup(c->comm);
}
c = c->next;
--
1.6.0.2
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH 7/8] perf timechart: Map power:cpu_idle events to the corresponding cpuidle state
2010-12-02 16:42 ` [PATCH 7/8] perf timechart: Map power:cpu_idle events to the corresponding cpuidle state Thomas Renninger
2010-12-02 16:42 ` [PATCH 8/8] perf: timechart: Fix memleak Thomas Renninger
@ 2010-12-02 16:51 ` Thomas Renninger
1 sibling, 0 replies; 4+ messages in thread
From: Thomas Renninger @ 2010-12-02 16:51 UTC (permalink / raw)
To: lenb
Cc: linux-acpi, linux-pm, Arjan van de Ven, Ingo Molnar, linux-kernel,
linux-perf-users, linux-omap
On Thursday 02 December 2010 17:42:27 Thomas Renninger wrote:
> Before, power:cpu_idle events were very specific X86 Intel mwait events.
> This got fixed with previous patches and cpu_idle events are now thrown by
> all cpuidle drivers and can be mapped to the corresponding cpuidle state
> in /sys.
>
> This patch reads out the corresponding cpuidle name of a cpu_idle event
> and uses it in the title line of the chart (c-states Cx in x86, omap2
> - DDR self refresh states for various arm archs).
>
> It also reads out the corresponding abbr(eviation) and uses the string
> to draw the cpu idle occurences. This needs a short (3 letter) string
> to keep the overview in the chart.
I forgot two other changes:
- Fixes black c-state drawings in eog and firefox:
class="rect.cX" is wrong and must be class="cX"
- Use green color instead of red for idle drawings. This does not clash
with the Block IO drawings (also red) and better fits the "green IT"
background the C-states are about :) (that was not really the reason,
green was one of the last not used colors)...
Thomas
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2010-12-02 16:51 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <1291308148-28628-1-git-send-email-trenn@suse.de>
[not found] ` <1291308148-28628-2-git-send-email-trenn@suse.de>
[not found] ` <1291308148-28628-3-git-send-email-trenn@suse.de>
2010-12-02 16:42 ` [PATCH 3/8] X86/perf: fix power:cpu_idle double end events and throw cpu_idle events from the cpuidle layer Thomas Renninger
[not found] ` <1291308148-28628-5-git-send-email-trenn@suse.de>
[not found] ` <1291308148-28628-6-git-send-email-trenn@suse.de>
[not found] ` <1291308148-28628-7-git-send-email-trenn@suse.de>
2010-12-02 16:42 ` [PATCH 7/8] perf timechart: Map power:cpu_idle events to the corresponding cpuidle state Thomas Renninger
2010-12-02 16:42 ` [PATCH 8/8] perf: timechart: Fix memleak Thomas Renninger
2010-12-02 16:51 ` [PATCH 7/8] perf timechart: Map power:cpu_idle events to the corresponding cpuidle state Thomas Renninger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).