]>
git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blob - tools/perf/util/thread.c
9 static struct rb_root threads
;
10 static struct thread
*last_match
;
12 void map_groups__init(struct map_groups
*self
)
15 for (i
= 0; i
< MAP__NR_TYPES
; ++i
) {
16 self
->maps
[i
] = RB_ROOT
;
17 INIT_LIST_HEAD(&self
->removed_maps
[i
]);
21 static struct thread
*thread__new(pid_t pid
)
23 struct thread
*self
= zalloc(sizeof(*self
));
26 map_groups__init(&self
->mg
);
28 self
->comm
= malloc(32);
30 snprintf(self
->comm
, 32, ":%d", self
->pid
);
36 int thread__set_comm(struct thread
*self
, const char *comm
)
40 self
->comm
= strdup(comm
);
41 return self
->comm
? 0 : -ENOMEM
;
44 int thread__comm_len(struct thread
*self
)
46 if (!self
->comm_len
) {
49 self
->comm_len
= strlen(self
->comm
);
52 return self
->comm_len
;
55 static const char *map_type__name
[MAP__NR_TYPES
] = {
56 [MAP__FUNCTION
] = "Functions",
59 static size_t __map_groups__fprintf_maps(struct map_groups
*self
,
60 enum map_type type
, FILE *fp
)
62 size_t printed
= fprintf(fp
, "%s:\n", map_type__name
[type
]);
65 for (nd
= rb_first(&self
->maps
[type
]); nd
; nd
= rb_next(nd
)) {
66 struct map
*pos
= rb_entry(nd
, struct map
, rb_node
);
67 printed
+= fprintf(fp
, "Map:");
68 printed
+= map__fprintf(pos
, fp
);
70 printed
+= dso__fprintf(pos
->dso
, type
, fp
);
71 printed
+= fprintf(fp
, "--\n");
78 size_t map_groups__fprintf_maps(struct map_groups
*self
, FILE *fp
)
80 size_t printed
= 0, i
;
81 for (i
= 0; i
< MAP__NR_TYPES
; ++i
)
82 printed
+= __map_groups__fprintf_maps(self
, i
, fp
);
86 static size_t __map_groups__fprintf_removed_maps(struct map_groups
*self
,
87 enum map_type type
, FILE *fp
)
92 list_for_each_entry(pos
, &self
->removed_maps
[type
], node
) {
93 printed
+= fprintf(fp
, "Map:");
94 printed
+= map__fprintf(pos
, fp
);
96 printed
+= dso__fprintf(pos
->dso
, type
, fp
);
97 printed
+= fprintf(fp
, "--\n");
103 static size_t map_groups__fprintf_removed_maps(struct map_groups
*self
, FILE *fp
)
105 size_t printed
= 0, i
;
106 for (i
= 0; i
< MAP__NR_TYPES
; ++i
)
107 printed
+= __map_groups__fprintf_removed_maps(self
, i
, fp
);
111 static size_t map_groups__fprintf(struct map_groups
*self
, FILE *fp
)
113 size_t printed
= map_groups__fprintf_maps(self
, fp
);
114 printed
+= fprintf(fp
, "Removed maps:\n");
115 return printed
+ map_groups__fprintf_removed_maps(self
, fp
);
118 static size_t thread__fprintf(struct thread
*self
, FILE *fp
)
120 return fprintf(fp
, "Thread %d %s\n", self
->pid
, self
->comm
) +
121 map_groups__fprintf(&self
->mg
, fp
);
124 struct thread
*threads__findnew(pid_t pid
)
126 struct rb_node
**p
= &threads
.rb_node
;
127 struct rb_node
*parent
= NULL
;
131 * Font-end cache - PID lookups come in blocks,
132 * so most of the time we dont have to look up
135 if (last_match
&& last_match
->pid
== pid
)
140 th
= rb_entry(parent
, struct thread
, rb_node
);
142 if (th
->pid
== pid
) {
153 th
= thread__new(pid
);
155 rb_link_node(&th
->rb_node
, parent
, p
);
156 rb_insert_color(&th
->rb_node
, &threads
);
163 struct thread
*register_idle_thread(void)
165 struct thread
*thread
= threads__findnew(0);
167 if (!thread
|| thread__set_comm(thread
, "swapper")) {
168 fprintf(stderr
, "problem inserting idle task.\n");
175 static void map_groups__remove_overlappings(struct map_groups
*self
,
178 struct rb_root
*root
= &self
->maps
[map
->type
];
179 struct rb_node
*next
= rb_first(root
);
182 struct map
*pos
= rb_entry(next
, struct map
, rb_node
);
183 next
= rb_next(&pos
->rb_node
);
185 if (!map__overlap(pos
, map
))
189 fputs("overlapping maps:\n", stderr
);
190 map__fprintf(map
, stderr
);
191 map__fprintf(pos
, stderr
);
194 rb_erase(&pos
->rb_node
, root
);
196 * We may have references to this map, for instance in some
197 * hist_entry instances, so just move them to a separate
200 list_add_tail(&pos
->node
, &self
->removed_maps
[map
->type
]);
204 void maps__insert(struct rb_root
*maps
, struct map
*map
)
206 struct rb_node
**p
= &maps
->rb_node
;
207 struct rb_node
*parent
= NULL
;
208 const u64 ip
= map
->start
;
213 m
= rb_entry(parent
, struct map
, rb_node
);
220 rb_link_node(&map
->rb_node
, parent
, p
);
221 rb_insert_color(&map
->rb_node
, maps
);
224 struct map
*maps__find(struct rb_root
*maps
, u64 ip
)
226 struct rb_node
**p
= &maps
->rb_node
;
227 struct rb_node
*parent
= NULL
;
232 m
= rb_entry(parent
, struct map
, rb_node
);
235 else if (ip
> m
->end
)
244 void thread__insert_map(struct thread
*self
, struct map
*map
)
246 map_groups__remove_overlappings(&self
->mg
, map
);
247 map_groups__insert(&self
->mg
, map
);
251 * XXX This should not really _copy_ te maps, but refcount them.
253 static int map_groups__clone(struct map_groups
*self
,
254 struct map_groups
*parent
, enum map_type type
)
257 for (nd
= rb_first(&parent
->maps
[type
]); nd
; nd
= rb_next(nd
)) {
258 struct map
*map
= rb_entry(nd
, struct map
, rb_node
);
259 struct map
*new = map__clone(map
);
262 map_groups__insert(self
, new);
267 int thread__fork(struct thread
*self
, struct thread
*parent
)
273 self
->comm
= strdup(parent
->comm
);
277 for (i
= 0; i
< MAP__NR_TYPES
; ++i
)
278 if (map_groups__clone(&self
->mg
, &parent
->mg
, i
) < 0)
283 size_t threads__fprintf(FILE *fp
)
288 for (nd
= rb_first(&threads
); nd
; nd
= rb_next(nd
)) {
289 struct thread
*pos
= rb_entry(nd
, struct thread
, rb_node
);
291 ret
+= thread__fprintf(pos
, fp
);
297 struct symbol
*map_groups__find_symbol(struct map_groups
*self
,
298 enum map_type type
, u64 addr
,
299 symbol_filter_t filter
)
301 struct map
*map
= map_groups__find(self
, type
, addr
);
304 return map__find_symbol(map
, map
->map_ip(map
, addr
), filter
);