diff options
Diffstat (limited to 'tools/perf/util/thread.c')
-rw-r--r-- | tools/perf/util/thread.c | 129 |
1 files changed, 83 insertions, 46 deletions
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; |