summaryrefslogtreecommitdiff
path: root/tools/perf/builtin-kmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/builtin-kmem.c')
-rw-r--r--tools/perf/builtin-kmem.c73
1 files changed, 42 insertions, 31 deletions
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 8ae0a1535293..7929a5fa5f46 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include "builtin.h"
-#include "perf.h"
#include "util/dso.h"
#include "util/evlist.h"
@@ -24,6 +23,7 @@
#include "util/debug.h"
#include "util/string2.h"
+#include "util/util.h"
#include <linux/kernel.h>
#include <linux/numa.h>
@@ -36,7 +36,7 @@
#include <regex.h>
#include <linux/ctype.h>
-#include <traceevent/event-parse.h>
+#include <event-parse.h>
static int kmem_slab;
static int kmem_page;
@@ -399,21 +399,29 @@ static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample)
struct addr_location al;
struct machine *machine = &kmem_session->machines.host;
struct callchain_cursor_node *node;
+ struct callchain_cursor *cursor;
+ u64 result = sample->ip;
+ addr_location__init(&al);
if (alloc_func_list == NULL) {
if (build_alloc_func_list() < 0)
goto out;
}
al.thread = machine__findnew_thread(machine, sample->pid, sample->tid);
- sample__resolve_callchain(sample, &callchain_cursor, NULL, evsel, &al, 16);
- callchain_cursor_commit(&callchain_cursor);
+ cursor = get_tls_callchain_cursor();
+ if (cursor == NULL)
+ goto out;
+
+ sample__resolve_callchain(sample, cursor, NULL, evsel, &al, 16);
+
+ callchain_cursor_commit(cursor);
while (true) {
struct alloc_func key, *caller;
u64 addr;
- node = callchain_cursor_current(&callchain_cursor);
+ node = callchain_cursor_current(cursor);
if (node == NULL)
break;
@@ -423,20 +431,22 @@ static u64 find_callsite(struct evsel *evsel, struct perf_sample *sample)
if (!caller) {
/* found */
if (node->ms.map)
- addr = map__unmap_ip(node->ms.map, node->ip);
+ addr = map__dso_unmap_ip(node->ms.map, node->ip);
else
addr = node->ip;
- return addr;
+ result = addr;
+ goto out;
} else
pr_debug3("skipping alloc function: %s\n", caller->name);
- callchain_cursor_advance(&callchain_cursor);
+ callchain_cursor_advance(cursor);
}
-out:
pr_debug2("unknown callsite: %"PRIx64 "\n", sample->ip);
- return sample->ip;
+out:
+ addr_location__exit(&al);
+ return result;
}
struct sort_dimension {
@@ -653,7 +663,6 @@ static const struct {
{ "__GFP_HIGHMEM", "HM" },
{ "GFP_DMA32", "D32" },
{ "__GFP_HIGH", "H" },
- { "__GFP_ATOMIC", "_A" },
{ "__GFP_IO", "I" },
{ "__GFP_FS", "F" },
{ "__GFP_NOWARN", "NWR" },
@@ -752,6 +761,7 @@ static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample,
};
struct trace_seq seq;
char *str, *pos = NULL;
+ const struct tep_event *tp_format;
if (nr_gfps) {
struct gfp_flag key = {
@@ -763,8 +773,9 @@ static int parse_gfp_flags(struct evsel *evsel, struct perf_sample *sample,
}
trace_seq_init(&seq);
- tep_print_event(evsel->tp_format->tep,
- &seq, &record, "%s", TEP_PRINT_INFO);
+ tp_format = evsel__tp_format(evsel);
+ if (tp_format)
+ tep_print_event(tp_format->tep, &seq, &record, "%s", TEP_PRINT_INFO);
str = strtok_r(seq.buffer, " ", &pos);
while (str) {
@@ -946,7 +957,7 @@ static bool perf_kmem__skip_sample(struct perf_sample *sample)
typedef int (*tracepoint_handler)(struct evsel *evsel,
struct perf_sample *sample);
-static int process_sample_event(struct perf_tool *tool __maybe_unused,
+static int process_sample_event(const struct perf_tool *tool __maybe_unused,
union perf_event *event,
struct perf_sample *sample,
struct evsel *evsel,
@@ -965,7 +976,7 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
if (perf_kmem__skip_sample(sample))
return 0;
- dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
+ dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread__tid(thread));
if (evsel->handler != NULL) {
tracepoint_handler f = evsel->handler;
@@ -977,15 +988,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
return err;
}
-static struct perf_tool perf_kmem = {
- .sample = process_sample_event,
- .comm = perf_event__process_comm,
- .mmap = perf_event__process_mmap,
- .mmap2 = perf_event__process_mmap2,
- .namespaces = perf_event__process_namespaces,
- .ordered_events = true,
-};
-
static double fragmentation(unsigned long n_req, unsigned long n_alloc)
{
if (n_alloc == 0)
@@ -1025,7 +1027,7 @@ static void __print_slab_result(struct rb_root *root,
if (sym != NULL)
snprintf(buf, sizeof(buf), "%s+%" PRIx64 "", sym->name,
- addr - map->unmap_ip(map, sym->start));
+ addr - map__unmap_ip(map, sym->start));
else
snprintf(buf, sizeof(buf), "%#" PRIx64 "", addr);
printf(" %-34s |", buf);
@@ -1399,7 +1401,7 @@ static int __cmd_kmem(struct perf_session *session)
}
evlist__for_each_entry(session->evlist, evsel) {
- if (!strcmp(evsel__name(evsel), "kmem:mm_page_alloc") &&
+ if (evsel__name_is(evsel, "kmem:mm_page_alloc") &&
evsel__field(evsel, "pfn")) {
use_pfn = true;
break;
@@ -1962,6 +1964,7 @@ int cmd_kmem(int argc, const char **argv)
NULL
};
struct perf_session *session;
+ struct perf_tool perf_kmem;
static const char errmsg[] = "No %s allocation events found. Have you run 'perf kmem record --%s'?\n";
int ret = perf_config(kmem_config, NULL);
@@ -1989,6 +1992,13 @@ int cmd_kmem(int argc, const char **argv)
data.path = input_name;
+ perf_tool__init(&perf_kmem, /*ordered_events=*/true);
+ perf_kmem.sample = process_sample_event;
+ perf_kmem.comm = perf_event__process_comm;
+ perf_kmem.mmap = perf_event__process_mmap;
+ perf_kmem.mmap2 = perf_event__process_mmap2;
+ perf_kmem.namespaces = perf_event__process_namespaces;
+
kmem_session = session = perf_session__new(&data, &perf_kmem);
if (IS_ERR(session))
return PTR_ERR(session);
@@ -2004,17 +2014,17 @@ int cmd_kmem(int argc, const char **argv)
if (kmem_page) {
struct evsel *evsel = evlist__find_tracepoint_by_name(session->evlist, "kmem:mm_page_alloc");
+ const struct tep_event *tp_format = evsel ? evsel__tp_format(evsel) : NULL;
- if (evsel == NULL) {
+ if (tp_format == NULL) {
pr_err(errmsg, "page", "page");
goto out_delete;
}
-
- kmem_page_size = tep_get_page_size(evsel->tp_format->tep);
+ kmem_page_size = tep_get_page_size(tp_format->tep);
symbol_conf.use_callchain = true;
}
- symbol__init(&session->header.env);
+ symbol__init(perf_session__env(session));
if (perf_time__parse_str(&ptime, time_str) != 0) {
pr_err("Invalid time string\n");
@@ -2049,7 +2059,8 @@ int cmd_kmem(int argc, const char **argv)
out_delete:
perf_session__delete(session);
+ /* free usage string allocated by parse_options_subcommand */
+ free((void *)kmem_usage[0]);
return ret;
}
-