perf tools: Don't trow away old map slices not overlapped by new maps
Arnaldo Carvalho de Melo [Fri, 5 Mar 2010 14:54:02 +0000 (11:54 -0300)]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1267800842-22324-1-git-send-email-acme@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

tools/perf/util/thread.c

index 21b9216..9024fa1 100644 (file)
@@ -183,8 +183,8 @@ struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
        return th;
 }
 
-static void map_groups__remove_overlappings(struct map_groups *self,
-                                           struct map *map)
+static int map_groups__fixup_overlappings(struct map_groups *self,
+                                         struct map *map)
 {
        struct rb_root *root = &self->maps[map->type];
        struct rb_node *next = rb_first(root);
@@ -209,7 +209,36 @@ static void map_groups__remove_overlappings(struct map_groups *self,
                 * list.
                 */
                list_add_tail(&pos->node, &self->removed_maps[map->type]);
+               /*
+                * Now check if we need to create new maps for areas not
+                * overlapped by the new map:
+                */
+               if (map->start > pos->start) {
+                       struct map *before = map__clone(pos);
+
+                       if (before == NULL)
+                               return -ENOMEM;
+
+                       before->end = map->start - 1;
+                       map_groups__insert(self, before);
+                       if (verbose >= 2)
+                               map__fprintf(before, stderr);
+               }
+
+               if (map->end < pos->end) {
+                       struct map *after = map__clone(pos);
+
+                       if (after == NULL)
+                               return -ENOMEM;
+
+                       after->start = map->end + 1;
+                       map_groups__insert(self, after);
+                       if (verbose >= 2)
+                               map__fprintf(after, stderr);
+               }
        }
+
+       return 0;
 }
 
 void maps__insert(struct rb_root *maps, struct map *map)
@@ -254,7 +283,7 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
 
 void thread__insert_map(struct thread *self, struct map *map)
 {
-       map_groups__remove_overlappings(&self->mg, map);
+       map_groups__fixup_overlappings(&self->mg, map);
        map_groups__insert(&self->mg, map);
 }