Skip to content

Commit

Permalink
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

 * Tidy up sample parsing validation, from Adrian Hunter.

 * Make events stream always parsable by adding a new sample_type bit:
   PERF_SAMPLE_IDENTIFIER, that when requested will be always aat a fixed
   position in all PERF_RECORD_ records, from Adrian Hunter.

 * Add a sample parsing test, from Adrian Hunter.

 * Add option to 'perf trace' to analyze events in a file versus live,
   so that one can do:

   [root@zoo ~]# perf record -a -e raw_syscalls:* sleep 1
   [ perf record: Woken up 0 times to write data ]
   [ perf record: Captured and wrote 25.150 MB perf.data (~1098836 samples) ]
   [root@zoo ~]# perf trace -i perf.data -e futex --duration 1
      17.799 ( 1.020 ms): 7127 futex(uaddr: 0x7fff3f6c6674, op: 393, val: 1, utime: 0x7fff3f6c6470, ua
     113.344 (95.429 ms): 7127 futex(uaddr: 0x7fff3f6c6674, op: 393, val: 1, utime: 0x7fff3f6c6470, uaddr2: 0x7fff3f6c6648, val3: 4294967
     133.778 ( 1.042 ms): 18004 futex(uaddr: 0x7fff3f6c6674, op: 393, val: 1, utime: 0x7fff3f6c6470, uaddr2: 0x7fff3f6c6648, val3: 429496
   [root@zoo ~]#

   From David Ahern.

 * Honor target pid / tid options in 'perf trace' when analyzing a file,
   from David Ahern.

 * Handle missing HUGEPAGE defines in the mmap beautifier in 'perf trace',
   from David Ahern.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Aug 31, 2013
2 parents 00e4cb1 + f2935f3 commit ea79ca0
Show file tree
Hide file tree
Showing 33 changed files with 1,193 additions and 195 deletions.
27 changes: 20 additions & 7 deletions include/uapi/linux/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,9 @@ enum perf_event_sample_format {
PERF_SAMPLE_STACK_USER = 1U << 13,
PERF_SAMPLE_WEIGHT = 1U << 14,
PERF_SAMPLE_DATA_SRC = 1U << 15,
PERF_SAMPLE_IDENTIFIER = 1U << 16,

PERF_SAMPLE_MAX = 1U << 16, /* non-ABI */
PERF_SAMPLE_MAX = 1U << 17, /* non-ABI */
};

/*
Expand Down Expand Up @@ -492,20 +493,25 @@ enum perf_event_type {
/*
* If perf_event_attr.sample_id_all is set then all event types will
* have the sample_type selected fields related to where/when
* (identity) an event took place (TID, TIME, ID, CPU, STREAM_ID)
* described in PERF_RECORD_SAMPLE below, it will be stashed just after
* the perf_event_header and the fields already present for the existing
* fields, i.e. at the end of the payload. That way a newer perf.data
* file will be supported by older perf tools, with these new optional
* fields being ignored.
* (identity) an event took place (TID, TIME, ID, STREAM_ID, CPU,
* IDENTIFIER) described in PERF_RECORD_SAMPLE below, it will be stashed
* just after the perf_event_header and the fields already present for
* the existing fields, i.e. at the end of the payload. That way a newer
* perf.data file will be supported by older perf tools, with these new
* optional fields being ignored.
*
* struct sample_id {
* { u32 pid, tid; } && PERF_SAMPLE_TID
* { u64 time; } && PERF_SAMPLE_TIME
* { u64 id; } && PERF_SAMPLE_ID
* { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
* { u32 cpu, res; } && PERF_SAMPLE_CPU
* { u64 id; } && PERF_SAMPLE_IDENTIFIER
* } && perf_event_attr::sample_id_all
*
* Note that PERF_SAMPLE_IDENTIFIER duplicates PERF_SAMPLE_ID. The
* advantage of PERF_SAMPLE_IDENTIFIER is that its position is fixed
* relative to header.size.
*/

/*
Expand Down Expand Up @@ -594,6 +600,13 @@ enum perf_event_type {
* struct {
* struct perf_event_header header;
*
* #
* # Note that PERF_SAMPLE_IDENTIFIER duplicates PERF_SAMPLE_ID.
* # The advantage of PERF_SAMPLE_IDENTIFIER is that its position
* # is fixed relative to header.
* #
*
* { u64 id; } && PERF_SAMPLE_IDENTIFIER
* { u64 ip; } && PERF_SAMPLE_IP
* { u32 pid, tid; } && PERF_SAMPLE_TID
* { u64 time; } && PERF_SAMPLE_TIME
Expand Down
11 changes: 10 additions & 1 deletion kernel/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,9 @@ static void perf_event__id_header_size(struct perf_event *event)
if (sample_type & PERF_SAMPLE_TIME)
size += sizeof(data->time);

if (sample_type & PERF_SAMPLE_IDENTIFIER)
size += sizeof(data->id);

if (sample_type & PERF_SAMPLE_ID)
size += sizeof(data->id);

Expand Down Expand Up @@ -4280,7 +4283,7 @@ static void __perf_event_header__init_id(struct perf_event_header *header,
if (sample_type & PERF_SAMPLE_TIME)
data->time = perf_clock();

if (sample_type & PERF_SAMPLE_ID)
if (sample_type & (PERF_SAMPLE_ID | PERF_SAMPLE_IDENTIFIER))
data->id = primary_event_id(event);

if (sample_type & PERF_SAMPLE_STREAM_ID)
Expand Down Expand Up @@ -4319,6 +4322,9 @@ static void __perf_event__output_id_sample(struct perf_output_handle *handle,

if (sample_type & PERF_SAMPLE_CPU)
perf_output_put(handle, data->cpu_entry);

if (sample_type & PERF_SAMPLE_IDENTIFIER)
perf_output_put(handle, data->id);
}

void perf_event__output_id_sample(struct perf_event *event,
Expand Down Expand Up @@ -4432,6 +4438,9 @@ void perf_output_sample(struct perf_output_handle *handle,

perf_output_put(handle, *header);

if (sample_type & PERF_SAMPLE_IDENTIFIER)
perf_output_put(handle, data->id);

if (sample_type & PERF_SAMPLE_IP)
perf_output_put(handle, data->ip);

Expand Down
4 changes: 4 additions & 0 deletions tools/perf/Documentation/perf-trace.txt
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
--sched:
Accrue thread runtime and provide a summary at the end of the session.

-i
--input
Process events from a given perf data file.

SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-script[1]
2 changes: 2 additions & 0 deletions tools/perf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ LIB_OBJS += $(OUTPUT)util/rblist.o
LIB_OBJS += $(OUTPUT)util/intlist.o
LIB_OBJS += $(OUTPUT)util/vdso.o
LIB_OBJS += $(OUTPUT)util/stat.o
LIB_OBJS += $(OUTPUT)util/record.o

LIB_OBJS += $(OUTPUT)ui/setup.o
LIB_OBJS += $(OUTPUT)ui/helpline.o
Expand Down Expand Up @@ -438,6 +439,7 @@ PERFLIBS = $(LIB_FILE) $(LIBLK) $(LIBTRACEEVENT)
ifneq ($(OUTPUT),)
CFLAGS += -I$(OUTPUT)
endif
LIB_OBJS += $(OUTPUT)tests/sample-parsing.o

ifdef NO_LIBELF
EXTLIBS := $(filter-out -lelf,$(EXTLIBS))
Expand Down
8 changes: 5 additions & 3 deletions tools/perf/builtin-inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,15 +198,15 @@ static int perf_event__inject_buildid(struct perf_tool *tool,

cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;

thread = machine__findnew_thread(machine, event->ip.pid);
thread = machine__findnew_thread(machine, sample->pid, sample->pid);
if (thread == NULL) {
pr_err("problem processing %d event, skipping it.\n",
event->header.type);
goto repipe;
}

thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
event->ip.ip, &al);
sample->ip, &al);

if (al.map != NULL) {
if (!al.map->dso->hit) {
Expand Down Expand Up @@ -301,7 +301,9 @@ static int perf_inject__sched_stat(struct perf_tool *tool,
sample_sw.period = sample->period;
sample_sw.time = sample->time;
perf_event__synthesize_sample(event_sw, evsel->attr.sample_type,
&sample_sw, false);
evsel->attr.sample_regs_user,
evsel->attr.read_format, &sample_sw,
false);
build_id__mark_dso_hit(tool, event_sw, &sample_sw, evsel, machine);
return perf_event__repipe(tool, event_sw, &sample_sw, machine);
}
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/builtin-kmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
struct perf_evsel *evsel,
struct machine *machine)
{
struct thread *thread = machine__findnew_thread(machine, event->ip.pid);
struct thread *thread = machine__findnew_thread(machine, sample->pid,
sample->pid);

if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/builtin-kvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -815,7 +815,7 @@ static int process_sample_event(struct perf_tool *tool,
if (skip_sample(kvm, sample))
return 0;

thread = machine__findnew_thread(machine, sample->tid);
thread = machine__findnew_thread(machine, sample->pid, sample->tid);
if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
event->header.type);
Expand Down
3 changes: 2 additions & 1 deletion tools/perf/builtin-lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
struct perf_evsel *evsel,
struct machine *machine)
{
struct thread *thread = machine__findnew_thread(machine, sample->tid);
struct thread *thread = machine__findnew_thread(machine, sample->pid,
sample->tid);

if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/builtin-mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ dump_raw_samples(struct perf_tool *tool,
symbol_conf.field_sep,
sample->tid,
symbol_conf.field_sep,
event->ip.ip,
sample->ip,
symbol_conf.field_sep,
sample->addr,
symbol_conf.field_sep,
Expand Down
2 changes: 1 addition & 1 deletion tools/perf/builtin-report.c
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ static int process_read_event(struct perf_tool *tool,
static int perf_report__setup_sample_type(struct perf_report *rep)
{
struct perf_session *self = rep->session;
u64 sample_type = perf_evlist__sample_type(self->evlist);
u64 sample_type = perf_evlist__combined_sample_type(self->evlist);

if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
if (sort__has_parent) {
Expand Down
20 changes: 11 additions & 9 deletions tools/perf/builtin-sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -724,8 +724,10 @@ static int replay_fork_event(struct perf_sched *sched,
{
struct thread *child, *parent;

child = machine__findnew_thread(machine, event->fork.tid);
parent = machine__findnew_thread(machine, event->fork.ptid);
child = machine__findnew_thread(machine, event->fork.pid,
event->fork.tid);
parent = machine__findnew_thread(machine, event->fork.ppid,
event->fork.ptid);

if (child == NULL || parent == NULL) {
pr_debug("thread does not exist on fork event: child %p, parent %p\n",
Expand Down Expand Up @@ -934,8 +936,8 @@ static int latency_switch_event(struct perf_sched *sched,
return -1;
}

sched_out = machine__findnew_thread(machine, prev_pid);
sched_in = machine__findnew_thread(machine, next_pid);
sched_out = machine__findnew_thread(machine, 0, prev_pid);
sched_in = machine__findnew_thread(machine, 0, next_pid);

out_events = thread_atoms_search(&sched->atom_root, sched_out, &sched->cmp_pid);
if (!out_events) {
Expand Down Expand Up @@ -978,7 +980,7 @@ static int latency_runtime_event(struct perf_sched *sched,
{
const u32 pid = perf_evsel__intval(evsel, sample, "pid");
const u64 runtime = perf_evsel__intval(evsel, sample, "runtime");
struct thread *thread = machine__findnew_thread(machine, pid);
struct thread *thread = machine__findnew_thread(machine, 0, pid);
struct work_atoms *atoms = thread_atoms_search(&sched->atom_root, thread, &sched->cmp_pid);
u64 timestamp = sample->time;
int cpu = sample->cpu;
Expand Down Expand Up @@ -1016,7 +1018,7 @@ static int latency_wakeup_event(struct perf_sched *sched,
if (!success)
return 0;

wakee = machine__findnew_thread(machine, pid);
wakee = machine__findnew_thread(machine, 0, pid);
atoms = thread_atoms_search(&sched->atom_root, wakee, &sched->cmp_pid);
if (!atoms) {
if (thread_atoms_insert(sched, wakee))
Expand Down Expand Up @@ -1070,7 +1072,7 @@ static int latency_migrate_task_event(struct perf_sched *sched,
if (sched->profile_cpu == -1)
return 0;

migrant = machine__findnew_thread(machine, pid);
migrant = machine__findnew_thread(machine, 0, pid);
atoms = thread_atoms_search(&sched->atom_root, migrant, &sched->cmp_pid);
if (!atoms) {
if (thread_atoms_insert(sched, migrant))
Expand Down Expand Up @@ -1289,8 +1291,8 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
return -1;
}

sched_out = machine__findnew_thread(machine, prev_pid);
sched_in = machine__findnew_thread(machine, next_pid);
sched_out = machine__findnew_thread(machine, 0, prev_pid);
sched_in = machine__findnew_thread(machine, 0, next_pid);

sched->curr_thread[this_cpu] = sched_in;

Expand Down
3 changes: 2 additions & 1 deletion tools/perf/builtin-script.c
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
struct machine *machine)
{
struct addr_location al;
struct thread *thread = machine__findnew_thread(machine, event->ip.tid);
struct thread *thread = machine__findnew_thread(machine, sample->pid,
sample->tid);

if (thread == NULL) {
pr_debug("problem processing %d event, skipping it.\n",
Expand Down
11 changes: 6 additions & 5 deletions tools/perf/builtin-top.c
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
{
struct perf_top *top = container_of(tool, struct perf_top, tool);
struct symbol *parent = NULL;
u64 ip = event->ip.ip;
u64 ip = sample->ip;
struct addr_location al;
int err;

Expand All @@ -699,10 +699,10 @@ static void perf_event__process_sample(struct perf_tool *tool,
if (!seen)
seen = intlist__new(NULL);

if (!intlist__has_entry(seen, event->ip.pid)) {
if (!intlist__has_entry(seen, sample->pid)) {
pr_err("Can't find guest [%d]'s kernel information\n",
event->ip.pid);
intlist__add(seen, event->ip.pid);
sample->pid);
intlist__add(seen, sample->pid);
}
return;
}
Expand Down Expand Up @@ -836,7 +836,8 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
break;
case PERF_RECORD_MISC_GUEST_KERNEL:
++top->guest_kernel_samples;
machine = perf_session__find_machine(session, event->ip.pid);
machine = perf_session__find_machine(session,
sample.pid);
break;
case PERF_RECORD_MISC_GUEST_USER:
++top->guest_us_samples;
Expand Down
Loading

0 comments on commit ea79ca0

Please sign in to comment.