[RFC/PATCH 25/38] perf callchain: Maintain libunwind's address space in map_groups
From: Namhyung Kim
Date: Fri Oct 02 2015 - 01:25:47 EST
Currently the address_space was kept in thread struct but it's more
appropriate to keep it in map_groups as it's maintained throughout
exec's with timestamps. Also we should not flush the address space
after exec since it still can be accessed when used with an indexed
data file.
Cc: Frederic Weisbecker <fweisbec@xxxxxxxxx>
Signed-off-by: Namhyung Kim <namhyung@xxxxxxxxxx>
---
tools/perf/tests/dwarf-unwind.c | 5 +++--
tools/perf/util/map.c | 5 +++++
tools/perf/util/map.h | 1 +
tools/perf/util/thread.c | 7 -------
tools/perf/util/unwind-libunwind.c | 28 +++++++++++++---------------
tools/perf/util/unwind.h | 15 ++++++---------
6 files changed, 28 insertions(+), 33 deletions(-)
diff --git a/tools/perf/tests/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index b9ca0a72fc4d..c3774e0ebcf4 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -143,6 +143,9 @@ int test__dwarf_unwind(void)
struct thread *thread;
int err = -1;
+ /* The record_mode should be set before calling map_groups__init() */
+ callchain_param.record_mode = CALLCHAIN_DWARF;
+
machines__init(&machines);
machine = machines__find(&machines, HOST_KERNEL_ID);
@@ -151,8 +154,6 @@ int test__dwarf_unwind(void)
return -1;
}
- callchain_param.record_mode = CALLCHAIN_DWARF;
-
if (init_live_machine(machine)) {
pr_err("Could not init machine\n");
goto out;
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index c0f8933f29f0..c458a40f8d26 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -14,6 +14,7 @@
#include "util.h"
#include "debug.h"
#include "machine.h"
+#include "unwind.h"
#include <linux/string.h>
static void __maps__insert(struct maps *maps, struct map *map);
@@ -475,6 +476,8 @@ void map_groups__init(struct map_groups *mg, struct machine *machine)
atomic_set(&mg->refcnt, 1);
mg->timestamp = 0;
INIT_LIST_HEAD(&mg->list);
+
+ unwind__prepare_access(mg);
}
static void __maps__purge(struct maps *maps)
@@ -504,6 +507,8 @@ void map_groups__exit(struct map_groups *mg)
for (i = 0; i < MAP__NR_TYPES; ++i)
maps__exit(&mg->maps[i]);
+
+ unwind__finish_access(mg);
}
bool map_groups__empty(struct map_groups *mg)
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 41a9a39f1027..ef3f8b1649ab 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -73,6 +73,7 @@ struct map_groups {
atomic_t refcnt;
u64 timestamp;
struct list_head list;
+ void *priv;
};
struct map_groups *map_groups__new(struct machine *machine);
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 21de681415f4..05aaf7d0ad18 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -107,9 +107,6 @@ struct thread *thread__new(pid_t pid, pid_t tid)
INIT_LIST_HEAD(&thread->comm_list);
INIT_LIST_HEAD(&thread->mg_list);
- if (unwind__prepare_access(thread) < 0)
- goto err_thread;
-
comm_str = malloc(32);
if (!comm_str)
goto err_thread;
@@ -155,7 +152,6 @@ void thread__delete(struct thread *thread)
list_del(&comm->list);
comm__free(comm);
}
- unwind__finish_access(thread);
free(thread);
}
@@ -252,9 +248,6 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
break;
}
list_add_tail(&new->list, &curr->list);
-
- if (exec)
- unwind__flush_access(thread);
}
if (exec) {
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index 5cac2dd68688..5cad1aecf051 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -32,6 +32,7 @@
#include "symbol.h"
#include "util.h"
#include "debug.h"
+#include "map.h"
extern int
UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
@@ -566,7 +567,7 @@ static unw_accessors_t accessors = {
.get_proc_name = get_proc_name,
};
-int unwind__prepare_access(struct thread *thread)
+int unwind__prepare_access(struct map_groups *mg)
{
unw_addr_space_t addr_space;
@@ -580,41 +581,38 @@ int unwind__prepare_access(struct thread *thread)
}
unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL);
- thread__set_priv(thread, addr_space);
+ mg->priv = addr_space;
return 0;
}
-void unwind__flush_access(struct thread *thread)
+void unwind__finish_access(struct map_groups *mg)
{
- unw_addr_space_t addr_space;
+ unw_addr_space_t addr_space = mg->priv;
if (callchain_param.record_mode != CALLCHAIN_DWARF)
return;
- addr_space = thread__priv(thread);
- unw_flush_cache(addr_space, 0, 0);
-}
-
-void unwind__finish_access(struct thread *thread)
-{
- unw_addr_space_t addr_space;
-
- if (callchain_param.record_mode != CALLCHAIN_DWARF)
+ if (addr_space == NULL)
return;
- addr_space = thread__priv(thread);
unw_destroy_addr_space(addr_space);
+ mg->priv = NULL;
}
static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
void *arg, int max_stack)
{
+ struct map_groups *mg;
unw_addr_space_t addr_space;
unw_cursor_t c;
int ret;
- addr_space = thread__priv(ui->thread);
+ mg = thread__get_map_groups(ui->thread, ui->sample->time);
+ if (mg == NULL)
+ return -1;
+
+ addr_space = mg->priv;
if (addr_space == NULL)
return -1;
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index 12790cf94618..c6860b481d07 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -21,17 +21,15 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
/* libunwind specific */
#ifdef HAVE_LIBUNWIND_SUPPORT
int libunwind__arch_reg_id(int regnum);
-int unwind__prepare_access(struct thread *thread);
-void unwind__flush_access(struct thread *thread);
-void unwind__finish_access(struct thread *thread);
+int unwind__prepare_access(struct map_groups *mg);
+void unwind__finish_access(struct map_groups *mg);
#else
-static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
+static inline int unwind__prepare_access(struct map_groups *mg __maybe_unused)
{
return 0;
}
-static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
-static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
+static inline void unwind__finish_access(struct map_groups *mg __maybe_unused) {}
#endif
#else
static inline int
@@ -44,12 +42,11 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
return 0;
}
-static inline int unwind__prepare_access(struct thread *thread __maybe_unused)
+static inline int unwind__prepare_access(struct map_groups *mg __maybe_unused)
{
return 0;
}
-static inline void unwind__flush_access(struct thread *thread __maybe_unused) {}
-static inline void unwind__finish_access(struct thread *thread __maybe_unused) {}
+static inline void unwind__finish_access(struct map_groups *mg __maybe_unused) {}
#endif /* HAVE_DWARF_UNWIND_SUPPORT */
#endif /* __UNWIND_H */
--
2.6.0
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/