aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/machine.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/machine.c')
-rw-r--r--tools/perf/util/machine.c67
1 files changed, 49 insertions, 18 deletions
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 28a9541c4835..cf826eca3aaf 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -24,9 +24,10 @@
#include "asm/bug.h"
#include "bpf-event.h"
-#include "sane_ctype.h"
+#include <linux/ctype.h>
#include <symbol/kallsyms.h>
#include <linux/mman.h>
+#include <linux/zalloc.h>
static void __machine__remove_thread(struct machine *machine, struct thread *th, bool lock);
@@ -209,6 +210,18 @@ void machine__exit(struct machine *machine)
for (i = 0; i < THREADS__TABLE_SIZE; i++) {
struct threads *threads = &machine->threads[i];
+ struct thread *thread, *n;
+ /*
+ * Forget about the dead, at this point whatever threads were
+ * left in the dead lists better have a reference count taken
+ * by who is using them, and then, when they drop those references
+ * and it finally hits zero, thread__put() will check and see that
+ * its not in the dead threads list and will not try to remove it
+ * from there, just calling thread__delete() straight away.
+ */
+ list_for_each_entry_safe(thread, n, &threads->dead, node)
+ list_del_init(&thread->node);
+
exit_rwsem(&threads->lock);
}
}
@@ -704,12 +717,12 @@ static int machine__process_ksymbol_register(struct machine *machine,
return -ENOMEM;
map->start = event->ksymbol_event.addr;
- map->pgoff = map->start;
map->end = map->start + event->ksymbol_event.len;
map_groups__insert(&machine->kmaps, map);
}
- sym = symbol__new(event->ksymbol_event.addr, event->ksymbol_event.len,
+ sym = symbol__new(map->map_ip(map, map->start),
+ event->ksymbol_event.len,
0, 0, event->ksymbol_event.name);
if (!sym)
return -ENOMEM;
@@ -797,7 +810,7 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start,
out:
/* put the dso here, corresponding to machine__findnew_module_dso */
dso__put(dso);
- free(m.name);
+ zfree(&m.name);
return map;
}
@@ -924,7 +937,8 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
* symbol_name if it's not that important.
*/
static int machine__get_running_kernel_start(struct machine *machine,
- const char **symbol_name, u64 *start)
+ const char **symbol_name,
+ u64 *start, u64 *end)
{
char filename[PATH_MAX];
int i, err = -1;
@@ -949,6 +963,11 @@ static int machine__get_running_kernel_start(struct machine *machine,
*symbol_name = name;
*start = addr;
+
+ err = kallsyms__get_function_start(filename, "_etext", &addr);
+ if (!err)
+ *end = addr;
+
return 0;
}
@@ -1235,9 +1254,9 @@ static char *get_kernel_version(const char *root_dir)
return NULL;
tmp = fgets(version, sizeof(version), file);
- if (!tmp)
- *version = '\0';
fclose(file);
+ if (!tmp)
+ return NULL;
name = strstr(version, prefix);
if (!name)
@@ -1331,7 +1350,7 @@ static int map_groups__set_modules_path_dir(struct map_groups *mg,
if (m.kmod)
ret = map_groups__set_module_path(mg, path, &m);
- free(m.name);
+ zfree(&m.name);
if (ret)
goto out;
@@ -1441,7 +1460,7 @@ int machine__create_kernel_maps(struct machine *machine)
struct dso *kernel = machine__get_kernel(machine);
const char *name = NULL;
struct map *map;
- u64 addr = 0;
+ u64 start = 0, end = ~0ULL;
int ret;
if (kernel == NULL)
@@ -1460,9 +1479,9 @@ int machine__create_kernel_maps(struct machine *machine)
"continuing anyway...\n", machine->pid);
}
- if (!machine__get_running_kernel_start(machine, &name, &addr)) {
+ if (!machine__get_running_kernel_start(machine, &name, &start, &end)) {
if (name &&
- map__set_kallsyms_ref_reloc_sym(machine->vmlinux_map, name, addr)) {
+ map__set_kallsyms_ref_reloc_sym(machine->vmlinux_map, name, start)) {
machine__destroy_kernel_maps(machine);
ret = -1;
goto out_put;
@@ -1472,16 +1491,19 @@ int machine__create_kernel_maps(struct machine *machine)
* we have a real start address now, so re-order the kmaps
* assume it's the last in the kmaps
*/
- machine__update_kernel_mmap(machine, addr, ~0ULL);
+ machine__update_kernel_mmap(machine, start, end);
}
if (machine__create_extra_kernel_maps(machine, kernel))
pr_debug("Problems creating extra kernel maps, continuing anyway...\n");
- /* update end address of the kernel map using adjacent module address */
- map = map__next(machine__kernel_map(machine));
- if (map)
- machine__set_kernel_mmap(machine, addr, map->start);
+ if (end == ~0ULL) {
+ /* update end address of the kernel map using adjacent module address */
+ map = map__next(machine__kernel_map(machine));
+ if (map)
+ machine__set_kernel_mmap(machine, start, map->start);
+ }
+
out_put:
dso__put(kernel);
return ret;
@@ -1749,9 +1771,11 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,
if (threads->last_match == th)
threads__set_last_match(threads, NULL);
- BUG_ON(refcount_read(&th->refcnt) == 0);
if (lock)
down_write(&threads->lock);
+
+ BUG_ON(refcount_read(&th->refcnt) == 0);
+
rb_erase_cached(&th->rb_node, &threads->entries);
RB_CLEAR_NODE(&th->rb_node);
--threads->nr;
@@ -1761,9 +1785,16 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,
* will be called and we will remove it from the dead_threads list.
*/
list_add_tail(&th->node, &threads->dead);
+
+ /*
+ * We need to do the put here because if this is the last refcount,
+ * then we will be touching the threads->dead head when removing the
+ * thread.
+ */
+ thread__put(th);
+
if (lock)
up_write(&threads->lock);
- thread__put(th);
}
void machine__remove_thread(struct machine *machine, struct thread *th)