From ca6c41c59b964d362823e80442e9e32c31106b29 Mon Sep 17 00:00:00 2001 From: David Ahern Date: Mon, 30 Mar 2015 14:35:58 -0600 Subject: perf tools: Fix ppid for synthesized fork events 363b785f38 added synthesized fork events and set a thread's parent id to itself. Since we are already processing /proc//status the ppid can be determined properly. Make it so. Signed-off-by: David Ahern Acked-by: Don Zickus Acked-by: Jiri Olsa Cc: Joe Mario Link: http://lkml.kernel.org/r/1427747758-18510-2-git-send-email-dsahern@gmail.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/event.c | 83 +++++++++++++++++++++++++++++-------------------- 1 file changed, 50 insertions(+), 33 deletions(-) (limited to 'tools') diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 023dd3548a94..5516236df6ab 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c @@ -51,29 +51,32 @@ static struct perf_sample synth_sample = { /* * Assumes that the first 4095 bytes of /proc/pid/stat contains - * the comm and tgid. + * the comm, tgid and ppid. */ -static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) +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[4096]; int fd; size_t size = 0, n; - pid_t tgid = -1; - char *nl, *name, *tgids; + char *nl, *name, *tgids, *ppids; + + *tgid = -1; + *ppid = -1; snprintf(filename, sizeof(filename), "/proc/%d/status", pid); fd = open(filename, O_RDONLY); if (fd < 0) { pr_debug("couldn't open %s\n", filename); - return 0; + return -1; } n = read(fd, bf, sizeof(bf) - 1); close(fd); if (n <= 0) { - pr_warning("Couldn't get COMM and tgid for pid %d\n", + pr_warning("Couldn't get COMM, tigd and ppid for pid %d\n", pid); return -1; } @@ -81,6 +84,7 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) name = strstr(bf, "Name:"); tgids = strstr(bf, "Tgid:"); + ppids = strstr(bf, "PPid:"); if (name) { name += 5; /* strlen("Name:") */ @@ -103,32 +107,45 @@ static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len) if (tgids) { tgids += 5; /* strlen("Tgid:") */ - tgid = atoi(tgids); + *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; @@ -138,8 +155,8 @@ 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, @@ -147,27 +164,27 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, 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; @@ -359,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) { @@ -394,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 -- cgit v1.2.3