aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/thread.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-11-27 13:29:20 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-27 14:22:00 -0500
commit95011c600740837288a3b34b411244a4d9157c4e (patch)
treef52496d2d378a338e7b0eee9b75e627bdfc4d2f1 /tools/perf/util/thread.c
parent23ea4a3fadc6b1692dec935397ea15e2affc1cba (diff)
perf symbols: Support multiple symtabs in struct thread
Making the routines that were so far specific to the kernel maps useful for all threads. This is done by making the kernel maps be contained in a kernel "thread". This gets the kernel specific routines closer to the userspace counterparts, which will help in reducing the boilerplate for resolving a symbol, as will be demonstrated in the next patches. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> 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: <1259346563-12568-9-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util/thread.c')
-rw-r--r--tools/perf/util/thread.c115
1 files changed, 89 insertions, 26 deletions
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 1796625f7784..2229f82cd630 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -9,17 +9,26 @@
9static struct rb_root threads; 9static struct rb_root threads;
10static struct thread *last_match; 10static struct thread *last_match;
11 11
12void thread__init(struct thread *self, pid_t pid)
13{
14 int i;
15 self->pid = pid;
16 self->comm = NULL;
17 for (i = 0; i < MAP__NR_TYPES; ++i) {
18 self->maps[i] = RB_ROOT;
19 INIT_LIST_HEAD(&self->removed_maps[i]);
20 }
21}
22
12static struct thread *thread__new(pid_t pid) 23static struct thread *thread__new(pid_t pid)
13{ 24{
14 struct thread *self = zalloc(sizeof(*self)); 25 struct thread *self = zalloc(sizeof(*self));
15 26
16 if (self != NULL) { 27 if (self != NULL) {
17 self->pid = pid; 28 thread__init(self, pid);
18 self->comm = malloc(32); 29 self->comm = malloc(32);
19 if (self->comm) 30 if (self->comm)
20 snprintf(self->comm, 32, ":%d", self->pid); 31 snprintf(self->comm, 32, ":%d", self->pid);
21 self->maps = RB_ROOT;
22 INIT_LIST_HEAD(&self->removed_maps);
23 } 32 }
24 33
25 return self; 34 return self;
@@ -44,24 +53,68 @@ int thread__comm_len(struct thread *self)
44 return self->comm_len; 53 return self->comm_len;
45} 54}
46 55
47static size_t thread__fprintf(struct thread *self, FILE *fp) 56static const char *map_type__name[MAP__NR_TYPES] = {
57 [MAP__FUNCTION] = "Functions",
58};
59
60static size_t __thread__fprintf_maps(struct thread *self,
61 enum map_type type, FILE *fp)
48{ 62{
63 size_t printed = fprintf(fp, "%s:\n", map_type__name[type]);
49 struct rb_node *nd; 64 struct rb_node *nd;
50 struct map *pos;
51 size_t ret = fprintf(fp, "Thread %d %s\nCurrent maps:\n",
52 self->pid, self->comm);
53 65
54 for (nd = rb_first(&self->maps); nd; nd = rb_next(nd)) { 66 for (nd = rb_first(&self->maps[type]); nd; nd = rb_next(nd)) {
55 pos = rb_entry(nd, struct map, rb_node); 67 struct map *pos = rb_entry(nd, struct map, rb_node);
56 ret += map__fprintf(pos, fp); 68 printed += fprintf(fp, "Map:");
69 printed += map__fprintf(pos, fp);
70 if (verbose > 1) {
71 printed += dso__fprintf(pos->dso, type, fp);
72 printed += fprintf(fp, "--\n");
73 }
57 } 74 }
58 75
59 ret = fprintf(fp, "Removed maps:\n"); 76 return printed;
77}
78
79size_t thread__fprintf_maps(struct thread *self, FILE *fp)
80{
81 size_t printed = 0, i;
82 for (i = 0; i < MAP__NR_TYPES; ++i)
83 printed += __thread__fprintf_maps(self, i, fp);
84 return printed;
85}
60 86
61 list_for_each_entry(pos, &self->removed_maps, node) 87static size_t __thread__fprintf_removed_maps(struct thread *self,
62 ret += map__fprintf(pos, fp); 88 enum map_type type, FILE *fp)
89{
90 struct map *pos;
91 size_t printed = 0;
92
93 list_for_each_entry(pos, &self->removed_maps[type], node) {
94 printed += fprintf(fp, "Map:");
95 printed += map__fprintf(pos, fp);
96 if (verbose > 1) {
97 printed += dso__fprintf(pos->dso, type, fp);
98 printed += fprintf(fp, "--\n");
99 }
100 }
101 return printed;
102}
63 103
64 return ret; 104static size_t thread__fprintf_removed_maps(struct thread *self, FILE *fp)
105{
106 size_t printed = 0, i;
107 for (i = 0; i < MAP__NR_TYPES; ++i)
108 printed += __thread__fprintf_removed_maps(self, i, fp);
109 return printed;
110}
111
112static size_t thread__fprintf(struct thread *self, FILE *fp)
113{
114 size_t printed = fprintf(fp, "Thread %d %s\n", self->pid, self->comm);
115 printed += thread__fprintf_removed_maps(self, fp);
116 printed += fprintf(fp, "Removed maps:\n");
117 return printed + thread__fprintf_removed_maps(self, fp);
65} 118}
66 119
67struct thread *threads__findnew(pid_t pid) 120struct thread *threads__findnew(pid_t pid)
@@ -117,7 +170,8 @@ struct thread *register_idle_thread(void)
117 170
118static void thread__remove_overlappings(struct thread *self, struct map *map) 171static void thread__remove_overlappings(struct thread *self, struct map *map)
119{ 172{
120 struct rb_node *next = rb_first(&self->maps); 173 struct rb_root *root = &self->maps[map->type];
174 struct rb_node *next = rb_first(root);
121 175
122 while (next) { 176 while (next) {
123 struct map *pos = rb_entry(next, struct map, rb_node); 177 struct map *pos = rb_entry(next, struct map, rb_node);
@@ -132,13 +186,13 @@ static void thread__remove_overlappings(struct thread *self, struct map *map)
132 map__fprintf(pos, stderr); 186 map__fprintf(pos, stderr);
133 } 187 }
134 188
135 rb_erase(&pos->rb_node, &self->maps); 189 rb_erase(&pos->rb_node, root);
136 /* 190 /*
137 * We may have references to this map, for instance in some 191 * We may have references to this map, for instance in some
138 * hist_entry instances, so just move them to a separate 192 * hist_entry instances, so just move them to a separate
139 * list. 193 * list.
140 */ 194 */
141 list_add_tail(&pos->node, &self->removed_maps); 195 list_add_tail(&pos->node, &self->removed_maps[map->type]);
142 } 196 }
143} 197}
144 198
@@ -185,12 +239,26 @@ struct map *maps__find(struct rb_root *maps, u64 ip)
185void thread__insert_map(struct thread *self, struct map *map) 239void thread__insert_map(struct thread *self, struct map *map)
186{ 240{
187 thread__remove_overlappings(self, map); 241 thread__remove_overlappings(self, map);
188 maps__insert(&self->maps, map); 242 maps__insert(&self->maps[map->type], map);
189} 243}
190 244
191int thread__fork(struct thread *self, struct thread *parent) 245static int thread__clone_maps(struct thread *self, struct thread *parent,
246 enum map_type type)
192{ 247{
193 struct rb_node *nd; 248 struct rb_node *nd;
249 for (nd = rb_first(&parent->maps[type]); nd; nd = rb_next(nd)) {
250 struct map *map = rb_entry(nd, struct map, rb_node);
251 struct map *new = map__clone(map);
252 if (new == NULL)
253 return -ENOMEM;
254 thread__insert_map(self, new);
255 }
256 return 0;
257}
258
259int thread__fork(struct thread *self, struct thread *parent)
260{
261 int i;
194 262
195 if (self->comm) 263 if (self->comm)
196 free(self->comm); 264 free(self->comm);
@@ -198,14 +266,9 @@ int thread__fork(struct thread *self, struct thread *parent)
198 if (!self->comm) 266 if (!self->comm)
199 return -ENOMEM; 267 return -ENOMEM;
200 268
201 for (nd = rb_first(&parent->maps); nd; nd = rb_next(nd)) { 269 for (i = 0; i < MAP__NR_TYPES; ++i)
202 struct map *map = rb_entry(nd, struct map, rb_node); 270 if (thread__clone_maps(self, parent, i) < 0)
203 struct map *new = map__clone(map);
204 if (!new)
205 return -ENOMEM; 271 return -ENOMEM;
206 thread__insert_map(self, new);
207 }
208
209 return 0; 272 return 0;
210} 273}
211 274