perf_counter: tools: Expand the COMM,MMAP event synthesizer
authorPeter Zijlstra <a.p.zijlstra@chello.nl>
Tue, 2 Jun 2009 12:13:24 +0000 (14:13 +0200)
committerIngo Molnar <mingo@elte.hu>
Tue, 2 Jun 2009 14:16:26 +0000 (16:16 +0200)
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: Peter 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: Ingo Molnar <mingo@elte.hu>
Documentation/perf_counter/builtin-record.c
Documentation/perf_counter/builtin-report.c

index 9c151ded22fabc74a5209660786628288d8bc6cb..810fc275ca65c95d69d2894249ad68f516759734 100644 (file)
@@ -162,7 +162,7 @@ struct comm_event {
        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;
        char filename[PATH_MAX];
@@ -170,6 +170,8 @@ static pid_t pid_synthesize_comm_event(pid_t pid)
        int fd, ret;
        size_t size;
        char *field, *sep;
+       DIR *tasks;
+       struct dirent dirent, *next;
 
        snprintf(filename, sizeof(filename), "/proc/%d/stat", pid);
 
@@ -194,29 +196,50 @@ static pid_t pid_synthesize_comm_event(pid_t pid)
                goto out_failure;
        size = sep - field;
        memcpy(comm_ev.comm, field, size++);
-       field = strchr(sep + 4, ' ');
-       if (field == NULL)
-               goto out_failure;
-       comm_ev.pid = atoi(++field);
+
+       comm_ev.pid = pid;
        comm_ev.header.type = PERF_EVENT_COMM;
-       comm_ev.tid = pid;
        size = ALIGN(size, sizeof(uint64_t));
        comm_ev.header.size = sizeof(comm_ev) - (sizeof(comm_ev.comm) - size);
 
-       ret = write(output, &comm_ev, comm_ev.header.size);
-       if (ret < 0) {
-               perror("failed to write");
-               exit(-1);
+       if (!full) {
+               comm_ev.tid = pid;
+
+               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:
        fprintf(stderr, "couldn't get COMM and pgid, malformed %s\n",
                filename);
        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];
        FILE *fp;
@@ -261,7 +284,7 @@ static void pid_synthesize_mmap_events(pid_t pid, pid_t pgid)
                        mmap_ev.len -= mmap_ev.start;
                        mmap_ev.header.size = (sizeof(mmap_ev) -
                                               (sizeof(mmap_ev.filename) - size));
-                       mmap_ev.pid = pgid;
+                       mmap_ev.pid = pid;
                        mmap_ev.tid = pid;
 
                        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)
        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)
 {
        struct perf_counter_hw_event hw_event;
@@ -281,8 +326,8 @@ static void open_counters(int cpu, pid_t pid)
        int track = 1;
 
        if (pid > 0) {
-               pid_t pgid = pid_synthesize_comm_event(pid);
-               pid_synthesize_mmap_events(pid, pgid);
+               pid_synthesize_comm_event(pid, 0);
+               pid_synthesize_mmap_events(pid);
        }
 
        group_fd = -1;
@@ -348,7 +393,7 @@ static int __cmd_record(int argc, const char **argv)
        assert(nr_cpus <= MAX_NR_CPUS);
        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) {
                perror("failed to create output file");
                exit(-1);
@@ -385,9 +430,8 @@ static int __cmd_record(int argc, const char **argv)
                }
        }
 
-       /*
-        * TODO: store the current /proc/$/maps information somewhere
-        */
+       if (system_wide)
+               synthesize_events();
 
        while (!done) {
                int hits = events;
index 20a4e519dfd175c9f72fd2d8a73ee7b5892a7771..0558c1e1aa5b21e9aeace1b872fd7e322b8bc1de 100644 (file)
@@ -18,7 +18,7 @@
 
 static char            const *input_name = "perf.data";
 static char            *vmlinux = NULL;
-static char            *sort_order = "pid,symbol";
+static char            *sort_order = "comm,dso";
 static int             input;
 static int             show_mask = SHOW_KERNEL | SHOW_USER | SHOW_HV;