diff options
-rw-r--r-- | tools/perf/Makefile | 1 | ||||
-rw-r--r-- | tools/perf/util/event.h | 4 | ||||
-rw-r--r-- | tools/perf/util/thread.c | 129 | ||||
-rw-r--r-- | tools/perf/util/thread.h | 12 |
4 files changed, 95 insertions, 51 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 3a99a9fda645..055290a5b835 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -341,6 +341,7 @@ LIB_H += util/color.h | |||
341 | LIB_H += util/values.h | 341 | LIB_H += util/values.h |
342 | LIB_H += util/sort.h | 342 | LIB_H += util/sort.h |
343 | LIB_H += util/hist.h | 343 | LIB_H += util/hist.h |
344 | LIB_H += util/thread.h | ||
344 | 345 | ||
345 | LIB_OBJS += util/abspath.o | 346 | LIB_OBJS += util/abspath.o |
346 | LIB_OBJS += util/alias.o | 347 | LIB_OBJS += util/alias.o |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index c31a5da6458b..4c69eb553807 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -3,7 +3,7 @@ | |||
3 | 3 | ||
4 | #include "../perf.h" | 4 | #include "../perf.h" |
5 | #include "util.h" | 5 | #include "util.h" |
6 | #include <linux/list.h> | 6 | #include <linux/rbtree.h> |
7 | 7 | ||
8 | enum { | 8 | enum { |
9 | SHOW_KERNEL = 1, | 9 | SHOW_KERNEL = 1, |
@@ -79,7 +79,7 @@ typedef union event_union { | |||
79 | } event_t; | 79 | } event_t; |
80 | 80 | ||
81 | struct map { | 81 | struct map { |
82 | struct list_head node; | 82 | struct rb_node rb_node; |
83 | u64 start; | 83 | u64 start; |
84 | u64 end; | 84 | u64 end; |
85 | u64 pgoff; | 85 | u64 pgoff; |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 45efb5db0d19..9d0945cc66d1 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -15,7 +15,7 @@ static struct thread *thread__new(pid_t pid) | |||
15 | self->comm = malloc(32); | 15 | self->comm = malloc(32); |
16 | if (self->comm) | 16 | if (self->comm) |
17 | snprintf(self->comm, 32, ":%d", self->pid); | 17 | snprintf(self->comm, 32, ":%d", self->pid); |
18 | INIT_LIST_HEAD(&self->maps); | 18 | self->maps = RB_ROOT; |
19 | } | 19 | } |
20 | 20 | ||
21 | return self; | 21 | return self; |
@@ -31,11 +31,13 @@ int thread__set_comm(struct thread *self, const char *comm) | |||
31 | 31 | ||
32 | static size_t thread__fprintf(struct thread *self, FILE *fp) | 32 | static size_t thread__fprintf(struct thread *self, FILE *fp) |
33 | { | 33 | { |
34 | struct map *pos; | 34 | struct rb_node *nd; |
35 | size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); | 35 | size_t ret = fprintf(fp, "Thread %d %s\n", self->pid, self->comm); |
36 | 36 | ||
37 | list_for_each_entry(pos, &self->maps, node) | 37 | for (nd = rb_first(&self->maps); nd; nd = rb_next(nd)) { |
38 | struct map *pos = rb_entry(nd, struct map, rb_node); | ||
38 | ret += map__fprintf(pos, fp); | 39 | ret += map__fprintf(pos, fp); |
40 | } | ||
39 | 41 | ||
40 | return ret; | 42 | return ret; |
41 | } | 43 | } |
@@ -93,42 +95,90 @@ register_idle_thread(struct rb_root *threads, struct thread **last_match) | |||
93 | return thread; | 95 | return thread; |
94 | } | 96 | } |
95 | 97 | ||
96 | void thread__insert_map(struct thread *self, struct map *map) | 98 | static void thread__remove_overlappings(struct thread *self, struct map *map) |
97 | { | 99 | { |
98 | struct map *pos, *tmp; | 100 | struct rb_node *next = rb_first(&self->maps); |
99 | 101 | ||
100 | list_for_each_entry_safe(pos, tmp, &self->maps, node) { | 102 | while (next) { |
101 | if (map__overlap(pos, map)) { | 103 | struct map *pos = rb_entry(next, struct map, rb_node); |
102 | if (verbose >= 2) { | 104 | next = rb_next(&pos->rb_node); |
103 | printf("overlapping maps:\n"); | 105 | |
104 | map__fprintf(map, stdout); | 106 | if (!map__overlap(pos, map)) |
105 | map__fprintf(pos, stdout); | 107 | continue; |
106 | } | 108 | |
107 | 109 | if (verbose >= 2) { | |
108 | if (map->start <= pos->start && map->end > pos->start) | 110 | printf("overlapping maps:\n"); |
109 | pos->start = map->end; | 111 | map__fprintf(map, stdout); |
110 | 112 | map__fprintf(pos, stdout); | |
111 | if (map->end >= pos->end && map->start < pos->end) | 113 | } |
112 | pos->end = map->start; | 114 | |
113 | 115 | if (map->start <= pos->start && map->end > pos->start) | |
114 | if (verbose >= 2) { | 116 | pos->start = map->end; |
115 | printf("after collision:\n"); | 117 | |
116 | map__fprintf(pos, stdout); | 118 | if (map->end >= pos->end && map->start < pos->end) |
117 | } | 119 | pos->end = map->start; |
118 | 120 | ||
119 | if (pos->start >= pos->end) { | 121 | if (verbose >= 2) { |
120 | list_del_init(&pos->node); | 122 | printf("after collision:\n"); |
121 | free(pos); | 123 | map__fprintf(pos, stdout); |
122 | } | 124 | } |
125 | |||
126 | if (pos->start >= pos->end) { | ||
127 | rb_erase(&pos->rb_node, &self->maps); | ||
128 | free(pos); | ||
123 | } | 129 | } |
124 | } | 130 | } |
131 | } | ||
132 | |||
133 | void maps__insert(struct rb_root *maps, struct map *map) | ||
134 | { | ||
135 | struct rb_node **p = &maps->rb_node; | ||
136 | struct rb_node *parent = NULL; | ||
137 | const u64 ip = map->start; | ||
138 | struct map *m; | ||
139 | |||
140 | while (*p != NULL) { | ||
141 | parent = *p; | ||
142 | m = rb_entry(parent, struct map, rb_node); | ||
143 | if (ip < m->start) | ||
144 | p = &(*p)->rb_left; | ||
145 | else | ||
146 | p = &(*p)->rb_right; | ||
147 | } | ||
148 | |||
149 | rb_link_node(&map->rb_node, parent, p); | ||
150 | rb_insert_color(&map->rb_node, maps); | ||
151 | } | ||
152 | |||
153 | struct map *maps__find(struct rb_root *maps, u64 ip) | ||
154 | { | ||
155 | struct rb_node **p = &maps->rb_node; | ||
156 | struct rb_node *parent = NULL; | ||
157 | struct map *m; | ||
158 | |||
159 | while (*p != NULL) { | ||
160 | parent = *p; | ||
161 | m = rb_entry(parent, struct map, rb_node); | ||
162 | if (ip < m->start) | ||
163 | p = &(*p)->rb_left; | ||
164 | else if (ip > m->end) | ||
165 | p = &(*p)->rb_right; | ||
166 | else | ||
167 | return m; | ||
168 | } | ||
169 | |||
170 | return NULL; | ||
171 | } | ||
125 | 172 | ||
126 | list_add_tail(&map->node, &self->maps); | 173 | void thread__insert_map(struct thread *self, struct map *map) |
174 | { | ||
175 | thread__remove_overlappings(self, map); | ||
176 | maps__insert(&self->maps, map); | ||
127 | } | 177 | } |
128 | 178 | ||
129 | int thread__fork(struct thread *self, struct thread *parent) | 179 | int thread__fork(struct thread *self, struct thread *parent) |
130 | { | 180 | { |
131 | struct map *map; | 181 | struct rb_node *nd; |
132 | 182 | ||
133 | if (self->comm) | 183 | if (self->comm) |
134 | free(self->comm); | 184 | free(self->comm); |
@@ -136,7 +186,8 @@ int thread__fork(struct thread *self, struct thread *parent) | |||
136 | if (!self->comm) | 186 | if (!self->comm) |
137 | return -ENOMEM; | 187 | return -ENOMEM; |
138 | 188 | ||
139 | list_for_each_entry(map, &parent->maps, node) { | 189 | for (nd = rb_first(&parent->maps); nd; nd = rb_next(nd)) { |
190 | struct map *map = rb_entry(nd, struct map, rb_node); | ||
140 | struct map *new = map__clone(map); | 191 | struct map *new = map__clone(map); |
141 | if (!new) | 192 | if (!new) |
142 | return -ENOMEM; | 193 | return -ENOMEM; |
@@ -146,20 +197,6 @@ int thread__fork(struct thread *self, struct thread *parent) | |||
146 | return 0; | 197 | return 0; |
147 | } | 198 | } |
148 | 199 | ||
149 | struct map *thread__find_map(struct thread *self, u64 ip) | ||
150 | { | ||
151 | struct map *pos; | ||
152 | |||
153 | if (self == NULL) | ||
154 | return NULL; | ||
155 | |||
156 | list_for_each_entry(pos, &self->maps, node) | ||
157 | if (ip >= pos->start && ip <= pos->end) | ||
158 | return pos; | ||
159 | |||
160 | return NULL; | ||
161 | } | ||
162 | |||
163 | size_t threads__fprintf(FILE *fp, struct rb_root *threads) | 200 | size_t threads__fprintf(FILE *fp, struct rb_root *threads) |
164 | { | 201 | { |
165 | size_t ret = 0; | 202 | size_t ret = 0; |
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 693ed1ea10b4..bbb37c1a52ee 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -2,13 +2,12 @@ | |||
2 | #define __PERF_THREAD_H | 2 | #define __PERF_THREAD_H |
3 | 3 | ||
4 | #include <linux/rbtree.h> | 4 | #include <linux/rbtree.h> |
5 | #include <linux/list.h> | ||
6 | #include <unistd.h> | 5 | #include <unistd.h> |
7 | #include "symbol.h" | 6 | #include "symbol.h" |
8 | 7 | ||
9 | struct thread { | 8 | struct thread { |
10 | struct rb_node rb_node; | 9 | struct rb_node rb_node; |
11 | struct list_head maps; | 10 | struct rb_root maps; |
12 | pid_t pid; | 11 | pid_t pid; |
13 | char shortname[3]; | 12 | char shortname[3]; |
14 | char *comm; | 13 | char *comm; |
@@ -21,7 +20,14 @@ struct thread * | |||
21 | register_idle_thread(struct rb_root *threads, struct thread **last_match); | 20 | register_idle_thread(struct rb_root *threads, struct thread **last_match); |
22 | void thread__insert_map(struct thread *self, struct map *map); | 21 | void thread__insert_map(struct thread *self, struct map *map); |
23 | int thread__fork(struct thread *self, struct thread *parent); | 22 | int thread__fork(struct thread *self, struct thread *parent); |
24 | struct map *thread__find_map(struct thread *self, u64 ip); | ||
25 | size_t threads__fprintf(FILE *fp, struct rb_root *threads); | 23 | size_t threads__fprintf(FILE *fp, struct rb_root *threads); |
26 | 24 | ||
25 | void maps__insert(struct rb_root *maps, struct map *map); | ||
26 | struct map *maps__find(struct rb_root *maps, u64 ip); | ||
27 | |||
28 | static inline struct map *thread__find_map(struct thread *self, u64 ip) | ||
29 | { | ||
30 | return self ? maps__find(&self->maps, ip) : NULL; | ||
31 | } | ||
32 | |||
27 | #endif /* __PERF_THREAD_H */ | 33 | #endif /* __PERF_THREAD_H */ |