Commit f70e87d7 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar

perf_counter: tools: Expand the COMM,MMAP event synthesizer

Include code to pre-construct mappings based on /proc,
on system wide recording.

Fix the existing code to properly fill out ->pid and ->tid.

The PID should be the Thread Group ID (PIDTYPE_PID of task->group_leader)
The TID should be the Thread ID (PIDTYPE_PID of task)

Furthermore, change the default sorting of report to comm,dso for a
better quick overview.
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 709e50cf
...@@ -162,7 +162,7 @@ struct comm_event { ...@@ -162,7 +162,7 @@ struct comm_event {
char comm[16]; char comm[16];
}; };
static pid_t pid_synthesize_comm_event(pid_t pid) static void 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];
...@@ -170,6 +170,8 @@ static pid_t pid_synthesize_comm_event(pid_t pid) ...@@ -170,6 +170,8 @@ static pid_t pid_synthesize_comm_event(pid_t pid)
int fd, ret; int fd, ret;
size_t size; size_t size;
char *field, *sep; char *field, *sep;
DIR *tasks;
struct dirent dirent, *next;
snprintf(filename, sizeof(filename), "/proc/%d/stat", pid); snprintf(filename, sizeof(filename), "/proc/%d/stat", pid);
...@@ -194,29 +196,50 @@ static pid_t pid_synthesize_comm_event(pid_t pid) ...@@ -194,29 +196,50 @@ static pid_t pid_synthesize_comm_event(pid_t pid)
goto out_failure; goto out_failure;
size = sep - field; size = sep - field;
memcpy(comm_ev.comm, field, size++); memcpy(comm_ev.comm, field, size++);
field = strchr(sep + 4, ' ');
if (field == NULL) comm_ev.pid = pid;
goto out_failure;
comm_ev.pid = atoi(++field);
comm_ev.header.type = PERF_EVENT_COMM; comm_ev.header.type = PERF_EVENT_COMM;
comm_ev.tid = pid;
size = ALIGN(size, sizeof(uint64_t)); size = ALIGN(size, sizeof(uint64_t));
comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size); comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
ret = write(output, &comm_ev, comm_ev.header.size); if (!full) {
if (ret < 0) { comm_ev.tid = pid;
perror("failed to write");
exit(-1); ret = write(output, &comm_ev, comm_ev.header.size);
if (ret < 0) {
perror("failed to write");
exit(-1);
}
return;
}
snprintf(filename, sizeof(filename), "/proc/%d/task", pid);
tasks = opendir(filename);
while (!readdir_r(tasks, &dirent, &next) && next) {
char *end;
pid = strtol(dirent.d_name, &end, 10);
if (*end)
continue;
comm_ev.tid = pid;
ret = write(output, &comm_ev, comm_ev.header.size);
if (ret < 0) {
perror("failed to write");
exit(-1);
}
} }
return comm_ev.pid; closedir(tasks);
return;
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",
filename); filename);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
return -1;
} }
static void pid_synthesize_mmap_events(pid_t pid, pid_t pgid) static void pid_synthesize_mmap_events(pid_t pid)
{ {
char filename[PATH_MAX]; char filename[PATH_MAX];
FILE *fp; FILE *fp;
...@@ -261,7 +284,7 @@ static void pid_synthesize_mmap_events(pid_t pid, pid_t pgid) ...@@ -261,7 +284,7 @@ static void pid_synthesize_mmap_events(pid_t pid, pid_t pgid)
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 = pgid; mmap_ev.pid = pid;
mmap_ev.tid = pid; mmap_ev.tid = pid;
if (write(output, &mmap_ev, mmap_ev.header.size) < 0) { if (write(output, &mmap_ev, mmap_ev.header.size) < 0) {
...@@ -274,6 +297,28 @@ static void pid_synthesize_mmap_events(pid_t pid, pid_t pgid) ...@@ -274,6 +297,28 @@ static void pid_synthesize_mmap_events(pid_t pid, pid_t pgid)
fclose(fp); fclose(fp);
} }
static void synthesize_events(void)
{
DIR *proc;
struct dirent dirent, *next;
proc = opendir("/proc");
while (!readdir_r(proc, &dirent, &next) && next) {
char *end;
pid_t pid;
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_events(pid);
}
closedir(proc);
}
static void open_counters(int cpu, pid_t pid) static void open_counters(int cpu, pid_t pid)
{ {
struct perf_counter_hw_event hw_event; struct perf_counter_hw_event hw_event;
...@@ -281,8 +326,8 @@ static void open_counters(int cpu, pid_t pid) ...@@ -281,8 +326,8 @@ static void open_counters(int cpu, pid_t pid)
int track = 1; int track = 1;
if (pid > 0) { if (pid > 0) {
pid_t pgid = pid_synthesize_comm_event(pid); pid_synthesize_comm_event(pid, 0);
pid_synthesize_mmap_events(pid, pgid); pid_synthesize_mmap_events(pid);
} }
group_fd = -1; group_fd = -1;
...@@ -348,7 +393,7 @@ static int __cmd_record(int argc, const char **argv) ...@@ -348,7 +393,7 @@ static int __cmd_record(int argc, const char **argv)
assert(nr_cpus <= MAX_NR_CPUS); assert(nr_cpus <= MAX_NR_CPUS);
assert(nr_cpus >= 0); assert(nr_cpus >= 0);
output = open(output_name, O_CREAT|O_EXCL|O_RDWR, S_IRWXU); output = open(output_name, O_CREAT|O_EXCL|O_TRUNC|O_RDWR, S_IRUSR|S_IWUSR);
if (output < 0) { if (output < 0) {
perror("failed to create output file"); perror("failed to create output file");
exit(-1); exit(-1);
...@@ -385,9 +430,8 @@ static int __cmd_record(int argc, const char **argv) ...@@ -385,9 +430,8 @@ static int __cmd_record(int argc, const char **argv)
} }
} }
/* if (system_wide)
* TODO: store the current /proc/$/maps information somewhere synthesize_events();
*/
while (!done) { while (!done) {
int hits = events; int hits = events;
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
static char const *input_name = "perf.data"; static char const *input_name = "perf.data";
static char *vmlinux = NULL; static char *vmlinux = NULL;
static char *sort_order = "pid,symbol"; static char *sort_order = "comm,dso";
static int input; static int input;
static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV; static int show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;
......
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