perf tools: Improve thread comm resolution in perf sched
[linux-3.10.git] / tools / perf / util / thread.c
index 9d0945c..8bd5ca2 100644 (file)
@@ -6,16 +6,19 @@
 #include "util.h"
 #include "debug.h"
 
-static struct thread *thread__new(pid_t pid)
+static struct thread *thread__new(pid_t pid, int set_comm)
 {
        struct thread *self = calloc(1, sizeof(*self));
 
        if (self != NULL) {
                self->pid = pid;
-               self->comm = malloc(32);
-               if (self->comm)
-                       snprintf(self->comm, 32, ":%d", self->pid);
+               if (set_comm) {
+                       self->comm = malloc(32);
+                       if (self->comm)
+                               snprintf(self->comm, 32, ":%d", self->pid);
+               }
                self->maps = RB_ROOT;
+               INIT_LIST_HEAD(&self->removed_maps);
        }
 
        return self;
@@ -32,18 +35,27 @@ int thread__set_comm(struct thread *self, const char *comm)
 static size_t thread__fprintf(struct thread *self, FILE *fp)
 {
        struct rb_node *nd;
-       size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm);
+       struct map *pos;
+       size_t ret = fprintf(fp, "Thread %d %s\nCurrent maps:\n",
+                            self->pid, self->comm);
 
        for (nd = rb_first(&self->maps); nd; nd = rb_next(nd)) {
-               struct map *pos = rb_entry(nd, struct map, rb_node);
+               pos = rb_entry(nd, struct map, rb_node);
                ret += map__fprintf(pos, fp);
        }
 
+       ret = fprintf(fp, "Removed maps:\n");
+
+       list_for_each_entry(pos, &self->removed_maps, node)
+               ret += map__fprintf(pos, fp);
+
        return ret;
 }
 
-struct thread *
-threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
+static struct thread *
+__threads__findnew(pid_t pid, struct rb_root *threads,
+                  struct thread **last_match,
+                  int set_comm)
 {
        struct rb_node **p = &threads->rb_node;
        struct rb_node *parent = NULL;
@@ -72,7 +84,8 @@ threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
                        p = &(*p)->rb_right;
        }
 
-       th = thread__new(pid);
+       th = thread__new(pid, set_comm);
+
        if (th != NULL) {
                rb_link_node(&th->rb_node, parent, p);
                rb_insert_color(&th->rb_node, threads);
@@ -83,6 +96,19 @@ threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
 }
 
 struct thread *
+threads__findnew(pid_t pid, struct rb_root *threads, struct thread **last_match)
+{
+       return __threads__findnew(pid, threads, last_match, 1);
+}
+
+struct thread *
+threads__findnew_nocomm(pid_t pid, struct rb_root *threads,
+                       struct thread **last_match)
+{
+       return __threads__findnew(pid, threads, last_match, 0);
+}
+
+struct thread *
 register_idle_thread(struct rb_root *threads, struct thread **last_match)
 {
        struct thread *thread = threads__findnew(0, threads, last_match);
@@ -112,21 +138,13 @@ static void thread__remove_overlappings(struct thread *self, struct map *map)
                        map__fprintf(pos, stdout);
                }
 
-               if (map->start <= pos->start && map->end > pos->start)
-                       pos->start = map->end;
-
-               if (map->end >= pos->end && map->start < pos->end)
-                       pos->end = map->start;
-
-               if (verbose >= 2) {
-                       printf("after collision:\n");
-                       map__fprintf(pos, stdout);
-               }
-
-               if (pos->start >= pos->end) {
-                       rb_erase(&pos->rb_node, &self->maps);
-                       free(pos);
-               }
+               rb_erase(&pos->rb_node, &self->maps);
+               /*
+                * We may have references to this map, for instance in some
+                * hist_entry instances, so just move them to a separate
+                * list.
+                */
+               list_add_tail(&pos->node, &self->removed_maps);
        }
 }