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:

User visible changes:

 - Fix 'perf script' pipe mode segfault, by always initializing ordered_events in
   perf_session__new(). (Arnaldo Carvalho de Melo)

 - Fix ppid for synthesized fork events. (David Ahern)

 - Fix kernel symbol resolution of callchains in S/390 by remembering the
   cpumode. (David Hildenbrand)

Infrastructure changes:

 - Disable libbabeltrace check by default in the build system. (Jiri Olsa)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Ingo Molnar committed Apr 1, 2015
2 parents ccd41c8 + 9870d78 commit aaa9fa3
Show file tree
Hide file tree
Showing 9 changed files with 144 additions and 123 deletions.
2 changes: 1 addition & 1 deletion tools/perf/Makefile.perf
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ include config/utilities.mak
#
# Define NO_ZLIB if you do not want to support compressed kernel modules
#
# Define NO_LIBBABELTRACE if you do not want libbabeltrace support
# Define LIBBABELTRACE if you DO want libbabeltrace support
# for CTF data format.
#
# Define NO_LZMA if you do not want to support compressed (xz) kernel modules
Expand Down
5 changes: 2 additions & 3 deletions tools/perf/config/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ ifndef NO_LIBELF
FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
endif

ifndef NO_LIBBABELTRACE
ifdef LIBBABELTRACE
# for linking with debug library, run like:
# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
ifdef LIBBABELTRACE_DIR
Expand Down Expand Up @@ -598,7 +598,7 @@ else
NO_PERF_READ_VDSOX32 := 1
endif

ifndef NO_LIBBABELTRACE
ifdef LIBBABELTRACE
$(call feature_check,libbabeltrace)
ifeq ($(feature-libbabeltrace), 1)
CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
Expand All @@ -607,7 +607,6 @@ ifndef NO_LIBBABELTRACE
$(call detected,CONFIG_LIBBABELTRACE)
else
msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-dev[el]/libbabeltrace-ctf-dev);
NO_LIBBABELTRACE := 1
endif
endif

Expand Down
147 changes: 90 additions & 57 deletions tools/perf/util/event.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,70 +49,103 @@ static struct perf_sample synth_sample = {
.period = 1,
};

static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
/*
* Assumes that the first 4095 bytes of /proc/pid/stat contains
* the comm, tgid and ppid.
*/
static int perf_event__get_comm_ids(pid_t pid, char *comm, size_t len,
pid_t *tgid, pid_t *ppid)
{
char filename[PATH_MAX];
char bf[BUFSIZ];
FILE *fp;
size_t size = 0;
pid_t tgid = -1;
char bf[4096];
int fd;
size_t size = 0, n;
char *nl, *name, *tgids, *ppids;

*tgid = -1;
*ppid = -1;

snprintf(filename, sizeof(filename), "/proc/%d/status", pid);

fp = fopen(filename, "r");
if (fp == NULL) {
fd = open(filename, O_RDONLY);
if (fd < 0) {
pr_debug("couldn't open %s\n", filename);
return 0;
return -1;
}

while (!comm[0] || (tgid < 0)) {
if (fgets(bf, sizeof(bf), fp) == NULL) {
pr_warning("couldn't get COMM and pgid, malformed %s\n",
filename);
break;
}
n = read(fd, bf, sizeof(bf) - 1);
close(fd);
if (n <= 0) {
pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n",
pid);
return -1;
}
bf[n] = '\0';

if (memcmp(bf, "Name:", 5) == 0) {
char *name = bf + 5;
while (*name && isspace(*name))
++name;
size = strlen(name) - 1;
if (size >= len)
size = len - 1;
memcpy(comm, name, size);
comm[size] = '\0';

} else if (memcmp(bf, "Tgid:", 5) == 0) {
char *tgids = bf + 5;
while (*tgids && isspace(*tgids))
++tgids;
tgid = atoi(tgids);
}
name = strstr(bf, "Name:");
tgids = strstr(bf, "Tgid:");
ppids = strstr(bf, "PPid:");

if (name) {
name += 5; /* strlen("Name:") */

while (*name && isspace(*name))
++name;

nl = strchr(name, '\n');
if (nl)
*nl = '\0';

size = strlen(name);
if (size >= len)
size = len - 1;
memcpy(comm, name, size);
comm[size] = '\0';
} else {
pr_debug("Name: string not found for pid %d\n", pid);
}

fclose(fp);
if (tgids) {
tgids += 5; /* strlen("Tgid:") */
*tgid = atoi(tgids);
} else {
pr_debug("Tgid: string not found for pid %d\n", pid);
}

return tgid;
if (ppids) {
ppids += 5; /* strlen("PPid:") */
*ppid = atoi(ppids);
} else {
pr_debug("PPid: string not found for pid %d\n", pid);
}

return 0;
}

static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
struct machine *machine)
static int perf_event__prepare_comm(union perf_event *event, pid_t pid,
struct machine *machine,
pid_t *tgid, pid_t *ppid)
{
size_t size;
pid_t tgid;

*ppid = -1;

memset(&event->comm, 0, sizeof(event->comm));

if (machine__is_host(machine))
tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
sizeof(event->comm.comm));
else
tgid = machine->pid;
if (machine__is_host(machine)) {
if (perf_event__get_comm_ids(pid, event->comm.comm,
sizeof(event->comm.comm),
tgid, ppid) != 0) {
return -1;
}
} else {
*tgid = machine->pid;
}

if (tgid < 0)
goto out;
if (*tgid < 0)
return -1;

event->comm.pid = tgid;
event->comm.pid = *tgid;
event->comm.header.type = PERF_RECORD_COMM;

