10 void map_groups__init(struct map_groups
*self
)
13 for (i
= 0; i
< MAP__NR_TYPES
; ++i
) {
14 self
->maps
[i
] = RB_ROOT
;
15 INIT_LIST_HEAD(&self
->removed_maps
[i
]);
19 static struct thread
*thread__new(pid_t pid
)
21 struct thread
*self
= zalloc(sizeof(*self
));
24 map_groups__init(&self
->mg
);
26 self
->comm
= malloc(32);
28 snprintf(self
->comm
, 32, ":%d", self
->pid
);
34 int thread__set_comm(struct thread
*self
, const char *comm
)
38 self
->comm
= strdup(comm
);
39 return self
->comm
? 0 : -ENOMEM
;
42 int thread__comm_len(struct thread
*self
)
44 if (!self
->comm_len
) {
47 self
->comm_len
= strlen(self
->comm
);
50 return self
->comm_len
;
53 static const char *map_type__name
[MAP__NR_TYPES
] = {
54 [MAP__FUNCTION
] = "Functions",
55 [MAP__VARIABLE
] = "Variables",
58 static size_t __map_groups__fprintf_maps(struct map_groups
*self
,
59 enum map_type type
, FILE *fp
)
61 size_t printed
= fprintf(fp
, "%s:\n", map_type__name
[type
]);
64 for (nd
= rb_first(&self
->maps
[type
]); nd
; nd
= rb_next(nd
)) {
65 struct map
*pos
= rb_entry(nd
, struct map
, rb_node
);
66 printed
+= fprintf(fp
, "Map:");
67 printed
+= map__fprintf(pos
, fp
);
69 printed
+= dso__fprintf(pos
->dso
, type
, fp
);
70 printed
+= fprintf(fp
, "--\n");
77 size_t map_groups__fprintf_maps(struct map_groups
*self
, FILE *fp
)
79 size_t printed
= 0, i
;
80 for (i
= 0; i
< MAP__NR_TYPES
; ++i
)
81 printed
+= __map_groups__fprintf_maps(self
, i
, fp
);
85 static size_t __map_groups__fprintf_removed_maps(struct map_groups
*self
,
86 enum map_type type
, FILE *fp
)
91 list_for_each_entry(pos
, &self
->removed_maps
[type
], node
) {
92 printed
+= fprintf(fp
, "Map:");
93 printed
+= map__fprintf(pos
, fp
);
95 printed
+= dso__fprintf(pos
->dso
, type
, fp
);
96 printed
+= fprintf(fp
, "--\n");
102 static size_t map_groups__fprintf_removed_maps(struct map_groups
*self
, FILE *fp
)
104 size_t printed
= 0, i
;
105 for (i
= 0; i
< MAP__NR_TYPES
; ++i
)
106 printed
+= __map_groups__fprintf_removed_maps(self
, i
, fp
);
110 static size_t map_groups__fprintf(struct map_groups
*self
, FILE *fp
)
112 size_t printed
= map_groups__fprintf_maps(self
, fp
);
113 printed
+= fprintf(fp
, "Removed maps:\n");
114 return printed
+ map_groups__fprintf_removed_maps(self
, fp
);
117 static size_t thread__fprintf(struct thread
*self
, FILE *fp
)
119 return fprintf(fp
, "Thread %d %s\n", self
->pid
, self
->comm
) +
120 map_groups__fprintf(&self
->mg
, fp
);
123 struct thread
*perf_session__findnew(struct perf_session
*self
, pid_t pid
)
125 struct rb_node
**p
= &self
->threads
.rb_node
;
126 struct rb_node
*parent
= NULL
;
130 * Font-end cache - PID lookups come in blocks,
131 * so most of the time we dont have to look up
134 if (self
->last_match
&& self
->last_match
->pid
== pid
)
135 return self
->last_match
;
139 th
= rb_entry(parent
, struct thread
, rb_node
);
141 if (th
->pid
== pid
) {
142 self
->last_match
= th
;
152 th
= thread__new(pid
);
154 rb_link_node(&th
->rb_node
, parent
, p
);
155 rb_insert_color(&th
->rb_node
, &self
->threads
);
156 self
->last_match
= th
;
162 static void map_groups__remove_overlappings(struct map_groups
*self
,
165 struct rb_root
*root
= &self
->maps
[map
->type
];
166 struct rb_node
*next
= rb_first(root
);
169 struct map
*pos
= rb_entry(next
, struct map
, rb_node
);
170 next
= rb_next(&pos
->rb_node
);
172 if (!map__overlap(pos
, map
))
176 fputs("overlapping maps:\n", stderr
);
177 map__fprintf(map
, stderr
);
178 map__fprintf(pos
, stderr
);
181 rb_erase(&pos
->rb_node
, root
);
183 * We may have references to this map, for instance in some
184 * hist_entry instances, so just move them to a separate
187 list_add_tail(&pos
->node
, &self
->removed_maps
[map
->type
]);
191 void maps__insert(struct rb_root
*maps
, struct map
*map
)
193 struct rb_node
**p
= &maps
->rb_node
;
194 struct rb_node
*parent
= NULL
;
195 const u64 ip
= map
->start
;
200 m
= rb_entry(parent
, struct map
, rb_node
);
207 rb_link_node(&map
->rb_node
, parent
, p
);
208 rb_insert_color(&map
->rb_node
, maps
);
211 struct map
*maps__find(struct rb_root
*maps
, u64 ip
)
213 struct rb_node
**p
= &maps
->rb_node
;
214 struct rb_node
*parent
= NULL
;
219 m
= rb_entry(parent
, struct map
, rb_node
);
222 else if (ip
> m
->end
)
231 void thread__insert_map(struct thread
*self
, struct map
*map
)
233 map_groups__remove_overlappings(&self
->mg
, map
);
234 map_groups__insert(&self
->mg
, map
);
238 * XXX This should not really _copy_ te maps, but refcount them.
240 static int map_groups__clone(struct map_groups
*self
,
241 struct map_groups
*parent
, enum map_type type
)
244 for (nd
= rb_first(&parent
->maps
[type
]); nd
; nd
= rb_next(nd
)) {
245 struct map
*map
= rb_entry(nd
, struct map
, rb_node
);
246 struct map
*new = map__clone(map
);
249 map_groups__insert(self
, new);
254 int thread__fork(struct thread
*self
, struct thread
*parent
)
260 self
->comm
= strdup(parent
->comm
);
264 for (i
= 0; i
< MAP__NR_TYPES
; ++i
)
265 if (map_groups__clone(&self
->mg
, &parent
->mg
, i
) < 0)
270 size_t perf_session__fprintf(struct perf_session
*self
, FILE *fp
)
275 for (nd
= rb_first(&self
->threads
); nd
; nd
= rb_next(nd
)) {
276 struct thread
*pos
= rb_entry(nd
, struct thread
, rb_node
);
278 ret
+= thread__fprintf(pos
, fp
);
284 struct symbol
*map_groups__find_symbol(struct map_groups
*self
,
285 struct perf_session
*session
,
286 enum map_type type
, u64 addr
,
287 symbol_filter_t filter
)
289 struct map
*map
= map_groups__find(self
, type
, addr
);
292 return map__find_symbol(map
, session
, map
->map_ip(map
, addr
), filter
);