Commit 2a8083f0 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Ingo Molnar

perf record: Fix .tid and .pid fill-in when synthesizing events

Noticed when trying to record events for a firefox thread. We
were synthesizing both .tid and .pid with the pid passed via
--pid.

Fix it by reading /proc/PID/status and getting the tgid
to use in .pid, .tid gets the specified "pid".
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <20090811192200.GF18061@ghostprotocols.net>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent f64ccccb
...@@ -203,46 +203,48 @@ static void sig_atexit(void) ...@@ -203,46 +203,48 @@ static void sig_atexit(void)
kill(getpid(), signr); kill(getpid(), signr);
} }
static void pid_synthesize_comm_event(pid_t pid, int full) static pid_t pid_synthesize_comm_event(pid_t pid, int full)
{ {
struct comm_event comm_ev; struct comm_event comm_ev;
char filename[PATH_MAX]; char filename[PATH_MAX];
char bf[BUFSIZ]; char bf[BUFSIZ];
int fd; FILE *fp;
size_t size; size_t size = 0;
char *field, *sep;
DIR *tasks; DIR *tasks;
struct dirent dirent, *next; struct dirent dirent, *next;
pid_t tgid = 0;
snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); snprintf(filename, sizeof(filename), "/proc/%d/status", pid);
fd = open(filename, O_RDONLY); fp = fopen(filename, "r");
if (fd < 0) { if (fd == NULL) {
/* /*
* We raced with a task exiting - just return: * We raced with a task exiting - just return:
*/ */
if (verbose) if (verbose)
fprintf(stderr, "couldn't open %s\n", filename); fprintf(stderr, "couldn't open %s\n", filename);
return; return 0;
}
if (read(fd, bf, sizeof(bf)) < 0) {
fprintf(stderr, "couldn't read %s\n", filename);
exit(EXIT_FAILURE);
} }
close(fd);
/* 9027 (cat) R 6747 9027 6747 34816 9027 ... */
memset(&comm_ev, 0, sizeof(comm_ev)); memset(&comm_ev, 0, sizeof(comm_ev));
field = strchr(bf, '('); while (!comm_ev.comm[0] || !comm_ev.pid) {
if (field == NULL) if (fgets(bf, sizeof(bf), fp) == NULL)
goto out_failure;
sep = strchr(++field, ')');
if (sep == NULL)
goto out_failure; goto out_failure;
size = sep - field;
memcpy(comm_ev.comm, field, size++);
comm_ev.pid = pid; if (memcmp(bf, "Name:", 5) == 0) {
char *name = bf + 5;
while (*name && isspace(*name))
++name;
size = strlen(name) - 1;
memcpy(comm_ev.comm, name, size++);
} else if (memcmp(bf, "Tgid:", 5) == 0) {
char *tgids = bf + 5;
while (*tgids && isspace(*tgids))
++tgids;
tgid = comm_ev.pid = atoi(tgids);
}
}
comm_ev.header.type = PERF_EVENT_COMM; comm_ev.header.type = PERF_EVENT_COMM;
size = ALIGN(size, sizeof(u64)); size = ALIGN(size, sizeof(u64));
comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size); comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
...@@ -251,7 +253,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full) ...@@ -251,7 +253,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
comm_ev.tid = pid; comm_ev.tid = pid;
write_output(&comm_ev, comm_ev.header.size); write_output(&comm_ev, comm_ev.header.size);
return; goto out_fclose;
} }
snprintf(filename, sizeof(filename), "/proc/%d/task", pid); snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
...@@ -268,7 +270,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full) ...@@ -268,7 +270,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
write_output(&comm_ev, comm_ev.header.size); write_output(&comm_ev, comm_ev.header.size);
} }
closedir(tasks); closedir(tasks);
return;
out_fclose:
fclose(fp);
return tgid;
out_failure: out_failure:
fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n", fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
...@@ -276,7 +281,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full) ...@@ -276,7 +281,7 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
static void pid_synthesize_mmap_samples(pid_t pid) static void pid_synthesize_mmap_samples(pid_t pid, pid_t tgid)
{ {
char filename[PATH_MAX]; char filename[PATH_MAX];
FILE *fp; FILE *fp;
...@@ -328,7 +333,7 @@ static void pid_synthesize_mmap_samples(pid_t pid) ...@@ -328,7 +333,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
mmap_ev.len -= mmap_ev.start; mmap_ev.len -= mmap_ev.start;
mmap_ev.header.size = (sizeof(mmap_ev) - mmap_ev.header.size = (sizeof(mmap_ev) -
(sizeof(mmap_ev.filename) - size)); (sizeof(mmap_ev.filename) - size));
mmap_ev.pid = pid; mmap_ev.pid = tgid;
mmap_ev.tid = pid; mmap_ev.tid = pid;
write_output(&mmap_ev, mmap_ev.header.size); write_output(&mmap_ev, mmap_ev.header.size);
...@@ -347,14 +352,14 @@ static void synthesize_all(void) ...@@ -347,14 +352,14 @@ static void synthesize_all(void)
while (!readdir_r(proc, &dirent, &next) && next) { while (!readdir_r(proc, &dirent, &next) && next) {
char *end; char *end;
pid_t pid; pid_t pid, tgid;
pid = strtol(dirent.d_name, &end, 10); pid = strtol(dirent.d_name, &end, 10);
if (*end) /* only interested in proper numerical dirents */ if (*end) /* only interested in proper numerical dirents */
continue; continue;
pid_synthesize_comm_event(pid, 1); tgid = pid_synthesize_comm_event(pid, 1);
pid_synthesize_mmap_samples(pid); pid_synthesize_mmap_samples(pid, tgid);
} }
closedir(proc); closedir(proc);
...@@ -567,8 +572,8 @@ static int __cmd_record(int argc, const char **argv) ...@@ -567,8 +572,8 @@ static int __cmd_record(int argc, const char **argv)
perf_header__write(header, output); perf_header__write(header, output);
if (!system_wide) { if (!system_wide) {
pid_synthesize_comm_event(pid, 0); pid_t tgid = pid_synthesize_comm_event(pid, 0);
pid_synthesize_mmap_samples(pid); pid_synthesize_mmap_samples(pid, tgid);
} else } else
synthesize_all(); synthesize_all();
......
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