size = strlen(event->comm.comm) + 1;
Expand All @@ -122,36 +155,36 @@ static pid_t perf_event__prepare_comm(union perf_event *event, pid_t pid,
(sizeof(event->comm.comm) - size) +
machine->id_hdr_size);
event->comm.tid = pid;
out:
return tgid;

return 0;
}

static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
union perf_event *event, pid_t pid,
perf_event__handler_t process,
struct machine *machine)
{
pid_t tgid = perf_event__prepare_comm(event, pid, machine);
pid_t tgid, ppid;

if (tgid == -1)
goto out;
if (perf_event__prepare_comm(event, pid, machine, &tgid, &ppid) != 0)
return -1;

if (process(tool, event, &synth_sample, machine) != 0)
return -1;

out:
return tgid;
}

static int perf_event__synthesize_fork(struct perf_tool *tool,
union perf_event *event, pid_t pid,
pid_t tgid, perf_event__handler_t process,
union perf_event *event,
pid_t pid, pid_t tgid, pid_t ppid,
perf_event__handler_t process,
struct machine *machine)
{
memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);

event->fork.ppid = tgid;
event->fork.ptid = tgid;
event->fork.ppid = ppid;
event->fork.ptid = ppid;
event->fork.pid = tgid;
event->fork.tid = pid;
event->fork.header.type = PERF_RECORD_FORK;
Expand Down Expand Up @@ -343,7 +376,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
char filename[PATH_MAX];
DIR *tasks;
struct dirent dirent, *next;
pid_t tgid;
pid_t tgid, ppid;

/* special case: only send one comm event using passed in pid */
if (!full) {
Expand Down Expand Up @@ -378,12 +411,12 @@ static int __event__synthesize_thread(union perf_event *comm_event,
if (*end)
continue;

tgid = perf_event__prepare_comm(comm_event, _pid, machine);
if (tgid == -1)
if (perf_event__prepare_comm(comm_event, _pid, machine,
&tgid, &ppid) != 0)
return -1;

if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
process, machine) < 0)
ppid, process, machine) < 0)
return -1;
/*
* Send the prepared comm event
Expand Down
1 change: 0 additions & 1 deletion tools/perf/util/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,6 @@ struct events_stats {
u32 nr_invalid_chains;
u32 nr_unknown_id;
u32 nr_unprocessable_samples;
u32 nr_unordered_events;
};

struct attr_event {
Expand Down
28 changes: 14 additions & 14 deletions tools/perf/util/machine.c
Original file line number Diff line number Diff line change
Expand Up @@ -1408,29 +1408,27 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
static int add_callchain_ip(struct thread *thread,
struct symbol **parent,
struct addr_location *root_al,
bool branch_history,
u8 *cpumode,
u64 ip)
{
struct addr_location al;

al.filtered = 0;
al.sym = NULL;
if (branch_history)
if (!cpumode) {
thread__find_cpumode_addr_location(thread, MAP__FUNCTION,
ip, &al);
else {
u8 cpumode = PERF_RECORD_MISC_USER;

} else {
if (ip >= PERF_CONTEXT_MAX) {
switch (ip) {
case PERF_CONTEXT_HV:
cpumode = PERF_RECORD_MISC_HYPERVISOR;
*cpumode = PERF_RECORD_MISC_HYPERVISOR;
break;
case PERF_CONTEXT_KERNEL:
cpumode = PERF_RECORD_MISC_KERNEL;
*cpumode = PERF_RECORD_MISC_KERNEL;
break;
case PERF_CONTEXT_USER:
cpumode = PERF_RECORD_MISC_USER;
*cpumode = PERF_RECORD_MISC_USER;
break;
default:
pr_debug("invalid callchain context: "
Expand All @@ -1444,8 +1442,8 @@ static int add_callchain_ip(struct thread *thread,
}
return 0;
}
thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
ip, &al);
thread__find_addr_location(thread, *cpumode, MAP__FUNCTION,
ip, &al);
}

if (al.sym != NULL) {
Expand Down Expand Up @@ -1538,6 +1536,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
{
struct ip_callchain *chain = sample->callchain;
int chain_nr = min(max_stack, (int)chain->nr);
u8 cpumode = PERF_RECORD_MISC_USER;
int i, j, err;
u64 ip;

Expand Down Expand Up @@ -1584,7 +1583,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
ip = lbr_stack->entries[0].to;
}

err = add_callchain_ip(thread, parent, root_al, false, ip);
err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);
if (err)
return (err < 0) ? err : 0;
}
Expand All @@ -1604,6 +1603,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
struct branch_stack *branch = sample->branch_stack;
struct ip_callchain *chain = sample->callchain;
int chain_nr = min(max_stack, (int)chain->nr);
u8 cpumode = PERF_RECORD_MISC_USER;
int i, j, err;
int skip_idx = -1;
int first_call = 0;
Expand Down Expand Up @@ -1669,10 +1669,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,

for (i = 0; i < nr; i++) {
err = add_callchain_ip(thread, parent, root_al,
true, be[i].to);
NULL, be[i].to);
if (!err)
err = add_callchain_ip(thread, parent, root_al,
true, be[i].from);
NULL, be[i].from);
if (err == -EINVAL)
break;
if (err)
Expand Down Expand Up @@ -1701,7 +1701,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
#endif
ip = chain->ips[j];

err = add_callchain_ip(thread, parent, root_al, false, ip);
err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);

if (err)
return (err < 0) ? err : 0;
Expand Down
Loading

0 comments on commit aaa9fa3

Please sign in to comment.