perf timechart: dynamically determine event fields offset

Since b000c8065a "tracing: Remove the extra 4 bytes of padding in
events" removed padding bytes, perf timechart got out of sync with the
kernel's trace_entry structure.

Convert perf timechart to use dynamic fields offsets (via
perf_evsel__intval) not relying on a hardcoded copy of fields layout
from the kernel.

Signed-off-by: Stanislav Fomichev <stfomichev@yandex-team.ru>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Chia-I Wu <olvaffe@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/20131127104459.GB3309@stfomichev-desktop
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Stanislav Fomichev 2013-11-27 14:45:00 +04:00 committed by Arnaldo Carvalho de Melo
parent 449867e346
commit 3ed0d21e11
1 changed files with 42 additions and 77 deletions

View File

@ -306,50 +306,10 @@ static int process_exit_event(struct perf_tool *tool __maybe_unused,
return 0; return 0;
} }
struct trace_entry {
unsigned short type;
unsigned char flags;
unsigned char preempt_count;
int pid;
int lock_depth;
};
#ifdef SUPPORT_OLD_POWER_EVENTS #ifdef SUPPORT_OLD_POWER_EVENTS
static int use_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 #endif
struct power_processor_entry {
struct trace_entry te;
u32 state;
u32 cpu_id;
};
#define TASK_COMM_LEN 16
struct wakeup_entry {
struct trace_entry te;
char comm[TASK_COMM_LEN];
int pid;
int prio;
int success;
};
struct sched_switch {
struct trace_entry te;
char prev_comm[TASK_COMM_LEN];
int prev_pid;
int prev_prio;
long prev_state; /* Arjan weeps. */
char next_comm[TASK_COMM_LEN];
int next_pid;
int next_prio;
};
static void c_state_start(int cpu, u64 timestamp, int state) static void c_state_start(int cpu, u64 timestamp, int state)
{ {
cpus_cstate_start_times[cpu] = timestamp; cpus_cstate_start_times[cpu] = timestamp;
@ -409,25 +369,23 @@ static void p_state_change(int cpu, u64 timestamp, u64 new_freq)
turbo_frequency = max_freq; turbo_frequency = max_freq;
} }
static void static void sched_wakeup(int cpu, u64 timestamp, int waker, int wakee,
sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te, u8 flags, const char *backtrace)
const char *backtrace)
{ {
struct per_pid *p; struct per_pid *p;
struct wakeup_entry *wake = (void *)te;
struct wake_event *we = zalloc(sizeof(*we)); struct wake_event *we = zalloc(sizeof(*we));
if (!we) if (!we)
return; return;
we->time = timestamp; we->time = timestamp;
we->waker = pid; we->waker = waker;
we->backtrace = backtrace; we->backtrace = backtrace;
if ((te->flags & TRACE_FLAG_HARDIRQ) || (te->flags & TRACE_FLAG_SOFTIRQ)) if ((flags & TRACE_FLAG_HARDIRQ) || (flags & TRACE_FLAG_SOFTIRQ))
we->waker = -1; we->waker = -1;
we->wakee = wake->pid; we->wakee = wakee;
we->next = wake_events; we->next = wake_events;
wake_events = we; wake_events = we;
p = find_create_pid(we->wakee); p = find_create_pid(we->wakee);
@ -444,24 +402,22 @@ sched_wakeup(int cpu, u64 timestamp, int pid, struct trace_entry *te,
} }
} }
static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te, static void sched_switch(int cpu, u64 timestamp, int prev_pid, int next_pid,
const char *backtrace) u64 prev_state, const char *backtrace)
{ {
struct per_pid *p = NULL, *prev_p; struct per_pid *p = NULL, *prev_p;
struct sched_switch *sw = (void *)te;
prev_p = find_create_pid(prev_pid);
prev_p = find_create_pid(sw->prev_pid); p = find_create_pid(next_pid);
p = find_create_pid(sw->next_pid);
if (prev_p->current && prev_p->current->state != TYPE_NONE) if (prev_p->current && prev_p->current->state != TYPE_NONE)
pid_put_sample(sw->prev_pid, TYPE_RUNNING, cpu, pid_put_sample(prev_pid, TYPE_RUNNING, cpu,
prev_p->current->state_since, timestamp, prev_p->current->state_since, timestamp,
backtrace); backtrace);
if (p && p->current) { if (p && p->current) {
if (p->current->state != TYPE_NONE) if (p->current->state != TYPE_NONE)
pid_put_sample(sw->next_pid, p->current->state, cpu, pid_put_sample(next_pid, p->current->state, cpu,
p->current->state_since, timestamp, p->current->state_since, timestamp,
backtrace); backtrace);
@ -472,9 +428,9 @@ static void sched_switch(int cpu, u64 timestamp, struct trace_entry *te,
if (prev_p->current) { if (prev_p->current) {
prev_p->current->state = TYPE_NONE; prev_p->current->state = TYPE_NONE;
prev_p->current->state_since = timestamp; prev_p->current->state_since = timestamp;
if (sw->prev_state & 2) if (prev_state & 2)
prev_p->current->state = TYPE_BLOCKED; prev_p->current->state = TYPE_BLOCKED;
if (sw->prev_state == 0) if (prev_state == 0)
prev_p->current->state = TYPE_WAITING; prev_p->current->state = TYPE_WAITING;
} }
} }
@ -586,61 +542,69 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
} }
static int static int
process_sample_cpu_idle(struct perf_evsel *evsel __maybe_unused, process_sample_cpu_idle(struct perf_evsel *evsel,
struct perf_sample *sample, struct perf_sample *sample,
const char *backtrace __maybe_unused) const char *backtrace __maybe_unused)
{ {
struct power_processor_entry *ppe = sample->raw_data; u32 state = perf_evsel__intval(evsel, sample, "state");
u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
if (ppe->state == (u32) PWR_EVENT_EXIT) if (state == (u32)PWR_EVENT_EXIT)
c_state_end(ppe->cpu_id, sample->time); c_state_end(cpu_id, sample->time);
else else
c_state_start(ppe->cpu_id, sample->time, ppe->state); c_state_start(cpu_id, sample->time, state);
return 0; return 0;
} }
static int static int
process_sample_cpu_frequency(struct perf_evsel *evsel __maybe_unused, process_sample_cpu_frequency(struct perf_evsel *evsel,
struct perf_sample *sample, struct perf_sample *sample,
const char *backtrace __maybe_unused) const char *backtrace __maybe_unused)
{ {
struct power_processor_entry *ppe = sample->raw_data; u32 state = perf_evsel__intval(evsel, sample, "state");
u32 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
p_state_change(ppe->cpu_id, sample->time, ppe->state); p_state_change(cpu_id, sample->time, state);
return 0; return 0;
} }
static int static int
process_sample_sched_wakeup(struct perf_evsel *evsel __maybe_unused, process_sample_sched_wakeup(struct perf_evsel *evsel,
struct perf_sample *sample, struct perf_sample *sample,
const char *backtrace) const char *backtrace)
{ {
struct trace_entry *te = sample->raw_data; u8 flags = perf_evsel__intval(evsel, sample, "common_flags");
int waker = perf_evsel__intval(evsel, sample, "common_pid");
int wakee = perf_evsel__intval(evsel, sample, "pid");
sched_wakeup(sample->cpu, sample->time, sample->pid, te, backtrace); sched_wakeup(sample->cpu, sample->time, waker, wakee, flags, backtrace);
return 0; return 0;
} }
static int static int
process_sample_sched_switch(struct perf_evsel *evsel __maybe_unused, process_sample_sched_switch(struct perf_evsel *evsel,
struct perf_sample *sample, struct perf_sample *sample,
const char *backtrace) const char *backtrace)
{ {
struct trace_entry *te = sample->raw_data; int prev_pid = perf_evsel__intval(evsel, sample, "prev_pid");
int next_pid = perf_evsel__intval(evsel, sample, "next_pid");
u64 prev_state = perf_evsel__intval(evsel, sample, "prev_state");
sched_switch(sample->cpu, sample->time, te, backtrace); sched_switch(sample->cpu, sample->time, prev_pid, next_pid, prev_state,
backtrace);
return 0; return 0;
} }
#ifdef SUPPORT_OLD_POWER_EVENTS #ifdef SUPPORT_OLD_POWER_EVENTS
static int static int
process_sample_power_start(struct perf_evsel *evsel __maybe_unused, process_sample_power_start(struct perf_evsel *evsel,
struct perf_sample *sample, struct perf_sample *sample,
const char *backtrace __maybe_unused) const char *backtrace __maybe_unused)
{ {
struct power_entry_old *peo = sample->raw_data; u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
u64 value = perf_evsel__intval(evsel, sample, "value");
c_state_start(peo->cpu_id, sample->time, peo->value); c_state_start(cpu_id, sample->time, value);
return 0; return 0;
} }
@ -654,13 +618,14 @@ process_sample_power_end(struct perf_evsel *evsel __maybe_unused,
} }
static int static int
process_sample_power_frequency(struct perf_evsel *evsel __maybe_unused, process_sample_power_frequency(struct perf_evsel *evsel,
struct perf_sample *sample, struct perf_sample *sample,
const char *backtrace __maybe_unused) const char *backtrace __maybe_unused)
{ {
struct power_entry_old *peo = sample->raw_data; u64 cpu_id = perf_evsel__intval(evsel, sample, "cpu_id");
u64 value = perf_evsel__intval(evsel, sample, "value");
p_state_change(peo->cpu_id, sample->time, peo->value); p_state_change(cpu_id, sample->time, value);
return 0; return 0;
} }
#endif /* SUPPORT_OLD_POWER_EVENTS */ #endif /* SUPPORT_OLD_POWER_EVENTS */