perf/core improvements and fixes:
. Check maximum frequency rate for record/top, emitting better error messages, from Jiri Olsa. . Disable live kvm command if timerfd is not supported, from David Ahern. . Add usage to 'perf list', from David Ahern. . Fix detection of non-core features, from David Ahern. . Consolidate __hists__add_*entry(), cleanup from Namhyung Kim. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.14 (GNU/Linux) iQIcBAABAgAGBQJSeVA1AAoJENZQFvNTUqpAsz4P/0x7yyXBlJHgf5qyLNvmIKoS V5vVrEfXTpfiDrGSJmPJ+iasUi1caiEV3wKI4tmpZZ5GllNvIHPYQMIbnQgipzQ+ JuVXoLgMe1jnzHuVflVoXhAHrexSpXIBJ27XJaZb9AIy7A1pwqnKDomUP9zn2Mth jzS835nCp/tsA+jcxJ4l8Fwr8XMz7F4aV5/Kp2I6+GDxBXbuAW29eTfBrEmAn9eH jocQq6m0m2f+upSwRWvLr7rlFBVgs1+yQszzq7QydZfb0dyczEPwgKIpJto7JnmR KyuSNFZZ9NArjQP7i1L84i/zA6WFT/shVv3T+8+EEoRMINTyZTZH4y6GSKNev30p hC3nSdGJ8tKVaLOjO7kv/OjQpOR/WfH6CUNKbVXPi1DruZTWQlgGsNczjO0OLpfx NAiy0qo2M8GSgl7uu7FjnpUgiSZgNnBztTUi9me/d5a0ES6ZAhId1EZfVYZ0h+A4 sUsXkrSVst62OiaolSc6GNeosgkvUPl/l6K+Mbbqt3gS2uJlx9jUQ18dwdTLU7NO aBPTujmQdTNgLOEVd7YixpN+3xg/ZSSRNuJbqsJcL8EyXi0bY+3oBvcG87/txI/r 6pnhCV0wFB2KoiSDaHkRtCi8ODvjCB6lwZBIILlybE9U4/qgagwj68IVSaW6o2gF 4cG6ZQHCKK/uA3y2ljsF =CXFq -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: * Check maximum frequency rate for record/top, emitting better error messages, from Jiri Olsa. * Disable live kvm command if timerfd is not supported, from David Ahern. * Add usage to 'perf list', from David Ahern. * Fix detection of non-core features, from David Ahern. * Consolidate __hists__add_*entry(), cleanup from Namhyung Kim. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
83bf9702c8
|
@ -242,7 +242,7 @@ LIB_H += util/cache.h
|
|||
LIB_H += util/callchain.h
|
||||
LIB_H += util/build-id.h
|
||||
LIB_H += util/debug.h
|
||||
LIB_H += util/sysfs.h
|
||||
LIB_H += util/fs.h
|
||||
LIB_H += util/pmu.h
|
||||
LIB_H += util/event.h
|
||||
LIB_H += util/evsel.h
|
||||
|
@ -304,7 +304,7 @@ LIB_OBJS += $(OUTPUT)util/annotate.o
|
|||
LIB_OBJS += $(OUTPUT)util/build-id.o
|
||||
LIB_OBJS += $(OUTPUT)util/config.o
|
||||
LIB_OBJS += $(OUTPUT)util/ctype.o
|
||||
LIB_OBJS += $(OUTPUT)util/sysfs.o
|
||||
LIB_OBJS += $(OUTPUT)util/fs.o
|
||||
LIB_OBJS += $(OUTPUT)util/pmu.o
|
||||
LIB_OBJS += $(OUTPUT)util/environment.o
|
||||
LIB_OBJS += $(OUTPUT)util/event.o
|
||||
|
|
|
@ -65,7 +65,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
|
|||
return 0;
|
||||
}
|
||||
|
||||
he = __hists__add_entry(&evsel->hists, al, NULL, 1, 1, 0);
|
||||
he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL, 1, 1, 0);
|
||||
if (he == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -307,7 +307,8 @@ static int hists__add_entry(struct hists *hists,
|
|||
struct addr_location *al, u64 period,
|
||||
u64 weight, u64 transaction)
|
||||
{
|
||||
if (__hists__add_entry(hists, al, NULL, period, weight, transaction) != NULL)
|
||||
if (__hists__add_entry(hists, al, NULL, NULL, NULL, period, weight,
|
||||
transaction) != NULL)
|
||||
return 0;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,9 @@
|
|||
#include "util/data.h"
|
||||
|
||||
#include <sys/prctl.h>
|
||||
#ifdef HAVE_TIMERFD_SUPPORT
|
||||
#include <sys/timerfd.h>
|
||||
#endif
|
||||
|
||||
#include <termios.h>
|
||||
#include <semaphore.h>
|
||||
|
@ -337,6 +339,7 @@ static void init_kvm_event_record(struct perf_kvm_stat *kvm)
|
|||
INIT_LIST_HEAD(&kvm->kvm_events_cache[i]);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TIMERFD_SUPPORT
|
||||
static void clear_events_cache_stats(struct list_head *kvm_events_cache)
|
||||
{
|
||||
struct list_head *head;
|
||||
|
@ -358,6 +361,7 @@ static void clear_events_cache_stats(struct list_head *kvm_events_cache)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int kvm_events_hash_fn(u64 key)
|
||||
{
|
||||
|
@ -783,6 +787,7 @@ static void print_result(struct perf_kvm_stat *kvm)
|
|||
pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TIMERFD_SUPPORT
|
||||
static int process_lost_event(struct perf_tool *tool,
|
||||
union perf_event *event __maybe_unused,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
|
@ -793,6 +798,7 @@ static int process_lost_event(struct perf_tool *tool,
|
|||
kvm->lost_events++;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool skip_sample(struct perf_kvm_stat *kvm,
|
||||
struct perf_sample *sample)
|
||||
|
@ -872,6 +878,7 @@ static bool verify_vcpu(int vcpu)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef HAVE_TIMERFD_SUPPORT
|
||||
/* keeping the max events to a modest level to keep
|
||||
* the processing of samples per mmap smooth.
|
||||
*/
|
||||
|
@ -1213,6 +1220,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
|
|||
out:
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int read_events(struct perf_kvm_stat *kvm)
|
||||
{
|
||||
|
@ -1379,6 +1387,7 @@ kvm_events_report(struct perf_kvm_stat *kvm, int argc, const char **argv)
|
|||
return kvm_events_report_vcpu(kvm);
|
||||
}
|
||||
|
||||
#ifdef HAVE_TIMERFD_SUPPORT
|
||||
static struct perf_evlist *kvm_live_event_list(void)
|
||||
{
|
||||
struct perf_evlist *evlist;
|
||||
|
@ -1566,6 +1575,7 @@ out:
|
|||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void print_kvm_stat_usage(void)
|
||||
{
|
||||
|
@ -1604,8 +1614,10 @@ static int kvm_cmd_stat(const char *file_name, int argc, const char **argv)
|
|||
if (!strncmp(argv[1], "rep", 3))
|
||||
return kvm_events_report(&kvm, argc - 1 , argv + 1);
|
||||
|
||||
#ifdef HAVE_TIMERFD_SUPPORT
|
||||
if (!strncmp(argv[1], "live", 4))
|
||||
return kvm_events_live(&kvm, argc - 1 , argv + 1);
|
||||
#endif
|
||||
|
||||
perf_stat:
|
||||
return cmd_stat(argc, argv, NULL);
|
||||
|
|
|
@ -14,51 +14,63 @@
|
|||
#include "util/parse-events.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/pmu.h"
|
||||
#include "util/parse-options.h"
|
||||
|
||||
int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
{
|
||||
int i;
|
||||
const struct option list_options[] = {
|
||||
OPT_END()
|
||||
};
|
||||
const char * const list_usage[] = {
|
||||
"perf list [hw|sw|cache|tracepoint|pmu|event_glob]",
|
||||
NULL
|
||||
};
|
||||
|
||||
argc = parse_options(argc, argv, list_options, list_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
||||
setup_pager();
|
||||
|
||||
if (argc == 1)
|
||||
if (argc == 0) {
|
||||
print_events(NULL, false);
|
||||
else {
|
||||
int i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
if (i > 2)
|
||||
putchar('\n');
|
||||
if (strncmp(argv[i], "tracepoint", 10) == 0)
|
||||
print_tracepoint_events(NULL, NULL, false);
|
||||
else if (strcmp(argv[i], "hw") == 0 ||
|
||||
strcmp(argv[i], "hardware") == 0)
|
||||
print_events_type(PERF_TYPE_HARDWARE);
|
||||
else if (strcmp(argv[i], "sw") == 0 ||
|
||||
strcmp(argv[i], "software") == 0)
|
||||
print_events_type(PERF_TYPE_SOFTWARE);
|
||||
else if (strcmp(argv[i], "cache") == 0 ||
|
||||
strcmp(argv[i], "hwcache") == 0)
|
||||
print_hwcache_events(NULL, false);
|
||||
else if (strcmp(argv[i], "pmu") == 0)
|
||||
print_pmu_events(NULL, false);
|
||||
else if (strcmp(argv[i], "--raw-dump") == 0)
|
||||
print_events(NULL, true);
|
||||
else {
|
||||
char *sep = strchr(argv[i], ':'), *s;
|
||||
int sep_idx;
|
||||
for (i = 0; i < argc; ++i) {
|
||||
if (i)
|
||||
putchar('\n');
|
||||
if (strncmp(argv[i], "tracepoint", 10) == 0)
|
||||
print_tracepoint_events(NULL, NULL, false);
|
||||
else if (strcmp(argv[i], "hw") == 0 ||
|
||||
strcmp(argv[i], "hardware") == 0)
|
||||
print_events_type(PERF_TYPE_HARDWARE);
|
||||
else if (strcmp(argv[i], "sw") == 0 ||
|
||||
strcmp(argv[i], "software") == 0)
|
||||
print_events_type(PERF_TYPE_SOFTWARE);
|
||||
else if (strcmp(argv[i], "cache") == 0 ||
|
||||
strcmp(argv[i], "hwcache") == 0)
|
||||
print_hwcache_events(NULL, false);
|
||||
else if (strcmp(argv[i], "pmu") == 0)
|
||||
print_pmu_events(NULL, false);
|
||||
else if (strcmp(argv[i], "--raw-dump") == 0)
|
||||
print_events(NULL, true);
|
||||
else {
|
||||
char *sep = strchr(argv[i], ':'), *s;
|
||||
int sep_idx;
|
||||
|
||||
if (sep == NULL) {
|
||||
print_events(argv[i], false);
|
||||
continue;
|
||||
}
|
||||
sep_idx = sep - argv[i];
|
||||
s = strdup(argv[i]);
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
|
||||
s[sep_idx] = '\0';
|
||||
print_tracepoint_events(s, s + sep_idx + 1, false);
|
||||
free(s);
|
||||
if (sep == NULL) {
|
||||
print_events(argv[i], false);
|
||||
continue;
|
||||
}
|
||||
sep_idx = sep - argv[i];
|
||||
s = strdup(argv[i]);
|
||||
if (s == NULL)
|
||||
return -1;
|
||||
|
||||
s[sep_idx] = '\0';
|
||||
print_tracepoint_events(s, s + sep_idx + 1, false);
|
||||
free(s);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -958,20 +958,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
if (perf_evlist__create_maps(evsel_list, &rec->opts.target) < 0)
|
||||
usage_with_options(record_usage, record_options);
|
||||
|
||||
if (rec->opts.user_interval != ULLONG_MAX)
|
||||
rec->opts.default_interval = rec->opts.user_interval;
|
||||
if (rec->opts.user_freq != UINT_MAX)
|
||||
rec->opts.freq = rec->opts.user_freq;
|
||||
|
||||
/*
|
||||
* User specified count overrides default frequency.
|
||||
*/
|
||||
if (rec->opts.default_interval)
|
||||
rec->opts.freq = 0;
|
||||
else if (rec->opts.freq) {
|
||||
rec->opts.default_interval = rec->opts.freq;
|
||||
} else {
|
||||
ui__error("frequency and count are zero, aborting\n");
|
||||
if (perf_record_opts__config(&rec->opts)) {
|
||||
err = -EINVAL;
|
||||
goto out_free_fd;
|
||||
}
|
||||
|
|
|
@ -115,7 +115,8 @@ static int perf_report__add_mem_hist_entry(struct perf_tool *tool,
|
|||
* and this is indirectly achieved by passing period=weight here
|
||||
* and the he_stat__add_period() function.
|
||||
*/
|
||||
he = __hists__add_mem_entry(&evsel->hists, al, parent, mi, cost, cost);
|
||||
he = __hists__add_entry(&evsel->hists, al, parent, NULL, mi,
|
||||
cost, cost, 0);
|
||||
if (!he)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -200,12 +201,16 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
|
|||
|
||||
err = -ENOMEM;
|
||||
|
||||
/* overwrite the 'al' to branch-to info */
|
||||
al->map = bi[i].to.map;
|
||||
al->sym = bi[i].to.sym;
|
||||
al->addr = bi[i].to.addr;
|
||||
/*
|
||||
* The report shows the percentage of total branches captured
|
||||
* and not events sampled. Thus we use a pseudo period of 1.
|
||||
*/
|
||||
he = __hists__add_branch_entry(&evsel->hists, al, parent,
|
||||
&bi[i], 1, 1);
|
||||
he = __hists__add_entry(&evsel->hists, al, parent, &bi[i], NULL,
|
||||
1, 1, 0);
|
||||
if (he) {
|
||||
struct annotation *notes;
|
||||
bx = he->branch_info;
|
||||
|
@ -266,8 +271,9 @@ static int perf_evsel__add_hist_entry(struct perf_tool *tool,
|
|||
return err;
|
||||
}
|
||||
|
||||
he = __hists__add_entry(&evsel->hists, al, parent, sample->period,
|
||||
sample->weight, sample->transaction);
|
||||
he = __hists__add_entry(&evsel->hists, al, parent, NULL, NULL,
|
||||
sample->period, sample->weight,
|
||||
sample->transaction);
|
||||
if (he == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
|
|
|
@ -246,8 +246,9 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel,
|
|||
struct hist_entry *he;
|
||||
|
||||
pthread_mutex_lock(&evsel->hists.lock);
|
||||
he = __hists__add_entry(&evsel->hists, al, NULL, sample->period,
|
||||
sample->weight, sample->transaction);
|
||||
he = __hists__add_entry(&evsel->hists, al, NULL, NULL, NULL,
|
||||
sample->period, sample->weight,
|
||||
sample->transaction);
|
||||
pthread_mutex_unlock(&evsel->hists.lock);
|
||||
if (he == NULL)
|
||||
return NULL;
|
||||
|
@ -1208,20 +1209,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
|
|||
if (top.delay_secs < 1)
|
||||
top.delay_secs = 1;
|
||||
|
||||
if (opts->user_interval != ULLONG_MAX)
|
||||
opts->default_interval = opts->user_interval;
|
||||
if (opts->user_freq != UINT_MAX)
|
||||
opts->freq = opts->user_freq;
|
||||
|
||||
/*
|
||||
* User specified count overrides default frequency.
|
||||
*/
|
||||
if (opts->default_interval)
|
||||
opts->freq = 0;
|
||||
else if (opts->freq) {
|
||||
opts->default_interval = opts->freq;
|
||||
} else {
|
||||
ui__error("frequency and count are zero, aborting\n");
|
||||
if (perf_record_opts__config(opts)) {
|
||||
status = -EINVAL;
|
||||
goto out_delete_maps;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ endif
|
|||
|
||||
feature_check = $(eval $(feature_check_code))
|
||||
define feature_check_code
|
||||
feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS=$(LDFLAGS) LIBUNWIND_LIBS="$(LIBUNWIND_LIBS)" -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0)
|
||||
feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS)" LDFLAGS="$(LDFLAGS)" LIBUNWIND_LIBS="$(LIBUNWIND_LIBS)" -C config/feature-checks test-$1 >/dev/null 2>/dev/null && echo 1 || echo 0)
|
||||
endef
|
||||
|
||||
feature_set = $(eval $(feature_set_code))
|
||||
|
@ -235,7 +235,7 @@ CFLAGS += -I$(LIB_INCLUDE)
|
|||
CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
|
||||
|
||||
ifndef NO_BIONIC
|
||||
$(feature_check,bionic)
|
||||
$(call feature_check,bionic)
|
||||
ifeq ($(feature-bionic), 1)
|
||||
BIONIC := 1
|
||||
EXTLIBS := $(filter-out -lrt,$(EXTLIBS))
|
||||
|
@ -397,6 +397,13 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
$(call feature_check,timerfd)
|
||||
ifeq ($(feature-timerfd), 1)
|
||||
CFLAGS += -DHAVE_TIMERFD_SUPPORT
|
||||
else
|
||||
msg := $(warning No timerfd support. Disables 'perf kvm stat live');
|
||||
endif
|
||||
|
||||
disable-python = $(eval $(disable-python_code))
|
||||
define disable-python_code
|
||||
CFLAGS += -DNO_LIBPYTHON
|
||||
|
@ -472,15 +479,15 @@ else
|
|||
CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
|
||||
else
|
||||
ifneq ($(feature-libbfd), 1)
|
||||
$(feature_check,liberty)
|
||||
$(call feature_check,liberty)
|
||||
ifeq ($(feature-liberty), 1)
|
||||
EXTLIBS += -lbfd -liberty
|
||||
else
|
||||
$(feature_check,liberty-z)
|
||||
$(call feature_check,liberty-z)
|
||||
ifeq ($(feature-liberty-z), 1)
|
||||
EXTLIBS += -lbfd -liberty -lz
|
||||
else
|
||||
$(feature_check,cplus-demangle)
|
||||
$(call feature_check,cplus-demangle)
|
||||
ifeq ($(feature-cplus-demangle), 1)
|
||||
EXTLIBS += -liberty
|
||||
CFLAGS += -DHAVE_CPLUS_DEMANGLE_SUPPORT
|
||||
|
|
|
@ -25,7 +25,8 @@ FILES= \
|
|||
test-libunwind \
|
||||
test-on-exit \
|
||||
test-stackprotector-all \
|
||||
test-stackprotector
|
||||
test-stackprotector \
|
||||
test-timerfd
|
||||
|
||||
CC := $(CC) -MD
|
||||
|
||||
|
@ -136,6 +137,9 @@ test-on-exit:
|
|||
test-backtrace:
|
||||
$(BUILD)
|
||||
|
||||
test-timerfd:
|
||||
$(BUILD)
|
||||
|
||||
-include *.d
|
||||
|
||||
###############################
|
||||
|
|
|
@ -81,6 +81,10 @@
|
|||
# include "test-libnuma.c"
|
||||
#undef main
|
||||
|
||||
#define main main_test_timerfd
|
||||
# include "test-timerfd.c"
|
||||
#undef main
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
main_test_libpython();
|
||||
|
@ -101,6 +105,7 @@ int main(int argc, char *argv[])
|
|||
main_test_on_exit();
|
||||
main_test_backtrace();
|
||||
main_test_libnuma();
|
||||
main_test_timerfd();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* test for timerfd functions used by perf-kvm-stat-live
|
||||
*/
|
||||
#include <sys/timerfd.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct itimerspec new_value;
|
||||
|
||||
int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
|
||||
if (fd < 0)
|
||||
return 1;
|
||||
|
||||
if (timerfd_settime(fd, 0, &new_value, NULL) != 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
PyMODINIT_FUNC initperf_trace_context(void);
|
||||
|
||||
static PyObject *perf_trace_context_common_pc(PyObject *self, PyObject *args)
|
||||
static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args)
|
||||
{
|
||||
static struct scripting_context *scripting_context;
|
||||
PyObject *context;
|
||||
|
@ -40,7 +40,7 @@ static PyObject *perf_trace_context_common_pc(PyObject *self, PyObject *args)
|
|||
return Py_BuildValue("i", retval);
|
||||
}
|
||||
|
||||
static PyObject *perf_trace_context_common_flags(PyObject *self,
|
||||
static PyObject *perf_trace_context_common_flags(PyObject *obj,
|
||||
PyObject *args)
|
||||
{
|
||||
static struct scripting_context *scripting_context;
|
||||
|
@ -56,7 +56,7 @@ static PyObject *perf_trace_context_common_flags(PyObject *self,
|
|||
return Py_BuildValue("i", retval);
|
||||
}
|
||||
|
||||
static PyObject *perf_trace_context_common_lock_depth(PyObject *self,
|
||||
static PyObject *perf_trace_context_common_lock_depth(PyObject *obj,
|
||||
PyObject *args)
|
||||
{
|
||||
static struct scripting_context *scripting_context;
|
||||
|
|
|
@ -223,7 +223,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
|
|||
goto out;
|
||||
|
||||
he = __hists__add_entry(&evsel->hists, &al, NULL,
|
||||
1, 1, 0);
|
||||
NULL, NULL, 1, 1, 0);
|
||||
if (he == NULL)
|
||||
goto out;
|
||||
|
||||
|
@ -245,8 +245,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
|
|||
&sample) < 0)
|
||||
goto out;
|
||||
|
||||
he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1,
|
||||
0);
|
||||
he = __hists__add_entry(&evsel->hists, &al, NULL,
|
||||
NULL, NULL, 1, 1, 0);
|
||||
if (he == NULL)
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "parse-events.h"
|
||||
#include "evsel.h"
|
||||
#include "evlist.h"
|
||||
#include "sysfs.h"
|
||||
#include "fs.h"
|
||||
#include <lk/debugfs.h>
|
||||
#include "tests.h"
|
||||
#include <linux/hw_breakpoint.h>
|
||||
|
@ -1456,7 +1456,7 @@ static int test_pmu(void)
|
|||
int ret;
|
||||
|
||||
snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/format/",
|
||||
sysfs_find_mountpoint());
|
||||
sysfs__mountpoint());
|
||||
|
||||
ret = stat(path, &st);
|
||||
if (ret)
|
||||
|
@ -1473,7 +1473,7 @@ static int test_pmu_events(void)
|
|||
int ret;
|
||||
|
||||
snprintf(path, PATH_MAX, "%s/bus/event_source/devices/cpu/events/",
|
||||
sysfs_find_mountpoint());
|
||||
sysfs__mountpoint());
|
||||
|
||||
ret = stat(path, &st);
|
||||
if (ret) {
|
||||
|
|
|
@ -21,32 +21,32 @@ struct ui_browser {
|
|||
void *priv;
|
||||
const char *title;
|
||||
char *helpline;
|
||||
unsigned int (*refresh)(struct ui_browser *self);
|
||||
void (*write)(struct ui_browser *self, void *entry, int row);
|
||||
void (*seek)(struct ui_browser *self, off_t offset, int whence);
|
||||
bool (*filter)(struct ui_browser *self, void *entry);
|
||||
unsigned int (*refresh)(struct ui_browser *browser);
|
||||
void (*write)(struct ui_browser *browser, void *entry, int row);
|
||||
void (*seek)(struct ui_browser *browser, off_t offset, int whence);
|
||||
bool (*filter)(struct ui_browser *browser, void *entry);
|
||||
u32 nr_entries;
|
||||
bool navkeypressed;
|
||||
bool use_navkeypressed;
|
||||
};
|
||||
|
||||
int ui_browser__set_color(struct ui_browser *browser, int color);
|
||||
void ui_browser__set_percent_color(struct ui_browser *self,
|
||||
void ui_browser__set_percent_color(struct ui_browser *browser,
|
||||
double percent, bool current);
|
||||
bool ui_browser__is_current_entry(struct ui_browser *self, unsigned row);
|
||||
void ui_browser__refresh_dimensions(struct ui_browser *self);
|
||||
void ui_browser__reset_index(struct ui_browser *self);
|
||||
bool ui_browser__is_current_entry(struct ui_browser *browser, unsigned row);
|
||||
void ui_browser__refresh_dimensions(struct ui_browser *browser);
|
||||
void ui_browser__reset_index(struct ui_browser *browser);
|
||||
|
||||
void ui_browser__gotorc(struct ui_browser *self, int y, int x);
|
||||
void ui_browser__gotorc(struct ui_browser *browser, int y, int x);
|
||||
void ui_browser__write_graph(struct ui_browser *browser, int graph);
|
||||
void __ui_browser__line_arrow(struct ui_browser *browser, unsigned int column,
|
||||
u64 start, u64 end);
|
||||
void __ui_browser__show_title(struct ui_browser *browser, const char *title);
|
||||
void ui_browser__show_title(struct ui_browser *browser, const char *title);
|
||||
int ui_browser__show(struct ui_browser *self, const char *title,
|
||||
int ui_browser__show(struct ui_browser *browser, const char *title,
|
||||
const char *helpline, ...);
|
||||
void ui_browser__hide(struct ui_browser *self);
|
||||
int ui_browser__refresh(struct ui_browser *self);
|
||||
void ui_browser__hide(struct ui_browser *browser);
|
||||
int ui_browser__refresh(struct ui_browser *browser);
|
||||
int ui_browser__run(struct ui_browser *browser, int delay_secs);
|
||||
void ui_browser__update_nr_entries(struct ui_browser *browser, u32 nr_entries);
|
||||
void ui_browser__handle_resize(struct ui_browser *browser);
|
||||
|
@ -63,11 +63,11 @@ int ui_browser__input_window(const char *title, const char *text, char *input,
|
|||
void ui_browser__argv_seek(struct ui_browser *browser, off_t offset, int whence);
|
||||
unsigned int ui_browser__argv_refresh(struct ui_browser *browser);
|
||||
|
||||
void ui_browser__rb_tree_seek(struct ui_browser *self, off_t offset, int whence);
|
||||
unsigned int ui_browser__rb_tree_refresh(struct ui_browser *self);
|
||||
void ui_browser__rb_tree_seek(struct ui_browser *browser, off_t offset, int whence);
|
||||
unsigned int ui_browser__rb_tree_refresh(struct ui_browser *browser);
|
||||
|
||||
void ui_browser__list_head_seek(struct ui_browser *self, off_t offset, int whence);
|
||||
unsigned int ui_browser__list_head_refresh(struct ui_browser *self);
|
||||
void ui_browser__list_head_seek(struct ui_browser *browser, off_t offset, int whence);
|
||||
unsigned int ui_browser__list_head_refresh(struct ui_browser *browser);
|
||||
|
||||
void ui_browser__init(void);
|
||||
void annotate_browser__init(void);
|
||||
|
|
|
@ -1889,7 +1889,7 @@ out:
|
|||
return key;
|
||||
}
|
||||
|
||||
static bool filter_group_entries(struct ui_browser *self __maybe_unused,
|
||||
static bool filter_group_entries(struct ui_browser *browser __maybe_unused,
|
||||
void *entry)
|
||||
{
|
||||
struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
|
||||
|
|
|
@ -18,30 +18,30 @@ struct map_browser {
|
|||
u8 addrlen;
|
||||
};
|
||||
|
||||
static void map_browser__write(struct ui_browser *self, void *nd, int row)
|
||||
static void map_browser__write(struct ui_browser *browser, void *nd, int row)
|
||||
{
|
||||
struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
|
||||
struct map_browser *mb = container_of(self, struct map_browser, b);
|
||||
bool current_entry = ui_browser__is_current_entry(self, row);
|
||||
struct map_browser *mb = container_of(browser, struct map_browser, b);
|
||||
bool current_entry = ui_browser__is_current_entry(browser, row);
|
||||
int width;
|
||||
|
||||
ui_browser__set_percent_color(self, 0, current_entry);
|
||||
ui_browser__set_percent_color(browser, 0, current_entry);
|
||||
slsmg_printf("%*" PRIx64 " %*" PRIx64 " %c ",
|
||||
mb->addrlen, sym->start, mb->addrlen, sym->end,
|
||||
sym->binding == STB_GLOBAL ? 'g' :
|
||||
sym->binding == STB_LOCAL ? 'l' : 'w');
|
||||
width = self->width - ((mb->addrlen * 2) + 4);
|
||||
width = browser->width - ((mb->addrlen * 2) + 4);
|
||||
if (width > 0)
|
||||
slsmg_write_nstring(sym->name, width);
|
||||
}
|
||||
|
||||
/* FIXME uber-kludgy, see comment on cmd_report... */
|
||||
static u32 *symbol__browser_index(struct symbol *self)
|
||||
static u32 *symbol__browser_index(struct symbol *browser)
|
||||
{
|
||||
return ((void *)self) - sizeof(struct rb_node) - sizeof(u32);
|
||||
return ((void *)browser) - sizeof(struct rb_node) - sizeof(u32);
|
||||
}
|
||||
|
||||
static int map_browser__search(struct map_browser *self)
|
||||
static int map_browser__search(struct map_browser *browser)
|
||||
{
|
||||
char target[512];
|
||||
struct symbol *sym;
|
||||
|
@ -53,37 +53,37 @@ static int map_browser__search(struct map_browser *self)
|
|||
|
||||
if (target[0] == '0' && tolower(target[1]) == 'x') {
|
||||
u64 addr = strtoull(target, NULL, 16);
|
||||
sym = map__find_symbol(self->map, addr, NULL);
|
||||
sym = map__find_symbol(browser->map, addr, NULL);
|
||||
} else
|
||||
sym = map__find_symbol_by_name(self->map, target, NULL);
|
||||
sym = map__find_symbol_by_name(browser->map, target, NULL);
|
||||
|
||||
if (sym != NULL) {
|
||||
u32 *idx = symbol__browser_index(sym);
|
||||
|
||||
self->b.top = &sym->rb_node;
|
||||
self->b.index = self->b.top_idx = *idx;
|
||||
browser->b.top = &sym->rb_node;
|
||||
browser->b.index = browser->b.top_idx = *idx;
|
||||
} else
|
||||
ui_helpline__fpush("%s not found!", target);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int map_browser__run(struct map_browser *self)
|
||||
static int map_browser__run(struct map_browser *browser)
|
||||
{
|
||||
int key;
|
||||
|
||||
if (ui_browser__show(&self->b, self->map->dso->long_name,
|
||||
if (ui_browser__show(&browser->b, browser->map->dso->long_name,
|
||||
"Press <- or ESC to exit, %s / to search",
|
||||
verbose ? "" : "restart with -v to use") < 0)
|
||||
return -1;
|
||||
|
||||
while (1) {
|
||||
key = ui_browser__run(&self->b, 0);
|
||||
key = ui_browser__run(&browser->b, 0);
|
||||
|
||||
switch (key) {
|
||||
case '/':
|
||||
if (verbose)
|
||||
map_browser__search(self);
|
||||
map_browser__search(browser);
|
||||
default:
|
||||
break;
|
||||
case K_LEFT:
|
||||
|
@ -94,20 +94,20 @@ static int map_browser__run(struct map_browser *self)
|
|||
}
|
||||
}
|
||||
out:
|
||||
ui_browser__hide(&self->b);
|
||||
ui_browser__hide(&browser->b);
|
||||
return key;
|
||||
}
|
||||
|
||||
int map__browse(struct map *self)
|
||||
int map__browse(struct map *map)
|
||||
{
|
||||
struct map_browser mb = {
|
||||
.b = {
|
||||
.entries = &self->dso->symbols[self->type],
|
||||
.entries = &map->dso->symbols[map->type],
|
||||
.refresh = ui_browser__rb_tree_refresh,
|
||||
.seek = ui_browser__rb_tree_seek,
|
||||
.write = map_browser__write,
|
||||
},
|
||||
.map = self,
|
||||
.map = map,
|
||||
};
|
||||
struct rb_node *nd;
|
||||
char tmp[BITS_PER_LONG / 4];
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
#define _PERF_UI_MAP_BROWSER_H_ 1
|
||||
struct map;
|
||||
|
||||
int map__browse(struct map *self);
|
||||
int map__browse(struct map *map);
|
||||
#endif /* _PERF_UI_MAP_BROWSER_H_ */
|
||||
|
|
|
@ -84,22 +84,22 @@ static void script_browser__write(struct ui_browser *browser,
|
|||
slsmg_write_nstring(sline->line, browser->width);
|
||||
}
|
||||
|
||||
static int script_browser__run(struct perf_script_browser *self)
|
||||
static int script_browser__run(struct perf_script_browser *browser)
|
||||
{
|
||||
int key;
|
||||
|
||||
if (ui_browser__show(&self->b, self->script_name,
|
||||
if (ui_browser__show(&browser->b, browser->script_name,
|
||||
"Press <- or ESC to exit") < 0)
|
||||
return -1;
|
||||
|
||||
while (1) {
|
||||
key = ui_browser__run(&self->b, 0);
|
||||
key = ui_browser__run(&browser->b, 0);
|
||||
|
||||
/* We can add some special key handling here if needed */
|
||||
break;
|
||||
}
|
||||
|
||||
ui_browser__hide(&self->b);
|
||||
ui_browser__hide(&browser->b);
|
||||
return key;
|
||||
}
|
||||
|
||||
|
|
|
@ -213,20 +213,19 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static size_t __callchain__fprintf_flat(FILE *fp,
|
||||
struct callchain_node *self,
|
||||
static size_t __callchain__fprintf_flat(FILE *fp, struct callchain_node *node,
|
||||
u64 total_samples)
|
||||
{
|
||||
struct callchain_list *chain;
|
||||
size_t ret = 0;
|
||||
|
||||
if (!self)
|
||||
if (!node)
|
||||
return 0;
|
||||
|
||||
ret += __callchain__fprintf_flat(fp, self->parent, total_samples);
|
||||
ret += __callchain__fprintf_flat(fp, node->parent, total_samples);
|
||||
|
||||
|
||||
list_for_each_entry(chain, &self->val, list) {
|
||||
list_for_each_entry(chain, &node->val, list) {
|
||||
if (chain->ip >= PERF_CONTEXT_MAX)
|
||||
continue;
|
||||
if (chain->ms.sym)
|
||||
|
@ -239,15 +238,14 @@ static size_t __callchain__fprintf_flat(FILE *fp,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *self,
|
||||
static size_t callchain__fprintf_flat(FILE *fp, struct rb_root *tree,
|
||||
u64 total_samples)
|
||||
{
|
||||
size_t ret = 0;
|
||||
u32 entries_printed = 0;
|
||||
struct rb_node *rb_node;
|
||||
struct callchain_node *chain;
|
||||
struct rb_node *rb_node = rb_first(tree);
|
||||
|
||||
rb_node = rb_first(self);
|
||||
while (rb_node) {
|
||||
double percent;
|
||||
|
||||
|
|
|
@ -10,10 +10,9 @@ extern struct perf_tool build_id__mark_dso_hit_ops;
|
|||
struct dso;
|
||||
|
||||
int build_id__sprintf(const u8 *build_id, int len, char *bf);
|
||||
char *dso__build_id_filename(struct dso *self, char *bf, size_t size);
|
||||
char *dso__build_id_filename(struct dso *dso, char *bf, size_t size);
|
||||
|
||||
int build_id__mark_dso_hit(struct perf_tool *tool, union perf_event *event,
|
||||
struct perf_sample *sample, struct perf_evsel *evsel,
|
||||
struct machine *machine);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#include "util.h"
|
||||
#include "sysfs.h"
|
||||
#include "fs.h"
|
||||
#include "../perf.h"
|
||||
#include "cpumap.h"
|
||||
#include <assert.h>
|
||||
|
@ -216,7 +216,7 @@ int cpu_map__get_socket(struct cpu_map *map, int idx)
|
|||
|
||||
cpu = map->map[idx];
|
||||
|
||||
mnt = sysfs_find_mountpoint();
|
||||
mnt = sysfs__mountpoint();
|
||||
if (!mnt)
|
||||
return -1;
|
||||
|
||||
|
@ -279,7 +279,7 @@ int cpu_map__get_core(struct cpu_map *map, int idx)
|
|||
|
||||
cpu = map->map[idx];
|
||||
|
||||
mnt = sysfs_find_mountpoint();
|
||||
mnt = sysfs__mountpoint();
|
||||
if (!mnt)
|
||||
return -1;
|
||||
|
||||
|
|
|
@ -617,15 +617,15 @@ int perf_event__process(struct perf_tool *tool __maybe_unused,
|
|||
return machine__process_event(machine, event, sample);
|
||||
}
|
||||
|
||||
void thread__find_addr_map(struct thread *self,
|
||||
void thread__find_addr_map(struct thread *thread,
|
||||
struct machine *machine, u8 cpumode,
|
||||
enum map_type type, u64 addr,
|
||||
struct addr_location *al)
|
||||
{
|
||||
struct map_groups *mg = &self->mg;
|
||||
struct map_groups *mg = &thread->mg;
|
||||
bool load_map = false;
|
||||
|
||||
al->thread = self;
|
||||
al->thread = thread;
|
||||
al->addr = addr;
|
||||
al->cpumode = cpumode;
|
||||
al->filtered = false;
|
||||
|
|
|
@ -251,7 +251,8 @@ int perf_event__process(struct perf_tool *tool,
|
|||
struct machine *machine);
|
||||
|
||||
struct addr_location;
|
||||
int perf_event__preprocess_sample(const union perf_event *self,
|
||||
|
||||
int perf_event__preprocess_sample(const union perf_event *event,
|
||||
struct machine *machine,
|
||||
struct addr_location *al,
|
||||
struct perf_sample *sample);
|
||||
|
|
|
@ -88,7 +88,7 @@ struct perf_evsel *perf_evlist__id2evsel(struct perf_evlist *evlist, u64 id);
|
|||
|
||||
struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
|
||||
|
||||
union perf_event *perf_evlist__mmap_read(struct perf_evlist *self, int idx);
|
||||
union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
|
||||
|
||||
void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
|
||||
|
||||
|
@ -99,6 +99,7 @@ void perf_evlist__set_id_pos(struct perf_evlist *evlist);
|
|||
bool perf_can_sample_identifier(void);
|
||||
void perf_evlist__config(struct perf_evlist *evlist,
|
||||
struct perf_record_opts *opts);
|
||||
int perf_record_opts__config(struct perf_record_opts *opts);
|
||||
|
||||
int perf_evlist__prepare_workload(struct perf_evlist *evlist,
|
||||
struct perf_target *target,
|
||||
|
|
|
@ -0,0 +1,119 @@
|
|||
|
||||
/* TODO merge/factor into tools/lib/lk/debugfs.c */
|
||||
|
||||
#include "util.h"
|
||||
#include "util/fs.h"
|
||||
|
||||
static const char * const sysfs__fs_known_mountpoints[] = {
|
||||
"/sys",
|
||||
0,
|
||||
};
|
||||
|
||||
static const char * const procfs__known_mountpoints[] = {
|
||||
"/proc",
|
||||
0,
|
||||
};
|
||||
|
||||
struct fs {
|
||||
const char *name;
|
||||
const char * const *mounts;
|
||||
char path[PATH_MAX + 1];
|
||||
bool found;
|
||||
long magic;
|
||||
};
|
||||
|
||||
enum {
|
||||
FS__SYSFS = 0,
|
||||
FS__PROCFS = 1,
|
||||
};
|
||||
|
||||
static struct fs fs__entries[] = {
|
||||
[FS__SYSFS] = {
|
||||
.name = "sysfs",
|
||||
.mounts = sysfs__fs_known_mountpoints,
|
||||
.magic = SYSFS_MAGIC,
|
||||
},
|
||||
[FS__PROCFS] = {
|
||||
.name = "proc",
|
||||
.mounts = procfs__known_mountpoints,
|
||||
.magic = PROC_SUPER_MAGIC,
|
||||
},
|
||||
};
|
||||
|
||||
static bool fs__read_mounts(struct fs *fs)
|
||||
{
|
||||
bool found = false;
|
||||
char type[100];
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen("/proc/mounts", "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
||||
while (!found &&
|
||||
fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
|
||||
fs->path, type) == 2) {
|
||||
|
||||
if (strcmp(type, fs->name) == 0)
|
||||
found = true;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return fs->found = found;
|
||||
}
|
||||
|
||||
static int fs__valid_mount(const char *fs, long magic)
|
||||
{
|
||||
struct statfs st_fs;
|
||||
|
||||
if (statfs(fs, &st_fs) < 0)
|
||||
return -ENOENT;
|
||||
else if (st_fs.f_type != magic)
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool fs__check_mounts(struct fs *fs)
|
||||
{
|
||||
const char * const *ptr;
|
||||
|
||||
ptr = fs->mounts;
|
||||
while (*ptr) {
|
||||
if (fs__valid_mount(*ptr, fs->magic) == 0) {
|
||||
fs->found = true;
|
||||
strcpy(fs->path, *ptr);
|
||||
return true;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char *fs__get_mountpoint(struct fs *fs)
|
||||
{
|
||||
if (fs__check_mounts(fs))
|
||||
return fs->path;
|
||||
|
||||
return fs__read_mounts(fs) ? fs->path : NULL;
|
||||
}
|
||||
|
||||
static const char *fs__mountpoint(int idx)
|
||||
{
|
||||
struct fs *fs = &fs__entries[idx];
|
||||
|
||||
if (fs->found)
|
||||
return (const char *)fs->path;
|
||||
|
||||
return fs__get_mountpoint(fs);
|
||||
}
|
||||
|
||||
#define FS__MOUNTPOINT(name, idx) \
|
||||
const char *name##__mountpoint(void) \
|
||||
{ \
|
||||
return fs__mountpoint(idx); \
|
||||
}
|
||||
|
||||
FS__MOUNTPOINT(sysfs, FS__SYSFS);
|
||||
FS__MOUNTPOINT(procfs, FS__PROCFS);
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef __PERF_FS
|
||||
#define __PERF_FS
|
||||
|
||||
const char *sysfs__mountpoint(void);
|
||||
const char *procfs__mountpoint(void);
|
||||
|
||||
#endif /* __PERF_FS */
|
|
@ -407,73 +407,12 @@ out:
|
|||
return he;
|
||||
}
|
||||
|
||||
struct hist_entry *__hists__add_mem_entry(struct hists *hists,
|
||||
struct addr_location *al,
|
||||
struct symbol *sym_parent,
|
||||
struct mem_info *mi,
|
||||
u64 period,
|
||||
u64 weight)
|
||||
{
|
||||
struct hist_entry entry = {
|
||||
.thread = al->thread,
|
||||
.comm = thread__comm(al->thread),
|
||||
.ms = {
|
||||
.map = al->map,
|
||||
.sym = al->sym,
|
||||
},
|
||||
.stat = {
|
||||
.period = period,
|
||||
.weight = weight,
|
||||
.nr_events = 1,
|
||||
},
|
||||
.cpu = al->cpu,
|
||||
.ip = al->addr,
|
||||
.level = al->level,
|
||||
.parent = sym_parent,
|
||||
.filtered = symbol__parent_filter(sym_parent),
|
||||
.hists = hists,
|
||||
.mem_info = mi,
|
||||
.branch_info = NULL,
|
||||
};
|
||||
return add_hist_entry(hists, &entry, al, period, weight);
|
||||
}
|
||||
|
||||
struct hist_entry *__hists__add_branch_entry(struct hists *hists,
|
||||
struct addr_location *al,
|
||||
struct symbol *sym_parent,
|
||||
struct branch_info *bi,
|
||||
u64 period,
|
||||
u64 weight)
|
||||
{
|
||||
struct hist_entry entry = {
|
||||
.thread = al->thread,
|
||||
.comm = thread__comm(al->thread),
|
||||
.ms = {
|
||||
.map = bi->to.map,
|
||||
.sym = bi->to.sym,
|
||||
},
|
||||
.cpu = al->cpu,
|
||||
.ip = bi->to.addr,
|
||||
.level = al->level,
|
||||
.stat = {
|
||||
.period = period,
|
||||
.nr_events = 1,
|
||||
.weight = weight,
|
||||
},
|
||||
.parent = sym_parent,
|
||||
.filtered = symbol__parent_filter(sym_parent),
|
||||
.branch_info = bi,
|
||||
.hists = hists,
|
||||
.mem_info = NULL,
|
||||
};
|
||||
|
||||
return add_hist_entry(hists, &entry, al, period, weight);
|
||||
}
|
||||
|
||||
struct hist_entry *__hists__add_entry(struct hists *hists,
|
||||
struct addr_location *al,
|
||||
struct symbol *sym_parent, u64 period,
|
||||
u64 weight, u64 transaction)
|
||||
struct symbol *sym_parent,
|
||||
struct branch_info *bi,
|
||||
struct mem_info *mi,
|
||||
u64 period, u64 weight, u64 transaction)
|
||||
{
|
||||
struct hist_entry entry = {
|
||||
.thread = al->thread,
|
||||
|
@ -486,15 +425,15 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
|
|||
.ip = al->addr,
|
||||
.level = al->level,
|
||||
.stat = {
|
||||
.period = period,
|
||||
.nr_events = 1,
|
||||
.period = period,
|
||||
.weight = weight,
|
||||
},
|
||||
.parent = sym_parent,
|
||||
.filtered = symbol__parent_filter(sym_parent),
|
||||
.hists = hists,
|
||||
.branch_info = NULL,
|
||||
.mem_info = NULL,
|
||||
.branch_info = bi,
|
||||
.mem_info = mi,
|
||||
.transaction = transaction,
|
||||
};
|
||||
|
||||
|
|
|
@ -84,55 +84,43 @@ struct hists {
|
|||
u16 col_len[HISTC_NR_COLS];
|
||||
};
|
||||
|
||||
struct hist_entry *__hists__add_entry(struct hists *self,
|
||||
struct hist_entry *__hists__add_entry(struct hists *hists,
|
||||
struct addr_location *al,
|
||||
struct symbol *parent, u64 period,
|
||||
struct symbol *parent,
|
||||
struct branch_info *bi,
|
||||
struct mem_info *mi, u64 period,
|
||||
u64 weight, u64 transaction);
|
||||
int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
|
||||
int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
|
||||
int hist_entry__transaction_len(void);
|
||||
int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size,
|
||||
int hist_entry__sort_snprintf(struct hist_entry *he, char *bf, size_t size,
|
||||
struct hists *hists);
|
||||
void hist_entry__free(struct hist_entry *);
|
||||
|
||||
struct hist_entry *__hists__add_branch_entry(struct hists *self,
|
||||
struct addr_location *al,
|
||||
struct symbol *sym_parent,
|
||||
struct branch_info *bi,
|
||||
u64 period,
|
||||
u64 weight);
|
||||
|
||||
struct hist_entry *__hists__add_mem_entry(struct hists *self,
|
||||
struct addr_location *al,
|
||||
struct symbol *sym_parent,
|
||||
struct mem_info *mi,
|
||||
u64 period,
|
||||
u64 weight);
|
||||
|
||||
void hists__output_resort(struct hists *self);
|
||||
void hists__collapse_resort(struct hists *self, struct ui_progress *prog);
|
||||
void hists__output_resort(struct hists *hists);
|
||||
void hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
|
||||
|
||||
void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
|
||||
void hists__output_recalc_col_len(struct hists *hists, int max_rows);
|
||||
|
||||
void hists__inc_nr_entries(struct hists *hists, struct hist_entry *h);
|
||||
void hists__inc_nr_events(struct hists *self, u32 type);
|
||||
void hists__inc_nr_events(struct hists *hists, u32 type);
|
||||
void events_stats__inc(struct events_stats *stats, u32 type);
|
||||
size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
|
||||
|
||||
size_t hists__fprintf(struct hists *self, bool show_header, int max_rows,
|
||||
size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
|
||||
int max_cols, float min_pcnt, FILE *fp);
|
||||
|
||||
int hist_entry__inc_addr_samples(struct hist_entry *self, int evidx, u64 addr);
|
||||
int hist_entry__annotate(struct hist_entry *self, size_t privsize);
|
||||
int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
|
||||
int hist_entry__annotate(struct hist_entry *he, size_t privsize);
|
||||
|
||||
void hists__filter_by_dso(struct hists *hists);
|
||||
void hists__filter_by_thread(struct hists *hists);
|
||||
void hists__filter_by_symbol(struct hists *hists);
|
||||
|
||||
u16 hists__col_len(struct hists *self, enum hist_column col);
|
||||
void hists__set_col_len(struct hists *self, enum hist_column col, u16 len);
|
||||
bool hists__new_col_len(struct hists *self, enum hist_column col, u16 len);
|
||||
u16 hists__col_len(struct hists *hists, enum hist_column col);
|
||||
void hists__set_col_len(struct hists *hists, enum hist_column col, u16 len);
|
||||
bool hists__new_col_len(struct hists *hists, enum hist_column col, u16 len);
|
||||
void hists__reset_col_len(struct hists *hists);
|
||||
void hists__calc_col_len(struct hists *hists, struct hist_entry *he);
|
||||
|
||||
|
@ -222,12 +210,9 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist __maybe_unused,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int hist_entry__tui_annotate(struct hist_entry *self
|
||||
__maybe_unused,
|
||||
struct perf_evsel *evsel
|
||||
__maybe_unused,
|
||||
struct hist_browser_timer *hbt
|
||||
__maybe_unused)
|
||||
static inline int hist_entry__tui_annotate(struct hist_entry *he __maybe_unused,
|
||||
struct perf_evsel *evsel __maybe_unused,
|
||||
struct hist_browser_timer *hbt __maybe_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -242,5 +227,5 @@ static inline int script_browse(const char *script_opt __maybe_unused)
|
|||
#define K_SWITCH_INPUT_DATA -3000
|
||||
#endif
|
||||
|
||||
unsigned int hists__sort_list_width(struct hists *self);
|
||||
unsigned int hists__sort_list_width(struct hists *hists);
|
||||
#endif /* __PERF_HIST_H */
|
||||
|
|
|
@ -9,4 +9,8 @@
|
|||
#define SYSFS_MAGIC 0x62656572
|
||||
#endif
|
||||
|
||||
#ifndef PROC_SUPER_MAGIC
|
||||
#define PROC_SUPER_MAGIC 0x9fa0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include "sysfs.h"
|
||||
#include "fs.h"
|
||||
#include "util.h"
|
||||
#include "pmu.h"
|
||||
#include "parse-events.h"
|
||||
|
@ -77,9 +77,8 @@ static int pmu_format(const char *name, struct list_head *format)
|
|||
{
|
||||
struct stat st;
|
||||
char path[PATH_MAX];
|
||||
const char *sysfs;
|
||||
const char *sysfs = sysfs__mountpoint();
|
||||
|
||||
sysfs = sysfs_find_mountpoint();
|
||||
if (!sysfs)
|
||||
return -1;
|
||||
|
||||
|
@ -166,9 +165,8 @@ static int pmu_aliases(const char *name, struct list_head *head)
|
|||
{
|
||||
struct stat st;
|
||||
char path[PATH_MAX];
|
||||
const char *sysfs;
|
||||
const char *sysfs = sysfs__mountpoint();
|
||||
|
||||
sysfs = sysfs_find_mountpoint();
|
||||
if (!sysfs)
|
||||
return -1;
|
||||
|
||||
|
@ -212,11 +210,10 @@ static int pmu_type(const char *name, __u32 *type)
|
|||
{
|
||||
struct stat st;
|
||||
char path[PATH_MAX];
|
||||
const char *sysfs;
|
||||
FILE *file;
|
||||
int ret = 0;
|
||||
const char *sysfs = sysfs__mountpoint();
|
||||
|
||||
sysfs = sysfs_find_mountpoint();
|
||||
if (!sysfs)
|
||||
return -1;
|
||||
|
||||
|
@ -241,11 +238,10 @@ static int pmu_type(const char *name, __u32 *type)
|
|||
static void pmu_read_sysfs(void)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
const char *sysfs;
|
||||
DIR *dir;
|
||||
struct dirent *dent;
|
||||
const char *sysfs = sysfs__mountpoint();
|
||||
|
||||
sysfs = sysfs_find_mountpoint();
|
||||
if (!sysfs)
|
||||
return;
|
||||
|
||||
|
@ -270,11 +266,10 @@ static struct cpu_map *pmu_cpumask(const char *name)
|
|||
{
|
||||
struct stat st;
|
||||
char path[PATH_MAX];
|
||||
const char *sysfs;
|
||||
FILE *file;
|
||||
struct cpu_map *cpus;
|
||||
const char *sysfs = sysfs__mountpoint();
|
||||
|
||||
sysfs = sysfs_find_mountpoint();
|
||||
if (!sysfs)
|
||||
return NULL;
|
||||
|
||||
|
|
|
@ -115,7 +115,7 @@ static const Dwfl_Callbacks offline_callbacks = {
|
|||
};
|
||||
|
||||
/* Get a Dwarf from offline image */
|
||||
static int debuginfo__init_offline_dwarf(struct debuginfo *self,
|
||||
static int debuginfo__init_offline_dwarf(struct debuginfo *dbg,
|
||||
const char *path)
|
||||
{
|
||||
int fd;
|
||||
|
@ -124,25 +124,25 @@ static int debuginfo__init_offline_dwarf(struct debuginfo *self,
|
|||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
self->dwfl = dwfl_begin(&offline_callbacks);
|
||||
if (!self->dwfl)
|
||||
dbg->dwfl = dwfl_begin(&offline_callbacks);
|
||||
if (!dbg->dwfl)
|
||||
goto error;
|
||||
|
||||
self->mod = dwfl_report_offline(self->dwfl, "", "", fd);
|
||||
if (!self->mod)
|
||||
dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd);
|
||||
if (!dbg->mod)
|
||||
goto error;
|
||||
|
||||
self->dbg = dwfl_module_getdwarf(self->mod, &self->bias);
|
||||
if (!self->dbg)
|
||||
dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias);
|
||||
if (!dbg->dbg)
|
||||
goto error;
|
||||
|
||||
return 0;
|
||||
error:
|
||||
if (self->dwfl)
|
||||
dwfl_end(self->dwfl);
|
||||
if (dbg->dwfl)
|
||||
dwfl_end(dbg->dwfl);
|
||||
else
|
||||
close(fd);
|
||||
memset(self, 0, sizeof(*self));
|
||||
memset(dbg, 0, sizeof(*dbg));
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
@ -180,24 +180,24 @@ static const Dwfl_Callbacks kernel_callbacks = {
|
|||
};
|
||||
|
||||
/* Get a Dwarf from live kernel image */
|
||||
static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
|
||||
static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
|
||||
Dwarf_Addr addr)
|
||||
{
|
||||
self->dwfl = dwfl_begin(&kernel_callbacks);
|
||||
if (!self->dwfl)
|
||||
dbg->dwfl = dwfl_begin(&kernel_callbacks);
|
||||
if (!dbg->dwfl)
|
||||
return -EINVAL;
|
||||
|
||||
/* Load the kernel dwarves: Don't care the result here */
|
||||
dwfl_linux_kernel_report_kernel(self->dwfl);
|
||||
dwfl_linux_kernel_report_modules(self->dwfl);
|
||||
dwfl_linux_kernel_report_kernel(dbg->dwfl);
|
||||
dwfl_linux_kernel_report_modules(dbg->dwfl);
|
||||
|
||||
self->dbg = dwfl_addrdwarf(self->dwfl, addr, &self->bias);
|
||||
dbg->dbg = dwfl_addrdwarf(dbg->dwfl, addr, &dbg->bias);
|
||||
/* Here, check whether we could get a real dwarf */
|
||||
if (!self->dbg) {
|
||||
if (!dbg->dbg) {
|
||||
pr_debug("Failed to find kernel dwarf at %lx\n",
|
||||
(unsigned long)addr);
|
||||
dwfl_end(self->dwfl);
|
||||
memset(self, 0, sizeof(*self));
|
||||
dwfl_end(dbg->dwfl);
|
||||
memset(dbg, 0, sizeof(*dbg));
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
|
@ -205,7 +205,7 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
|
|||
}
|
||||
#else
|
||||
/* With older elfutils, this just support kernel module... */
|
||||
static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
|
||||
static int debuginfo__init_online_kernel_dwarf(struct debuginfo *dbg,
|
||||
Dwarf_Addr addr __maybe_unused)
|
||||
{
|
||||
const char *path = kernel_get_module_path("kernel");
|
||||
|
@ -216,44 +216,45 @@ static int debuginfo__init_online_kernel_dwarf(struct debuginfo *self,
|
|||
}
|
||||
|
||||
pr_debug2("Use file %s for debuginfo\n", path);
|
||||
return debuginfo__init_offline_dwarf(self, path);
|
||||
return debuginfo__init_offline_dwarf(dbg, path);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct debuginfo *debuginfo__new(const char *path)
|
||||
{
|
||||
struct debuginfo *self = zalloc(sizeof(struct debuginfo));
|
||||
if (!self)
|
||||
struct debuginfo *dbg = zalloc(sizeof(*dbg));
|
||||
if (!dbg)
|
||||
return NULL;
|
||||
|
||||
if (debuginfo__init_offline_dwarf(self, path) < 0) {
|
||||
free(self);
|
||||
self = NULL;
|
||||
if (debuginfo__init_offline_dwarf(dbg, path) < 0) {
|
||||
free(dbg);
|
||||
dbg = NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
return dbg;
|
||||
}
|
||||
|
||||
struct debuginfo *debuginfo__new_online_kernel(unsigned long addr)
|
||||
{
|
||||
struct debuginfo *self = zalloc(sizeof(struct debuginfo));
|
||||
if (!self)
|
||||
struct debuginfo *dbg = zalloc(sizeof(*dbg));
|
||||
|
||||
if (!dbg)
|
||||
return NULL;
|
||||
|
||||
if (debuginfo__init_online_kernel_dwarf(self, (Dwarf_Addr)addr) < 0) {
|
||||
free(self);
|
||||
self = NULL;
|
||||
if (debuginfo__init_online_kernel_dwarf(dbg, (Dwarf_Addr)addr) < 0) {
|
||||
free(dbg);
|
||||
dbg = NULL;
|
||||
}
|
||||
|
||||
return self;
|
||||
return dbg;
|
||||
}
|
||||
|
||||
void debuginfo__delete(struct debuginfo *self)
|
||||
void debuginfo__delete(struct debuginfo *dbg)
|
||||
{
|
||||
if (self) {
|
||||
if (self->dwfl)
|
||||
dwfl_end(self->dwfl);
|
||||
free(self);
|
||||
if (dbg) {
|
||||
if (dbg->dwfl)
|
||||
dwfl_end(dbg->dwfl);
|
||||
free(dbg);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1083,7 +1084,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data)
|
|||
}
|
||||
|
||||
/* Find probe points from debuginfo */
|
||||
static int debuginfo__find_probes(struct debuginfo *self,
|
||||
static int debuginfo__find_probes(struct debuginfo *dbg,
|
||||
struct probe_finder *pf)
|
||||
{
|
||||
struct perf_probe_point *pp = &pf->pev->point;
|
||||
|
@ -1094,7 +1095,7 @@ static int debuginfo__find_probes(struct debuginfo *self,
|
|||
|
||||
#if _ELFUTILS_PREREQ(0, 142)
|
||||
/* Get the call frame information from this dwarf */
|
||||
pf->cfi = dwarf_getcfi(self->dbg);
|
||||
pf->cfi = dwarf_getcfi(dbg->dbg);
|
||||
#endif
|
||||
|
||||
off = 0;
|
||||
|
@ -1113,7 +1114,7 @@ static int debuginfo__find_probes(struct debuginfo *self,
|
|||
.data = pf,
|
||||
};
|
||||
|
||||
dwarf_getpubnames(self->dbg, pubname_search_cb,
|
||||
dwarf_getpubnames(dbg->dbg, pubname_search_cb,
|
||||
&pubname_param, 0);
|
||||
if (pubname_param.found) {
|
||||
ret = probe_point_search_cb(&pf->sp_die, &probe_param);
|
||||
|
@ -1123,9 +1124,9 @@ static int debuginfo__find_probes(struct debuginfo *self,
|
|||
}
|
||||
|
||||
/* Loop on CUs (Compilation Unit) */
|
||||
while (!dwarf_nextcu(self->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
|
||||
while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
|
||||
/* Get the DIE(Debugging Information Entry) of this CU */
|
||||
diep = dwarf_offdie(self->dbg, off + cuhl, &pf->cu_die);
|
||||
diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die);
|
||||
if (!diep)
|
||||
continue;
|
||||
|
||||
|
@ -1281,13 +1282,13 @@ end:
|
|||
}
|
||||
|
||||
/* Find probe_trace_events specified by perf_probe_event from debuginfo */
|
||||
int debuginfo__find_trace_events(struct debuginfo *self,
|
||||
int debuginfo__find_trace_events(struct debuginfo *dbg,
|
||||
struct perf_probe_event *pev,
|
||||
struct probe_trace_event **tevs, int max_tevs)
|
||||
{
|
||||
struct trace_event_finder tf = {
|
||||
.pf = {.pev = pev, .callback = add_probe_trace_event},
|
||||
.mod = self->mod, .max_tevs = max_tevs};
|
||||
.mod = dbg->mod, .max_tevs = max_tevs};
|
||||
int ret;
|
||||
|
||||
/* Allocate result tevs array */
|
||||
|
@ -1298,7 +1299,7 @@ int debuginfo__find_trace_events(struct debuginfo *self,
|
|||
tf.tevs = *tevs;
|
||||
tf.ntevs = 0;
|
||||
|
||||
ret = debuginfo__find_probes(self, &tf.pf);
|
||||
ret = debuginfo__find_probes(dbg, &tf.pf);
|
||||
if (ret < 0) {
|
||||
free(*tevs);
|
||||
*tevs = NULL;
|
||||
|
@ -1389,14 +1390,14 @@ out:
|
|||
}
|
||||
|
||||
/* Find available variables at given probe point */
|
||||
int debuginfo__find_available_vars_at(struct debuginfo *self,
|
||||
int debuginfo__find_available_vars_at(struct debuginfo *dbg,
|
||||
struct perf_probe_event *pev,
|
||||
struct variable_list **vls,
|
||||
int max_vls, bool externs)
|
||||
{
|
||||
struct available_var_finder af = {
|
||||
.pf = {.pev = pev, .callback = add_available_vars},
|
||||
.mod = self->mod,
|
||||
.mod = dbg->mod,
|
||||
.max_vls = max_vls, .externs = externs};
|
||||
int ret;
|
||||
|
||||
|
@ -1408,7 +1409,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self,
|
|||
af.vls = *vls;
|
||||
af.nvls = 0;
|
||||
|
||||
ret = debuginfo__find_probes(self, &af.pf);
|
||||
ret = debuginfo__find_probes(dbg, &af.pf);
|
||||
if (ret < 0) {
|
||||
/* Free vlist for error */
|
||||
while (af.nvls--) {
|
||||
|
@ -1426,7 +1427,7 @@ int debuginfo__find_available_vars_at(struct debuginfo *self,
|
|||
}
|
||||
|
||||
/* Reverse search */
|
||||
int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
|
||||
int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
|
||||
struct perf_probe_point *ppt)
|
||||
{
|
||||
Dwarf_Die cudie, spdie, indie;
|
||||
|
@ -1435,10 +1436,10 @@ int debuginfo__find_probe_point(struct debuginfo *self, unsigned long addr,
|
|||
int baseline = 0, lineno = 0, ret = 0;
|
||||
|
||||
/* Adjust address with bias */
|
||||
addr += self->bias;
|
||||
addr += dbg->bias;
|
||||
|
||||
/* Find cu die */
|
||||
if (!dwarf_addrdie(self->dbg, (Dwarf_Addr)addr - self->bias, &cudie)) {
|
||||
if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr - dbg->bias, &cudie)) {
|
||||
pr_warning("Failed to find debug information for address %lx\n",
|
||||
addr);
|
||||
ret = -EINVAL;
|
||||
|
@ -1639,7 +1640,7 @@ static int find_line_range_by_func(struct line_finder *lf)
|
|||
return param.retval;
|
||||
}
|
||||
|
||||
int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
|
||||
int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr)
|
||||
{
|
||||
struct line_finder lf = {.lr = lr, .found = 0};
|
||||
int ret = 0;
|
||||
|
@ -1656,7 +1657,7 @@ int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
|
|||
struct dwarf_callback_param line_range_param = {
|
||||
.data = (void *)&lf, .retval = 0};
|
||||
|
||||
dwarf_getpubnames(self->dbg, pubname_search_cb,
|
||||
dwarf_getpubnames(dbg->dbg, pubname_search_cb,
|
||||
&pubname_param, 0);
|
||||
if (pubname_param.found) {
|
||||
line_range_search_cb(&lf.sp_die, &line_range_param);
|
||||
|
@ -1667,12 +1668,12 @@ int debuginfo__find_line_range(struct debuginfo *self, struct line_range *lr)
|
|||
|
||||
/* Loop on CUs (Compilation Unit) */
|
||||
while (!lf.found && ret >= 0) {
|
||||
if (dwarf_nextcu(self->dbg, off, &noff, &cuhl,
|
||||
if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl,
|
||||
NULL, NULL, NULL) != 0)
|
||||
break;
|
||||
|
||||
/* Get the DIE(Debugging Information Entry) of this CU */
|
||||
diep = dwarf_offdie(self->dbg, off + cuhl, &lf.cu_die);
|
||||
diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die);
|
||||
if (!diep)
|
||||
continue;
|
||||
|
||||
|
|
|
@ -31,25 +31,25 @@ struct debuginfo {
|
|||
|
||||
extern struct debuginfo *debuginfo__new(const char *path);
|
||||
extern struct debuginfo *debuginfo__new_online_kernel(unsigned long addr);
|
||||
extern void debuginfo__delete(struct debuginfo *self);
|
||||
extern void debuginfo__delete(struct debuginfo *dbg);
|
||||
|
||||
/* Find probe_trace_events specified by perf_probe_event from debuginfo */
|
||||
extern int debuginfo__find_trace_events(struct debuginfo *self,
|
||||
extern int debuginfo__find_trace_events(struct debuginfo *dbg,
|
||||
struct perf_probe_event *pev,
|
||||
struct probe_trace_event **tevs,
|
||||
int max_tevs);
|
||||
|
||||
/* Find a perf_probe_point from debuginfo */
|
||||
extern int debuginfo__find_probe_point(struct debuginfo *self,
|
||||
extern int debuginfo__find_probe_point(struct debuginfo *dbg,
|
||||
unsigned long addr,
|
||||
struct perf_probe_point *ppt);
|
||||
|
||||
/* Find a line range */
|
||||
extern int debuginfo__find_line_range(struct debuginfo *self,
|
||||
extern int debuginfo__find_line_range(struct debuginfo *dbg,
|
||||
struct line_range *lr);
|
||||
|
||||
/* Find available variables */
|
||||
extern int debuginfo__find_available_vars_at(struct debuginfo *self,
|
||||
extern int debuginfo__find_available_vars_at(struct debuginfo *dbg,
|
||||
struct perf_probe_event *pev,
|
||||
struct variable_list **vls,
|
||||
int max_points, bool externs);
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
|
||||
struct pstack;
|
||||
struct pstack *pstack__new(unsigned short max_nr_entries);
|
||||
void pstack__delete(struct pstack *self);
|
||||
bool pstack__empty(const struct pstack *self);
|
||||
void pstack__remove(struct pstack *self, void *key);
|
||||
void pstack__push(struct pstack *self, void *key);
|
||||
void *pstack__pop(struct pstack *self);
|
||||
void pstack__delete(struct pstack *pstack);
|
||||
bool pstack__empty(const struct pstack *pstack);
|
||||
void pstack__remove(struct pstack *pstack, void *key);
|
||||
void pstack__push(struct pstack *pstack, void *key);
|
||||
void *pstack__pop(struct pstack *pstack);
|
||||
|
||||
#endif /* _PERF_PSTACK_ */
|
||||
|
|
|
@ -17,5 +17,5 @@ util/xyarray.c
|
|||
util/cgroup.c
|
||||
util/rblist.c
|
||||
util/strlist.c
|
||||
util/sysfs.c
|
||||
util/fs.c
|
||||
../../lib/rbtree.c
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "evsel.h"
|
||||
#include "cpumap.h"
|
||||
#include "parse-events.h"
|
||||
#include "fs.h"
|
||||
#include "util.h"
|
||||
|
||||
typedef void (*setup_probe_fn_t)(struct perf_evsel *evsel);
|
||||
|
||||
|
@ -106,3 +108,72 @@ void perf_evlist__config(struct perf_evlist *evlist,
|
|||
|
||||
perf_evlist__set_id_pos(evlist);
|
||||
}
|
||||
|
||||
static int get_max_rate(unsigned int *rate)
|
||||
{
|
||||
char path[PATH_MAX];
|
||||
const char *procfs = procfs__mountpoint();
|
||||
|
||||
if (!procfs)
|
||||
return -1;
|
||||
|
||||
snprintf(path, PATH_MAX,
|
||||
"%s/sys/kernel/perf_event_max_sample_rate", procfs);
|
||||
|
||||
return filename__read_int(path, (int *) rate);
|
||||
}
|
||||
|
||||
static int perf_record_opts__config_freq(struct perf_record_opts *opts)
|
||||
{
|
||||
bool user_freq = opts->user_freq != UINT_MAX;
|
||||
unsigned int max_rate;
|
||||
|
||||
if (opts->user_interval != ULLONG_MAX)
|
||||
opts->default_interval = opts->user_interval;
|
||||
if (user_freq)
|
||||
opts->freq = opts->user_freq;
|
||||
|
||||
/*
|
||||
* User specified count overrides default frequency.
|
||||
*/
|
||||
if (opts->default_interval)
|
||||
opts->freq = 0;
|
||||
else if (opts->freq) {
|
||||
opts->default_interval = opts->freq;
|
||||
} else {
|
||||
pr_err("frequency and count are zero, aborting\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_max_rate(&max_rate))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* User specified frequency is over current maximum.
|
||||
*/
|
||||
if (user_freq && (max_rate < opts->freq)) {
|
||||
pr_err("Maximum frequency rate (%u) reached.\n"
|
||||
"Please use -F freq option with lower value or consider\n"
|
||||
"tweaking /proc/sys/kernel/perf_event_max_sample_rate.\n",
|
||||
max_rate);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Default frequency is over current maximum.
|
||||
*/
|
||||
if (max_rate < opts->freq) {
|
||||
pr_warning("Lowering default frequency rate to %u.\n"
|
||||
"Please consider tweaking "
|
||||
"/proc/sys/kernel/perf_event_max_sample_rate.\n",
|
||||
max_rate);
|
||||
opts->freq = max_rate;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int perf_record_opts__config(struct perf_record_opts *opts)
|
||||
{
|
||||
return perf_record_opts__config_freq(opts);
|
||||
}
|
||||
|
|
|
@ -16,11 +16,11 @@
|
|||
#include "perf_regs.h"
|
||||
#include "vdso.h"
|
||||
|
||||
static int perf_session__open(struct perf_session *self)
|
||||
static int perf_session__open(struct perf_session *session)
|
||||
{
|
||||
struct perf_data_file *file = self->file;
|
||||
struct perf_data_file *file = session->file;
|
||||
|
||||
if (perf_session__read_header(self) < 0) {
|
||||
if (perf_session__read_header(session) < 0) {
|
||||
pr_err("incompatible file format (rerun with -v to learn more)");
|
||||
return -1;
|
||||
}
|
||||
|
@ -28,17 +28,17 @@ static int perf_session__open(struct perf_session *self)
|
|||
if (perf_data_file__is_pipe(file))
|
||||
return 0;
|
||||
|
||||
if (!perf_evlist__valid_sample_type(self->evlist)) {
|
||||
if (!perf_evlist__valid_sample_type(session->evlist)) {
|
||||
pr_err("non matching sample_type");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!perf_evlist__valid_sample_id_all(self->evlist)) {
|
||||
if (!perf_evlist__valid_sample_id_all(session->evlist)) {
|
||||
pr_err("non matching sample_id_all");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!perf_evlist__valid_read_format(self->evlist)) {
|
||||
if (!perf_evlist__valid_read_format(session->evlist)) {
|
||||
pr_err("non matching read_format");
|
||||
return -1;
|
||||
}
|
||||
|
@ -53,46 +53,45 @@ void perf_session__set_id_hdr_size(struct perf_session *session)
|
|||
machines__set_id_hdr_size(&session->machines, id_hdr_size);
|
||||
}
|
||||
|
||||
int perf_session__create_kernel_maps(struct perf_session *self)
|
||||
int perf_session__create_kernel_maps(struct perf_session *session)
|
||||
{
|
||||
int ret = machine__create_kernel_maps(&self->machines.host);
|
||||
int ret = machine__create_kernel_maps(&session->machines.host);
|
||||
|
||||
if (ret >= 0)
|
||||
ret = machines__create_guest_kernel_maps(&self->machines);
|
||||
ret = machines__create_guest_kernel_maps(&session->machines);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void perf_session__destroy_kernel_maps(struct perf_session *self)
|
||||
static void perf_session__destroy_kernel_maps(struct perf_session *session)
|
||||
{
|
||||
machines__destroy_kernel_maps(&self->machines);
|
||||
machines__destroy_kernel_maps(&session->machines);
|
||||
}
|
||||
|
||||
struct perf_session *perf_session__new(struct perf_data_file *file,
|
||||
bool repipe, struct perf_tool *tool)
|
||||
{
|
||||
struct perf_session *self;
|
||||
struct perf_session *session = zalloc(sizeof(*session));
|
||||
|
||||
self = zalloc(sizeof(*self));
|
||||
if (!self)
|
||||
if (!session)
|
||||
goto out;
|
||||
|
||||
self->repipe = repipe;
|
||||
INIT_LIST_HEAD(&self->ordered_samples.samples);
|
||||
INIT_LIST_HEAD(&self->ordered_samples.sample_cache);
|
||||
INIT_LIST_HEAD(&self->ordered_samples.to_free);
|
||||
machines__init(&self->machines);
|
||||
session->repipe = repipe;
|
||||
INIT_LIST_HEAD(&session->ordered_samples.samples);
|
||||
INIT_LIST_HEAD(&session->ordered_samples.sample_cache);
|
||||
INIT_LIST_HEAD(&session->ordered_samples.to_free);
|
||||
machines__init(&session->machines);
|
||||
|
||||
if (file) {
|
||||
if (perf_data_file__open(file))
|
||||
goto out_delete;
|
||||
|
||||
self->file = file;
|
||||
session->file = file;
|
||||
|
||||
if (perf_data_file__is_read(file)) {
|
||||
if (perf_session__open(self) < 0)
|
||||
if (perf_session__open(session) < 0)
|
||||
goto out_close;
|
||||
|
||||
perf_session__set_id_hdr_size(self);
|
||||
perf_session__set_id_hdr_size(session);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,22 +100,22 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
|
|||
* In O_RDONLY mode this will be performed when reading the
|
||||
* kernel MMAP event, in perf_event__process_mmap().
|
||||
*/
|
||||
if (perf_session__create_kernel_maps(self) < 0)
|
||||
if (perf_session__create_kernel_maps(session) < 0)
|
||||
goto out_delete;
|
||||
}
|
||||
|
||||
if (tool && tool->ordering_requires_timestamps &&
|
||||
tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) {
|
||||
tool->ordered_samples && !perf_evlist__sample_id_all(session->evlist)) {
|
||||
dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
|
||||
tool->ordered_samples = false;
|
||||
}
|
||||
|
||||
return self;
|
||||
return session;
|
||||
|
||||
out_close:
|
||||
perf_data_file__close(file);
|
||||
out_delete:
|
||||
perf_session__delete(self);
|
||||
perf_session__delete(session);
|
||||
out:
|
||||
return NULL;
|
||||
}
|
||||
|
@ -147,16 +146,16 @@ static void perf_session_env__delete(struct perf_session_env *env)
|
|||
free(env->pmu_mappings);
|
||||
}
|
||||
|
||||
void perf_session__delete(struct perf_session *self)
|
||||
void perf_session__delete(struct perf_session *session)
|
||||
{
|
||||
perf_session__destroy_kernel_maps(self);
|
||||
perf_session__delete_dead_threads(self);
|
||||
perf_session__delete_threads(self);
|
||||
perf_session_env__delete(&self->header.env);
|
||||
machines__exit(&self->machines);
|
||||
if (self->file)
|
||||
perf_data_file__close(self->file);
|
||||
free(self);
|
||||
perf_session__destroy_kernel_maps(session);
|
||||
perf_session__delete_dead_threads(session);
|
||||
perf_session__delete_threads(session);
|
||||
perf_session_env__delete(&session->header.env);
|
||||
machines__exit(&session->machines);
|
||||
if (session->file)
|
||||
perf_data_file__close(session->file);
|
||||
free(session);
|
||||
vdso__exit();
|
||||
}
|
||||
|
||||
|
@ -1084,11 +1083,11 @@ static int perf_session__process_event(struct perf_session *session,
|
|||
file_offset);
|
||||
}
|
||||
|
||||
void perf_event_header__bswap(struct perf_event_header *self)
|
||||
void perf_event_header__bswap(struct perf_event_header *hdr)
|
||||
{
|
||||
self->type = bswap_32(self->type);
|
||||
self->misc = bswap_16(self->misc);
|
||||
self->size = bswap_16(self->size);
|
||||
hdr->type = bswap_32(hdr->type);
|
||||
hdr->misc = bswap_16(hdr->misc);
|
||||
hdr->size = bswap_16(hdr->size);
|
||||
}
|
||||
|
||||
struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
|
||||
|
@ -1096,9 +1095,9 @@ struct thread *perf_session__findnew(struct perf_session *session, pid_t pid)
|
|||
return machine__findnew_thread(&session->machines.host, 0, pid);
|
||||
}
|
||||
|
||||
static struct thread *perf_session__register_idle_thread(struct perf_session *self)
|
||||
static struct thread *perf_session__register_idle_thread(struct perf_session *session)
|
||||
{
|
||||
struct thread *thread = perf_session__findnew(self, 0);
|
||||
struct thread *thread = perf_session__findnew(session, 0);
|
||||
|
||||
if (thread == NULL || thread__set_comm(thread, "swapper", 0)) {
|
||||
pr_err("problem inserting idle task.\n");
|
||||
|
@ -1150,10 +1149,10 @@ static void perf_session__warn_about_errors(const struct perf_session *session,
|
|||
|
||||
volatile int session_done;
|
||||
|
||||
static int __perf_session__process_pipe_events(struct perf_session *self,
|
||||
static int __perf_session__process_pipe_events(struct perf_session *session,
|
||||
struct perf_tool *tool)
|
||||
{
|
||||
int fd = perf_data_file__fd(self->file);
|
||||
int fd = perf_data_file__fd(session->file);
|
||||
union perf_event *event;
|
||||
uint32_t size, cur_size = 0;
|
||||
void *buf = NULL;
|
||||
|
@ -1181,7 +1180,7 @@ more:
|
|||
goto out_err;
|
||||
}
|
||||
|
||||
if (self->header.needs_swap)
|
||||
if (session->header.needs_swap)
|
||||
perf_event_header__bswap(&event->header);
|
||||
|
||||
size = event->header.size;
|
||||
|
@ -1216,7 +1215,7 @@ more:
|
|||
}
|
||||
}
|
||||
|
||||
if ((skip = perf_session__process_event(self, event, tool, head)) < 0) {
|
||||
if ((skip = perf_session__process_event(session, event, tool, head)) < 0) {
|
||||
pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
|
||||
head, event->header.size, event->header.type);
|
||||
err = -EINVAL;
|
||||
|
@ -1232,12 +1231,12 @@ more:
|
|||
goto more;
|
||||
done:
|
||||
/* do the final flush for ordered samples */
|
||||
self->ordered_samples.next_flush = ULLONG_MAX;
|
||||
err = flush_sample_queue(self, tool);
|
||||
session->ordered_samples.next_flush = ULLONG_MAX;
|
||||
err = flush_sample_queue(session, tool);
|
||||
out_err:
|
||||
free(buf);
|
||||
perf_session__warn_about_errors(self, tool);
|
||||
perf_session_free_sample_buffers(self);
|
||||
perf_session__warn_about_errors(session, tool);
|
||||
perf_session_free_sample_buffers(session);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1377,22 +1376,22 @@ out_err:
|
|||
return err;
|
||||
}
|
||||
|
||||
int perf_session__process_events(struct perf_session *self,
|
||||
int perf_session__process_events(struct perf_session *session,
|
||||
struct perf_tool *tool)
|
||||
{
|
||||
u64 size = perf_data_file__size(self->file);
|
||||
u64 size = perf_data_file__size(session->file);
|
||||
int err;
|
||||
|
||||
if (perf_session__register_idle_thread(self) == NULL)
|
||||
if (perf_session__register_idle_thread(session) == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!perf_data_file__is_pipe(self->file))
|
||||
err = __perf_session__process_events(self,
|
||||
self->header.data_offset,
|
||||
self->header.data_size,
|
||||
if (!perf_data_file__is_pipe(session->file))
|
||||
err = __perf_session__process_events(session,
|
||||
session->header.data_offset,
|
||||
session->header.data_size,
|
||||
size, tool);
|
||||
else
|
||||
err = __perf_session__process_pipe_events(self, tool);
|
||||
err = __perf_session__process_pipe_events(session, tool);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -1441,15 +1440,15 @@ int maps__set_kallsyms_ref_reloc_sym(struct map **maps,
|
|||
return 0;
|
||||
}
|
||||
|
||||
size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp)
|
||||
size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp)
|
||||
{
|
||||
return machines__fprintf_dsos(&self->machines, fp);
|
||||
return machines__fprintf_dsos(&session->machines, fp);
|
||||
}
|
||||
|
||||
size_t perf_session__fprintf_dsos_buildid(struct perf_session *self, FILE *fp,
|
||||
size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
|
||||
bool (skip)(struct dso *dso, int parm), int parm)
|
||||
{
|
||||
return machines__fprintf_dsos_buildid(&self->machines, fp, skip, parm);
|
||||
return machines__fprintf_dsos_buildid(&session->machines, fp, skip, parm);
|
||||
}
|
||||
|
||||
size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
|
||||
|
|
|
@ -51,12 +51,12 @@ struct perf_session *perf_session__new(struct perf_data_file *file,
|
|||
bool repipe, struct perf_tool *tool);
|
||||
void perf_session__delete(struct perf_session *session);
|
||||
|
||||
void perf_event_header__bswap(struct perf_event_header *self);
|
||||
void perf_event_header__bswap(struct perf_event_header *hdr);
|
||||
|
||||
int __perf_session__process_events(struct perf_session *self,
|
||||
int __perf_session__process_events(struct perf_session *session,
|
||||
u64 data_offset, u64 data_size, u64 size,
|
||||
struct perf_tool *tool);
|
||||
int perf_session__process_events(struct perf_session *self,
|
||||
int perf_session__process_events(struct perf_session *session,
|
||||
struct perf_tool *tool);
|
||||
|
||||
int perf_session_queue_event(struct perf_session *s, union perf_event *event,
|
||||
|
@ -64,37 +64,38 @@ int perf_session_queue_event(struct perf_session *s, union perf_event *event,
|
|||
|
||||
void perf_tool__fill_defaults(struct perf_tool *tool);
|
||||
|
||||
int perf_session__resolve_callchain(struct perf_session *self, struct perf_evsel *evsel,
|
||||
int perf_session__resolve_callchain(struct perf_session *session,
|
||||
struct perf_evsel *evsel,
|
||||
struct thread *thread,
|
||||
struct ip_callchain *chain,
|
||||
struct symbol **parent);
|
||||
|
||||
bool perf_session__has_traces(struct perf_session *self, const char *msg);
|
||||
bool perf_session__has_traces(struct perf_session *session, const char *msg);
|
||||
|
||||
void mem_bswap_64(void *src, int byte_size);
|
||||
void mem_bswap_32(void *src, int byte_size);
|
||||
void perf_event__attr_swap(struct perf_event_attr *attr);
|
||||
|
||||
int perf_session__create_kernel_maps(struct perf_session *self);
|
||||
int perf_session__create_kernel_maps(struct perf_session *session);
|
||||
|
||||
void perf_session__set_id_hdr_size(struct perf_session *session);
|
||||
|
||||
static inline
|
||||
struct machine *perf_session__find_machine(struct perf_session *self, pid_t pid)
|
||||
struct machine *perf_session__find_machine(struct perf_session *session, pid_t pid)
|
||||
{
|
||||
return machines__find(&self->machines, pid);
|
||||
return machines__find(&session->machines, pid);
|
||||
}
|
||||
|
||||
static inline
|
||||
struct machine *perf_session__findnew_machine(struct perf_session *self, pid_t pid)
|
||||
struct machine *perf_session__findnew_machine(struct perf_session *session, pid_t pid)
|
||||
{
|
||||
return machines__findnew(&self->machines, pid);
|
||||
return machines__findnew(&session->machines, pid);
|
||||
}
|
||||
|
||||
struct thread *perf_session__findnew(struct perf_session *self, pid_t pid);
|
||||
size_t perf_session__fprintf(struct perf_session *self, FILE *fp);
|
||||
struct thread *perf_session__findnew(struct perf_session *session, pid_t pid);
|
||||
size_t perf_session__fprintf(struct perf_session *session, FILE *fp);
|
||||
|
||||
size_t perf_session__fprintf_dsos(struct perf_session *self, FILE *fp);
|
||||
size_t perf_session__fprintf_dsos(struct perf_session *session, FILE *fp);
|
||||
|
||||
size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fp,
|
||||
bool (fn)(struct dso *dso, int parm), int parm);
|
||||
|
|
|
@ -180,7 +180,7 @@ struct sort_entry {
|
|||
|
||||
int64_t (*se_cmp)(struct hist_entry *, struct hist_entry *);
|
||||
int64_t (*se_collapse)(struct hist_entry *, struct hist_entry *);
|
||||
int (*se_snprintf)(struct hist_entry *self, char *bf, size_t size,
|
||||
int (*se_snprintf)(struct hist_entry *he, char *bf, size_t size,
|
||||
unsigned int width);
|
||||
u8 se_width_idx;
|
||||
bool elide;
|
||||
|
|
|
@ -62,15 +62,15 @@ static struct strfilter_node *strfilter_node__alloc(const char *op,
|
|||
struct strfilter_node *l,
|
||||
struct strfilter_node *r)
|
||||
{
|
||||
struct strfilter_node *ret = zalloc(sizeof(struct strfilter_node));
|
||||
struct strfilter_node *node = zalloc(sizeof(*node));
|
||||
|
||||
if (ret) {
|
||||
ret->p = op;
|
||||
ret->l = l;
|
||||
ret->r = r;
|
||||
if (node) {
|
||||
node->p = op;
|
||||
node->l = l;
|
||||
node->r = r;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return node;
|
||||
}
|
||||
|
||||
static struct strfilter_node *strfilter_node__new(const char *s,
|
||||
|
@ -154,20 +154,20 @@ error:
|
|||
*/
|
||||
struct strfilter *strfilter__new(const char *rules, const char **err)
|
||||
{
|
||||
struct strfilter *ret = zalloc(sizeof(struct strfilter));
|
||||
struct strfilter *filter = zalloc(sizeof(*filter));
|
||||
const char *ep = NULL;
|
||||
|
||||
if (ret)
|
||||
ret->root = strfilter_node__new(rules, &ep);
|
||||
if (filter)
|
||||
filter->root = strfilter_node__new(rules, &ep);
|
||||
|
||||
if (!ret || !ret->root || *ep != '\0') {
|
||||
if (!filter || !filter->root || *ep != '\0') {
|
||||
if (err)
|
||||
*err = ep;
|
||||
strfilter__delete(ret);
|
||||
ret = NULL;
|
||||
strfilter__delete(filter);
|
||||
filter = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
return filter;
|
||||
}
|
||||
|
||||
static bool strfilter_node__compare(struct strfilter_node *node,
|
||||
|
@ -191,9 +191,9 @@ static bool strfilter_node__compare(struct strfilter_node *node,
|
|||
}
|
||||
|
||||
/* Return true if STR matches the filter rules */
|
||||
bool strfilter__compare(struct strfilter *node, const char *str)
|
||||
bool strfilter__compare(struct strfilter *filter, const char *str)
|
||||
{
|
||||
if (!node)
|
||||
if (!filter)
|
||||
return false;
|
||||
return strfilter_node__compare(node->root, str);
|
||||
return strfilter_node__compare(filter->root, str);
|
||||
}
|
||||
|
|
|
@ -30,19 +30,19 @@ struct strfilter *strfilter__new(const char *rules, const char **err);
|
|||
|
||||
/**
|
||||
* strfilter__compare - compare given string and a string filter
|
||||
* @self: String filter
|
||||
* @filter: String filter
|
||||
* @str: target string
|
||||
*
|
||||
* Compare @str and @self. Return true if the str match the rule
|
||||
* Compare @str and @filter. Return true if the str match the rule
|
||||
*/
|
||||
bool strfilter__compare(struct strfilter *self, const char *str);
|
||||
bool strfilter__compare(struct strfilter *filter, const char *str);
|
||||
|
||||
/**
|
||||
* strfilter__delete - delete a string filter
|
||||
* @self: String filter to delete
|
||||
* @filter: String filter to delete
|
||||
*
|
||||
* Delete @self.
|
||||
* Delete @filter.
|
||||
*/
|
||||
void strfilter__delete(struct strfilter *self);
|
||||
void strfilter__delete(struct strfilter *filter);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
|
||||
#include "util.h"
|
||||
#include "sysfs.h"
|
||||
|
||||
static const char * const sysfs_known_mountpoints[] = {
|
||||
"/sys",
|
||||
0,
|
||||
};
|
||||
|
||||
static int sysfs_found;
|
||||
char sysfs_mountpoint[PATH_MAX + 1];
|
||||
|
||||
static int sysfs_valid_mountpoint(const char *sysfs)
|
||||
{
|
||||
struct statfs st_fs;
|
||||
|
||||
if (statfs(sysfs, &st_fs) < 0)
|
||||
return -ENOENT;
|
||||
else if (st_fs.f_type != (long) SYSFS_MAGIC)
|
||||
return -ENOENT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *sysfs_find_mountpoint(void)
|
||||
{
|
||||
const char * const *ptr;
|
||||
char type[100];
|
||||
FILE *fp;
|
||||
|
||||
if (sysfs_found)
|
||||
return (const char *) sysfs_mountpoint;
|
||||
|
||||
ptr = sysfs_known_mountpoints;
|
||||
while (*ptr) {
|
||||
if (sysfs_valid_mountpoint(*ptr) == 0) {
|
||||
sysfs_found = 1;
|
||||
strcpy(sysfs_mountpoint, *ptr);
|
||||
return sysfs_mountpoint;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* give up and parse /proc/mounts */
|
||||
fp = fopen("/proc/mounts", "r");
|
||||
if (fp == NULL)
|
||||
return NULL;
|
||||
|
||||
while (!sysfs_found &&
|
||||
fscanf(fp, "%*s %" STR(PATH_MAX) "s %99s %*s %*d %*d\n",
|
||||
sysfs_mountpoint, type) == 2) {
|
||||
|
||||
if (strcmp(type, "sysfs") == 0)
|
||||
sysfs_found = 1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return sysfs_found ? sysfs_mountpoint : NULL;
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef __SYSFS_H__
|
||||
#define __SYSFS_H__
|
||||
|
||||
const char *sysfs_find_mountpoint(void);
|
||||
|
||||
#endif /* __DEBUGFS_H__ */
|
|
@ -29,24 +29,24 @@ struct machine;
|
|||
struct comm;
|
||||
|
||||
struct thread *thread__new(pid_t pid, pid_t tid);
|
||||
void thread__delete(struct thread *self);
|
||||
void thread__delete(struct thread *thread);
|
||||
static inline void thread__exited(struct thread *thread)
|
||||
{
|
||||
thread->dead = true;
|
||||
}
|
||||
|
||||
int thread__set_comm(struct thread *thread, const char *comm, u64 timestamp);
|
||||
int thread__comm_len(struct thread *self);
|
||||
int thread__comm_len(struct thread *thread);
|
||||
struct comm *thread__comm(const struct thread *thread);
|
||||
const char *thread__comm_str(const struct thread *thread);
|
||||
void thread__insert_map(struct thread *self, struct map *map);
|
||||
void thread__insert_map(struct thread *thread, struct map *map);
|
||||
int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
|
||||
size_t thread__fprintf(struct thread *thread, FILE *fp);
|
||||
|
||||
static inline struct map *thread__find_map(struct thread *self,
|
||||
static inline struct map *thread__find_map(struct thread *thread,
|
||||
enum map_type type, u64 addr)
|
||||
{
|
||||
return self ? map_groups__find(&self->mg, type, addr) : NULL;
|
||||
return thread ? map_groups__find(&thread->mg, type, addr) : NULL;
|
||||
}
|
||||
|
||||
void thread__find_addr_map(struct thread *thread, struct machine *machine,
|
||||
|
|
Loading…
Reference in New Issue