aboutsummaryrefslogtreecommitdiffstats
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.c213
1 files changed, 28 insertions, 185 deletions
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 21b92162282b..1f7ecd47f499 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -7,13 +7,35 @@
7#include "util.h" 7#include "util.h"
8#include "debug.h" 8#include "debug.h"
9 9
10void map_groups__init(struct map_groups *self) 10int find_all_tid(int pid, pid_t ** all_tid)
11{ 11{
12 char name[256];
13 int items;
14 struct dirent **namelist = NULL;
15 int ret = 0;
12 int i; 16 int i;
13 for (i = 0; i < MAP__NR_TYPES; ++i) { 17
14 self->maps[i] = RB_ROOT; 18 sprintf(name, "/proc/%d/task", pid);
15 INIT_LIST_HEAD(&self->removed_maps[i]); 19 items = scandir(name, &namelist, NULL, NULL);
20 if (items <= 0)
21 return -ENOENT;
22 *all_tid = malloc(sizeof(pid_t) * items);
23 if (!*all_tid) {
24 ret = -ENOMEM;
25 goto failure;
16 } 26 }
27
28 for (i = 0; i < items; i++)
29 (*all_tid)[i] = atoi(namelist[i]->d_name);
30
31 ret = items;
32
33failure:
34 for (i=0; i<items; i++)
35 free(namelist[i]);
36 free(namelist);
37
38 return ret;
17} 39}
18 40
19static struct thread *thread__new(pid_t pid) 41static struct thread *thread__new(pid_t pid)
@@ -31,28 +53,6 @@ static struct thread *thread__new(pid_t pid)
31 return self; 53 return self;
32} 54}
33 55
34static void map_groups__flush(struct map_groups *self)
35{
36 int type;
37
38 for (type = 0; type < MAP__NR_TYPES; type++) {
39 struct rb_root *root = &self->maps[type];
40 struct rb_node *next = rb_first(root);
41
42 while (next) {
43 struct map *pos = rb_entry(next, struct map, rb_node);
44 next = rb_next(&pos->rb_node);
45 rb_erase(&pos->rb_node, root);
46 /*
47 * We may have references to this map, for
48 * instance in some hist_entry instances, so
49 * just move them to a separate list.
50 */
51 list_add_tail(&pos->node, &self->removed_maps[pos->type]);
52 }
53 }
54}
55
56int thread__set_comm(struct thread *self, const char *comm) 56int thread__set_comm(struct thread *self, const char *comm)
57{ 57{
58 int err; 58 int err;
@@ -79,69 +79,10 @@ int thread__comm_len(struct thread *self)
79 return self->comm_len; 79 return self->comm_len;
80} 80}
81 81
82static size_t __map_groups__fprintf_maps(struct map_groups *self,
83 enum map_type type, FILE *fp)
84{
85 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
86 struct rb_node *nd;
87
88 for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
89 struct map *pos = rb_entry(nd, struct map, rb_node);
90 printed += fprintf(fp, "Map:");
91 printed += map__fprintf(pos, fp);
92 if (verbose > 1) {
93 printed += dso__fprintf(pos->dso, type, fp);
94 printed += fprintf(fp, "--\n");
95 }
96 }
97
98 return printed;
99}
100
101size_t map_groups__fprintf_maps(struct map_groups *self, FILE *fp)
102{
103 size_t printed = 0, i;
104 for (i = 0; i < MAP__NR_TYPES; ++i)
105 printed += __map_groups__fprintf_maps(self, i, fp);
106 return printed;
107}
108
109static size_t __map_groups__fprintf_removed_maps(struct map_groups *self,
110 enum map_type type, FILE *fp)
111{
112 struct map *pos;
113 size_t printed = 0;
114
115 list_for_each_entry(pos, &self->removed_maps[type], node) {
116 printed += fprintf(fp, "Map:");
117 printed += map__fprintf(pos, fp);
118 if (verbose > 1) {
119 printed += dso__fprintf(pos->dso, type, fp);
120 printed += fprintf(fp, "--\n");
121 }
122 }
123 return printed;
124}
125
126static size_t map_groups__fprintf_removed_maps(struct map_groups *self, FILE *fp)
127{
128 size_t printed = 0, i;
129 for (i = 0; i < MAP__NR_TYPES; ++i)
130 printed += __map_groups__fprintf_removed_maps(self, i, fp);
131 return printed;
132}
133
134static size_t map_groups__fprintf(struct map_groups *self, FILE *fp)
135{
136 size_t printed = map_groups__fprintf_maps(self, fp);
137 printed += fprintf(fp, "Removed maps:\n");
138 return printed + map_groups__fprintf_removed_maps(self, fp);
139}
140
141static size_t thread__fprintf(struct thread *self, FILE *fp) 82static size_t thread__fprintf(struct thread *self, FILE *fp)
142{ 83{
143 return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) + 84 return fprintf(fp, "Thread %d %s\n", self->pid, self->comm) +
144 map_groups__fprintf(&self->mg, fp); 85 map_groups__fprintf(&self->mg, verbose, fp);
145} 86}
146 87
147struct thread *perf_session__findnew(struct perf_session *self, pid_t pid) 88struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
@@ -183,98 +124,12 @@ struct thread *perf_session__findnew(struct perf_session *self, pid_t pid)
183 return th; 124 return th;
184} 125}
185 126
186static void map_groups__remove_overlappings(struct map_groups *self,
187 struct map *map)
188{
189 struct rb_root *root = &self->maps[map->type];
190 struct rb_node *next = rb_first(root);
191
192 while (next) {
193 struct map *pos = rb_entry(next, struct map, rb_node);
194 next = rb_next(&pos->rb_node);
195
196 if (!map__overlap(pos, map))
197 continue;
198
199 if (verbose >= 2) {
200 fputs("overlapping maps:\n", stderr);
201 map__fprintf(map, stderr);
202 map__fprintf(pos, stderr);
203 }
204
205 rb_erase(&pos->rb_node, root);
206 /*
207 * We may have references to this map, for instance in some
208 * hist_entry instances, so just move them to a separate
209 * list.
210 */
211 list_add_tail(&pos->node, &self->removed_maps[map->type]);
212 }
213}
214
215void maps__insert(struct rb_root *maps, struct map *map)
216{
217 struct rb_node **p = &maps->rb_node;
218 struct rb_node *parent = NULL;
219 const u64 ip = map->start;
220 struct map *m;
221
222 while (*p != NULL) {
223 parent = *p;
224 m = rb_entry(parent, struct map, rb_node);
225 if (ip < m->start)
226 p = &(*p)->rb_left;
227 else
228 p = &(*p)->rb_right;
229 }
230
231 rb_link_node(&map->rb_node, parent, p);
232 rb_insert_color(&map->rb_node, maps);
233}
234
235struct map *maps__find(struct rb_root *maps, u64 ip)
236{
237 struct rb_node **p = &maps->rb_node;
238 struct rb_node *parent = NULL;
239 struct map *m;
240
241 while (*p != NULL) {
242 parent = *p;
243 m = rb_entry(parent, struct map, rb_node);
244 if (ip < m->start)
245 p = &(*p)->rb_left;
246 else if (ip > m->end)
247 p = &(*p)->rb_right;
248 else
249 return m;
250 }
251
252 return NULL;
253}
254
255void thread__insert_map(struct thread *self, struct map *map) 127void thread__insert_map(struct thread *self, struct map *map)
256{ 128{
257 map_groups__remove_overlappings(&self->mg, map); 129 map_groups__fixup_overlappings(&self->mg, map, verbose, stderr);
258 map_groups__insert(&self->mg, map); 130 map_groups__insert(&self->mg, map);
259} 131}
260 132
261/*
262 * XXX This should not really _copy_ te maps, but refcount them.
263 */
264static int map_groups__clone(struct map_groups *self,
265 struct map_groups *parent, enum map_type type)
266{
267 struct rb_node *nd;
268 for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
269 struct map *map = rb_entry(nd, struct map, rb_node);
270 struct map *new = map__clone(map);
271 if (new == NULL)
272 return -ENOMEM;
273 map_groups__insert(self, new);
274 }
275 return 0;
276}
277
278int thread__fork(struct thread *self, struct thread *parent) 133int thread__fork(struct thread *self, struct thread *parent)
279{ 134{
280 int i; 135 int i;
@@ -307,15 +162,3 @@ size_t perf_session__fprintf(struct perf_session *self, FILE *fp)
307 162
308 return ret; 163 return ret;
309} 164}
310
311struct symbol *map_groups__find_symbol(struct map_groups *self,
312 enum map_type type, u64 addr,
313 symbol_filter_t filter)
314{
315 struct map *map = map_groups__find(self, type, addr);
316
317 if (map != NULL)
318 return map__find_symbol(map, map->map_ip(map, addr), filter);
319
320 return NULL;
321}