summaryrefslogtreecommitdiff
path: root/tools/perf/util/thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/thread.c')
-rw-r--r--tools/perf/util/thread.c93
1 files changed, 74 insertions, 19 deletions
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 4a08dcf50b68..fa968312ee7d 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -31,12 +31,41 @@ static struct thread *thread__new(pid_t pid)
return self;
}
+static void map_groups__flush(struct map_groups *self)
+{
+ int type;
+
+ for (type = 0; type < MAP__NR_TYPES; type++) {
+ struct rb_root *root = &self->maps[type];
+ struct rb_node *next = rb_first(root);
+
+ while (next) {
+ struct map *pos = rb_entry(next, struct map, rb_node);
+ next = rb_next(&pos->rb_node);
+ rb_erase(&pos->rb_node, root);
+ /*
+ * 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[pos->type]);
+ }
+ }
+}
+
int thread__set_comm(struct thread *self, const char *comm)
{
+ int err;
+
if (self->comm)
free(self->comm);
self->comm = strdup(comm);
- return self->comm ? 0 : -ENOMEM;
+ err = self->comm == NULL ? -ENOMEM : 0;
+ if (!err) {
+ self->comm_set = true;
+ map_groups__flush(&self->mg);
+ }
+ return err;
}
int thread__comm_len(struct thread *self)
@@ -50,13 +79,8 @@ int thread__comm_len(struct thread *self)
return self->comm_len;
}
-static const char *map_type__name[MAP__NR_TYPES] = {
- [MAP__FUNCTION] = "Functions",
- [MAP__VARIABLE] = "Variables",
-};
-
-static size_t __map_groups__fprintf_maps(struct map_groups *self,
- enum map_type type, FILE *fp)
+size_t __map_groups__fprintf_maps(struct map_groups *self,
+ enum map_type type, FILE *fp)
{
size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
struct rb_node *nd;
@@ -65,7 +89,7 @@ static size_t __map_groups__fprintf_maps(struct map_groups *self,
struct map *pos = rb_entry(nd, struct map, rb_node);
printed += fprintf(fp, "Map:");
printed += map__fprintf(pos, fp);
- if (verbose > 1) {
+ if (verbose > 2) {
printed += dso__fprintf(pos->dso, type, fp);
printed += fprintf(fp, "--\n");
}
@@ -159,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);
@@ -185,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)
@@ -230,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);
}
@@ -255,11 +308,14 @@ int thread__fork(struct thread *self, struct thread *parent)
{
int i;
- if (self->comm)
- free(self->comm);
- self->comm = strdup(parent->comm);
- if (!self->comm)
- return -ENOMEM;
+ if (parent->comm_set) {
+ if (self->comm)
+ free(self->comm);
+ self->comm = strdup(parent->comm);
+ if (!self->comm)
+ return -ENOMEM;
+ self->comm_set = true;
+ }
for (i = 0; i < MAP__NR_TYPES; ++i)
if (map_groups__clone(&self->mg, &parent->mg, i) < 0)
@@ -282,14 +338,13 @@ size_t perf_session__fprintf(struct perf_session *self, FILE *fp)
}
struct symbol *map_groups__find_symbol(struct map_groups *self,
- struct perf_session *session,
enum map_type type, u64 addr,
symbol_filter_t filter)
{
struct map *map = map_groups__find(self, type, addr);
if (map != NULL)
- return map__find_symbol(map, session, map->map_ip(map, addr), filter);
+ return map__find_symbol(map, map->map_ip(map, addr), filter);
return NULL;
}