Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5faf726 authored by David Ahern's avatar David Ahern Committed by Arnaldo Carvalho de Melo
Browse files

perf tools: Look up thread names for system wide profiling

This handles multithreaded processes with named threads when doing
system wide profiling: the comm for each thread is looked up allowing
them to be different from the thread group leader.

v2:
- fixed sizeof arg to perf_event__get_comm_tgid

Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1324578603-12762-3-git-send-email-dsahern@gmail.com


Signed-off-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent defd8d38
Loading
Loading
Loading
Loading
+53 −22
Original line number Diff line number Diff line
@@ -43,37 +43,27 @@ static struct perf_sample synth_sample = {
	.period	   = 1,
};

static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
					 union perf_event *event, pid_t pid,
					 int full, perf_event__handler_t process,
					 struct machine *machine)
static pid_t perf_event__get_comm_tgid(pid_t pid, char *comm, size_t len)
{
	char filename[PATH_MAX];
	char bf[BUFSIZ];
	FILE *fp;
	size_t size = 0;
	DIR *tasks;
	struct dirent dirent, *next;
	pid_t tgid = 0;
	pid_t tgid = -1;

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

	fp = fopen(filename, "r");
	if (fp == NULL) {
out_race:
		/*
		 * We raced with a task exiting - just return:
		 */
		pr_debug("couldn't open %s\n", filename);
		return 0;
	}

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

	while (!event->comm.comm[0] || !event->comm.pid) {
	while (!comm[0] || (tgid < 0)) {
		if (fgets(bf, sizeof(bf), fp) == NULL) {
			pr_warning("couldn't get COMM and pgid, malformed %s\n", filename);
			goto out;
			pr_warning("couldn't get COMM and pgid, malformed %s\n",
				   filename);
			break;
		}

		if (memcmp(bf, "Name:", 5) == 0) {
@@ -81,16 +71,46 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
			while (*name && isspace(*name))
				++name;
			size = strlen(name) - 1;
			memcpy(event->comm.comm, name, size++);
			if (size >= len)
				size = len - 1;
			memcpy(comm, name, size);

		} else if (memcmp(bf, "Tgid:", 5) == 0) {
			char *tgids = bf + 5;
			while (*tgids && isspace(*tgids))
				++tgids;
			tgid = event->comm.pid = atoi(tgids);
			tgid = atoi(tgids);
		}
	}

	fclose(fp);

	return tgid;
}

static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
					 union perf_event *event, pid_t pid,
					 int full,
					 perf_event__handler_t process,
					 struct machine *machine)
{
	char filename[PATH_MAX];
	size_t size;
	DIR *tasks;
	struct dirent dirent, *next;
	pid_t tgid;

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

	tgid = perf_event__get_comm_tgid(pid, event->comm.comm,
					 sizeof(event->comm.comm));
	if (tgid < 0)
		goto out;

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

	size = strlen(event->comm.comm) + 1;
	size = ALIGN(size, sizeof(u64));
	memset(event->comm.comm + size, 0, machine->id_hdr_size);
	event->comm.header.size = (sizeof(event->comm) -
@@ -106,8 +126,10 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
	snprintf(filename, sizeof(filename), "/proc/%d/task", pid);

	tasks = opendir(filename);
	if (tasks == NULL)
		goto out_race;
	if (tasks == NULL) {
		pr_debug("couldn't open %s\n", filename);
		return 0;
	}

	while (!readdir_r(tasks, &dirent, &next) && next) {
		char *end;
@@ -115,6 +137,17 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
		if (*end)
			continue;

		/* already have tgid; jut want to update the comm */
		(void) perf_event__get_comm_tgid(pid, event->comm.comm,
					 sizeof(event->comm.comm));

		size = strlen(event->comm.comm) + 1;
		size = ALIGN(size, sizeof(u64));
		memset(event->comm.comm + size, 0, machine->id_hdr_size);
		event->comm.header.size = (sizeof(event->comm) -
					  (sizeof(event->comm.comm) - size) +
					  machine->id_hdr_size);

		event->comm.tid = pid;

		process(tool, event, &synth_sample, machine);
@@ -122,8 +155,6 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,

	closedir(tasks);
out:
	fclose(fp);

	return tgid;
}