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

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
Loading
Loading
Loading
Loading
+38 −33
Original line number Diff line number Diff line
@@ -203,46 +203,48 @@ static void sig_atexit(void)
	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;
	char filename[PATH_MAX];
	char bf[BUFSIZ];
	int fd;
	size_t size;
	char *field, *sep;
	FILE *fp;
	size_t size = 0;
	DIR *tasks;
	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);
	if (fd < 0) {
	fp = fopen(filename, "r");
	if (fd == NULL) {
		/*
		 * We raced with a task exiting - just return:
		 */
		if (verbose)
			fprintf(stderr, "couldn't open %s\n", filename);
		return;
	}
	if (read(fd, bf, sizeof(bf)) < 0) {
		fprintf(stderr, "couldn't read %s\n", filename);
		exit(EXIT_FAILURE);
		return 0;
	}
	close(fd);

	/* 9027 (cat) R 6747 9027 6747 34816 9027 ... */
	memset(&comm_ev, 0, sizeof(comm_ev));
	field = strchr(bf, '(');
	if (field == NULL)
		goto out_failure;
	sep = strchr(++field, ')');
	if (sep == NULL)
	while (!comm_ev.comm[0] || !comm_ev.pid) {
		if (fgets(bf, sizeof(bf), fp) == NULL)
			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;
	size = ALIGN(size, sizeof(u64));
	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)
		comm_ev.tid = pid;

		write_output(&comm_ev, comm_ev.header.size);
		return;
		goto out_fclose;
	}

	snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
@@ -268,7 +270,10 @@ static void pid_synthesize_comm_event(pid_t pid, int full)
		write_output(&comm_ev, comm_ev.header.size);
	}
	closedir(tasks);
	return;

out_fclose:
	fclose(fp);
	return tgid;

out_failure:
	fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
@@ -276,7 +281,7 @@ out_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];
	FILE *fp;
@@ -328,7 +333,7 @@ static void pid_synthesize_mmap_samples(pid_t pid)
			mmap_ev.len -= mmap_ev.start;
			mmap_ev.header.size = (sizeof(mmap_ev) -
					       (sizeof(mmap_ev.filename) - size));
			mmap_ev.pid = pid;
			mmap_ev.pid = tgid;
			mmap_ev.tid = pid;

			write_output(&mmap_ev, mmap_ev.header.size);
@@ -347,14 +352,14 @@ static void synthesize_all(void)

	while (!readdir_r(proc, &dirent, &next) && next) {
		char *end;
		pid_t pid;
		pid_t pid, tgid;

		pid = strtol(dirent.d_name, &end, 10);
		if (*end) /* only interested in proper numerical dirents */
			continue;

		pid_synthesize_comm_event(pid, 1);
		pid_synthesize_mmap_samples(pid);
		tgid = pid_synthesize_comm_event(pid, 1);
		pid_synthesize_mmap_samples(pid, tgid);
	}

	closedir(proc);
@@ -567,8 +572,8 @@ static int __cmd_record(int argc, const char **argv)
		perf_header__write(header, output);

	if (!system_wide) {
		pid_synthesize_comm_event(pid, 0);
		pid_synthesize_mmap_samples(pid);
		pid_t tgid = pid_synthesize_comm_event(pid, 0);
		pid_synthesize_mmap_samples(pid, tgid);
	} else
		synthesize_all();