Commit f4eccb6d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'perfcounters-fixes-for-linus' of...

Merge branch 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'perfcounters-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  perf_counter, powerpc, sparc: Fix compilation after perf_counter_overflow() change
  perf_counter: x86: Fix PMU resource leak
  perf util: SVG performance improvements
  perf util: Make the timechart SVG width dynamic
  perf timechart: Show the duration of scheduler delays in the SVG
  perf timechart: Show the name of the waker/wakee in timechart
parents 8e4bc3dd cd74c86b
...@@ -1162,7 +1162,6 @@ static void record_and_restart(struct perf_counter *counter, unsigned long val, ...@@ -1162,7 +1162,6 @@ static void record_and_restart(struct perf_counter *counter, unsigned long val,
*/ */
if (record) { if (record) {
struct perf_sample_data data = { struct perf_sample_data data = {
.regs = regs,
.addr = 0, .addr = 0,
.period = counter->hw.last_period, .period = counter->hw.last_period,
}; };
...@@ -1170,7 +1169,7 @@ static void record_and_restart(struct perf_counter *counter, unsigned long val, ...@@ -1170,7 +1169,7 @@ static void record_and_restart(struct perf_counter *counter, unsigned long val,
if (counter->attr.sample_type & PERF_SAMPLE_ADDR) if (counter->attr.sample_type & PERF_SAMPLE_ADDR)
perf_get_data_addr(regs, &data.addr); perf_get_data_addr(regs, &data.addr);
if (perf_counter_overflow(counter, nmi, &data)) { if (perf_counter_overflow(counter, nmi, &data, regs)) {
/* /*
* Interrupts are coming too fast - throttle them * Interrupts are coming too fast - throttle them
* by setting the counter to 0, so it will be * by setting the counter to 0, so it will be
......
...@@ -493,7 +493,6 @@ static int __kprobes perf_counter_nmi_handler(struct notifier_block *self, ...@@ -493,7 +493,6 @@ static int __kprobes perf_counter_nmi_handler(struct notifier_block *self,
regs = args->regs; regs = args->regs;
data.regs = regs;
data.addr = 0; data.addr = 0;
cpuc = &__get_cpu_var(cpu_hw_counters); cpuc = &__get_cpu_var(cpu_hw_counters);
...@@ -513,7 +512,7 @@ static int __kprobes perf_counter_nmi_handler(struct notifier_block *self, ...@@ -513,7 +512,7 @@ static int __kprobes perf_counter_nmi_handler(struct notifier_block *self,
if (!sparc_perf_counter_set_period(counter, hwc, idx)) if (!sparc_perf_counter_set_period(counter, hwc, idx))
continue; continue;
if (perf_counter_overflow(counter, 1, &data)) if (perf_counter_overflow(counter, 1, &data, regs))
sparc_pmu_disable_counter(hwc, idx); sparc_pmu_disable_counter(hwc, idx);
} }
......
...@@ -924,6 +924,8 @@ static int __hw_perf_counter_init(struct perf_counter *counter) ...@@ -924,6 +924,8 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
if (err) if (err)
return err; return err;
counter->destroy = hw_perf_counter_destroy;
/* /*
* Generate PMC IRQs: * Generate PMC IRQs:
* (keep 'enabled' bit clear for now) * (keep 'enabled' bit clear for now)
...@@ -953,8 +955,6 @@ static int __hw_perf_counter_init(struct perf_counter *counter) ...@@ -953,8 +955,6 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
counter->destroy = hw_perf_counter_destroy;
/* /*
* Raw event type provide the config in the event structure * Raw event type provide the config in the event structure
*/ */
...@@ -2107,8 +2107,11 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter) ...@@ -2107,8 +2107,11 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter)
int err; int err;
err = __hw_perf_counter_init(counter); err = __hw_perf_counter_init(counter);
if (err) if (err) {
if (counter->destroy)
counter->destroy(counter);
return ERR_PTR(err); return ERR_PTR(err);
}
return &pmu; return &pmu;
} }
......
...@@ -849,23 +849,6 @@ static inline void perf_counter_comm(struct task_struct *tsk) { } ...@@ -849,23 +849,6 @@ static inline void perf_counter_comm(struct task_struct *tsk) { }
static inline void perf_counter_fork(struct task_struct *tsk) { } static inline void perf_counter_fork(struct task_struct *tsk) { }
static inline void perf_counter_init(void) { } static inline void perf_counter_init(void) { }
static inline int
perf_output_begin(struct perf_output_handle *handle, struct perf_counter *c,
unsigned int size, int nmi, int sample) { }
static inline void perf_output_end(struct perf_output_handle *handle) { }
static inline void
perf_output_copy(struct perf_output_handle *handle,
const void *buf, unsigned int len) { }
static inline void
perf_output_sample(struct perf_output_handle *handle,
struct perf_event_header *header,
struct perf_sample_data *data,
struct perf_counter *counter) { }
static inline void
perf_prepare_sample(struct perf_event_header *header,
struct perf_sample_data *data,
struct perf_counter *counter,
struct pt_regs *regs) { }
#endif #endif
#define perf_output_put(handle, x) \ #define perf_output_put(handle, x) \
......
...@@ -28,6 +28,9 @@ OPTIONS ...@@ -28,6 +28,9 @@ OPTIONS
-i:: -i::
--input=:: --input=::
Select the input file (default: perf.data) Select the input file (default: perf.data)
-w::
--width=::
Select the width of the SVG file (default: 1000)
SEE ALSO SEE ALSO
......
...@@ -752,6 +752,7 @@ static void draw_wakeups(void) ...@@ -752,6 +752,7 @@ static void draw_wakeups(void)
we = wake_events; we = wake_events;
while (we) { while (we) {
int from = 0, to = 0; int from = 0, to = 0;
char *task_from = NULL, *task_to = NULL;
/* locate the column of the waker and wakee */ /* locate the column of the waker and wakee */
p = all_data; p = all_data;
...@@ -760,10 +761,14 @@ static void draw_wakeups(void) ...@@ -760,10 +761,14 @@ static void draw_wakeups(void)
c = p->all; c = p->all;
while (c) { while (c) {
if (c->Y && c->start_time <= we->time && c->end_time >= we->time) { if (c->Y && c->start_time <= we->time && c->end_time >= we->time) {
if (p->pid == we->waker) if (p->pid == we->waker) {
from = c->Y; from = c->Y;
if (p->pid == we->wakee) task_from = c->comm;
}
if (p->pid == we->wakee) {
to = c->Y; to = c->Y;
task_to = c->comm;
}
} }
c = c->next; c = c->next;
} }
...@@ -776,7 +781,7 @@ static void draw_wakeups(void) ...@@ -776,7 +781,7 @@ static void draw_wakeups(void)
else if (from && to && abs(from - to) == 1) else if (from && to && abs(from - to) == 1)
svg_wakeline(we->time, from, to); svg_wakeline(we->time, from, to);
else else
svg_partial_wakeline(we->time, from, to); svg_partial_wakeline(we->time, from, task_from, to, task_to);
we = we->next; we = we->next;
} }
} }
...@@ -822,15 +827,15 @@ static void draw_process_bars(void) ...@@ -822,15 +827,15 @@ static void draw_process_bars(void)
continue; continue;
} }
svg_box(Y, p->start_time, p->end_time, "process"); svg_box(Y, c->start_time, c->end_time, "process");
sample = c->samples; sample = c->samples;
while (sample) { while (sample) {
if (sample->type == TYPE_RUNNING) if (sample->type == TYPE_RUNNING)
svg_sample(Y, sample->cpu, sample->start_time, sample->end_time, "sample"); svg_sample(Y, sample->cpu, sample->start_time, sample->end_time);
if (sample->type == TYPE_BLOCKED) if (sample->type == TYPE_BLOCKED)
svg_box(Y, sample->start_time, sample->end_time, "blocked"); svg_box(Y, sample->start_time, sample->end_time, "blocked");
if (sample->type == TYPE_WAITING) if (sample->type == TYPE_WAITING)
svg_box(Y, sample->start_time, sample->end_time, "waiting"); svg_waiting(Y, sample->start_time, sample->end_time);
sample = sample->next; sample = sample->next;
} }
...@@ -910,9 +915,9 @@ static void write_svg_file(const char *filename) ...@@ -910,9 +915,9 @@ static void write_svg_file(const char *filename)
if (count < 15) if (count < 15)
count = determine_display_tasks(TIME_THRESH / 10); count = determine_display_tasks(TIME_THRESH / 10);
open_svg(filename, numcpus, count); open_svg(filename, numcpus, count, first_time, last_time);
svg_time_grid(first_time, last_time); svg_time_grid();
svg_legenda(); svg_legenda();
for (i = 0; i < numcpus; i++) for (i = 0; i < numcpus; i++)
...@@ -1127,6 +1132,8 @@ static const struct option options[] = { ...@@ -1127,6 +1132,8 @@ static const struct option options[] = {
"input file name"), "input file name"),
OPT_STRING('o', "output", &output_name, "file", OPT_STRING('o', "output", &output_name, "file",
"output file name"), "output file name"),
OPT_INTEGER('w', "width", &svg_page_width,
"page width"),
OPT_END() OPT_END()
}; };
......
This diff is collapsed.
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
#include "types.h" #include "types.h"
extern void open_svg(const char *filename, int cpus, int rows); extern void open_svg(const char *filename, int cpus, int rows, u64 start, u64 end);
extern void svg_box(int Yslot, u64 start, u64 end, const char *type); extern void svg_box(int Yslot, u64 start, u64 end, const char *type);
extern void svg_sample(int Yslot, int cpu, u64 start, u64 end, const char *type); extern void svg_sample(int Yslot, int cpu, u64 start, u64 end);
extern void svg_waiting(int Yslot, u64 start, u64 end);
extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency); extern void svg_cpu_box(int cpu, u64 max_frequency, u64 turbo_frequency);
...@@ -14,12 +15,14 @@ extern void svg_cstate(int cpu, u64 start, u64 end, int type); ...@@ -14,12 +15,14 @@ extern void svg_cstate(int cpu, u64 start, u64 end, int type);
extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq); extern void svg_pstate(int cpu, u64 start, u64 end, u64 freq);
extern void svg_time_grid(u64 start, u64 end); extern void svg_time_grid(void);
extern void svg_legenda(void); extern void svg_legenda(void);
extern void svg_wakeline(u64 start, int row1, int row2); extern void svg_wakeline(u64 start, int row1, int row2);
extern void svg_partial_wakeline(u64 start, int row1, int row2); extern void svg_partial_wakeline(u64 start, int row1, char *desc1, int row2, char *desc2);
extern void svg_interrupt(u64 start, int row); extern void svg_interrupt(u64 start, int row);
extern void svg_text(int Yslot, u64 start, const char *text); extern void svg_text(int Yslot, u64 start, const char *text);
extern void svg_close(void); extern void svg_close(void);
extern int svg_page_width;
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment