perf/core improvements and fixes:

New features:
 
 - Add 'callindent' option to 'perf script -F', to indent the Intel PT
   call stack, making this output more ftrace-like (Adrian Hunter, Andi Kleen)
 
 User visible:
 
 - Enlarge 'pid' column width, to cope with large pids (Jiri Olsa)
 
 Infrastructure:
 
 - Cross platform unwind fixes (He Kuang)
 
 - Make destructors accept NULL, behaving like free() (Arnaldo Carvalho de Melo)
 
 - Remove reference to perl interpreted in the recently added 'perf script'
   stackcollapse python script (Arnaldo Carvalho de Melo)
 
 - Rename CLASS__for_each() macros to CLASS__for_each_entry(), to use the
   list_for_each_entry() semantics, as most of these class specific loop helpers
   are list_for_each_entry*() wrappers  (Arnaldo Carvalho de Melo)
 
 - Expose the hist_browser code, will be used with data structures other
   than perf_evsel (Jiri Olsa)
 
 - 'perf config' refactorings (Taeung Song)
 
 Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJXbFIcAAoJENZQFvNTUqpADw0QAJzIZK63uJ+kA3eq91go3oJi
 GDYqhA/HSV6cBHKG4CEuemKLYIK6GrnmLYK8wPquh8h1VkoRmBuV7AoLUbUdVW6P
 uINnJXqC45d/picN6z4K/KLfZAt/cT3FEl/JIRcMw72SyNhHfOvcPEUWZ+FCikWR
 11FtuU4bjIc+ctiXxn+Gwx1v3NacATRDIBiqHaUPVZtbWLXOcWKvgX6F6a0WCDF9
 0SPSyoW6nZDEl4aZScQ4eW8XwF4xFZesj0q/8JOP0XrMGQ7HtcvRSSoXhTrTlE5f
 MGF6OIfNOBuQhqKDrpfU/jwCqORA4dcv67iTo2MCfq+w3FiLMMCU7pB9543N5YT6
 WW70k2/AvFnhuD5gRZMHGZujRw7Ya1ZnVt9V6WtT5ia4he7dJC/7g26nee1OLRrT
 ug0l/03xOVVsZYQrAFo3efMYS7uMqMUP1Sdp5ujZ/KoEuSsQ/PJSvGyInsB9k994
 nmz4jGhDdRV7AqrxnhIwmcQJmukWSPjYF3Ei3rHRxa18HC29rKPQ9GvJHMMKt7wT
 JRP/Mle3ZyzRnMjFP+Rc/MOzQruqatCy3d/NH7ndL/UFzlW+873USK8Uj9VxuX20
 fvgl4yVcHJIzjiguuzF2AADpweWUdyk0oKMcyXblGT3Iokmr3su15Ml/Lg/U4sVN
 ey2y0qcut8K1uV1++Wlq
 =HRRs
 -----END PGP SIGNATURE-----

Merge tag 'perf-core-for-mingo-20160623' 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:

New features:

- Add 'callindent' option to 'perf script -F', to indent the Intel PT
  call stack, making this output more ftrace-like (Adrian Hunter, Andi Kleen)

User visible changes:

- Enlarge 'pid' column width, to cope with large pids (Jiri Olsa)

Infrastructure changes:

- Fix cross platform unwind (He Kuang)

- Make destructors accept NULL, behaving like free() (Arnaldo Carvalho de Melo)

- Remove reference to perl interpreted in the recently added 'perf script'
  stackcollapse python script (Arnaldo Carvalho de Melo)

- Rename CLASS__for_each() macros to CLASS__for_each_entry(), to use the
  list_for_each_entry() semantics, as most of these class specific loop helpers
  are list_for_each_entry*() wrappers  (Arnaldo Carvalho de Melo)

- Expose the hist_browser code, will be used with data structures other
  than perf_evsel (Jiri Olsa)

- Refactor 'perf config' (Taeung Song)

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Ingo Molnar 2016-06-26 12:41:59 +02:00
commit 9840b1ae45
77 changed files with 607 additions and 359 deletions

View File

@ -170,7 +170,16 @@ OPTIONS
Trace decoding. The flags are "bcrosyiABEx" which stand for branch,
call, return, conditional, system, asynchronous, interrupt,
transaction abort, trace begin, trace end, and in transaction,
respectively.
respectively. Known combinations of flags are printed more nicely e.g.
"call" for "bc", "return" for "br", "jcc" for "bo", "jmp" for "b",
"int" for "bci", "iret" for "bri", "syscall" for "bcs", "sysret" for "brs",
"async" for "by", "hw int" for "bcyi", "tx abrt" for "bA", "tr strt" for "bB",
"tr end" for "bE". However the "x" flag will be display separately in those
cases e.g. "jcc (x)" for a condition branch within a transaction.
The callindent field is synthesized and may have a value when
Instruction Trace decoding. For calls and returns, it will display the
name of the symbol indented with spaces to reflect the stack depth.
Finally, a user may not set fields to none for all event types.
i.e., -F "" is not allowed.

View File

@ -254,7 +254,8 @@ PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
$(QUIET_GEN)CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
$(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
$(PYTHON_WORD) util/setup.py \
--quiet build_ext; \
mkdir -p $(OUTPUT)python && \

View File

@ -154,10 +154,6 @@ next_event:
err = 0;
out_err:
if (evlist) {
perf_evlist__disable(evlist);
perf_evlist__delete(evlist);
}
perf_evlist__delete(evlist);
return err;
}

View File

@ -37,7 +37,7 @@ struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist,
intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME);
if (evlist) {
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (intel_pt_pmu &&
evsel->attr.type == intel_pt_pmu->type)
found_pt = true;

View File

@ -124,7 +124,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr,
btsr->evlist = evlist;
btsr->snapshot_mode = opts->auxtrace_snapshot_mode;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type == intel_bts_pmu->type) {
if (intel_bts_evsel) {
pr_err("There may be only one " INTEL_BTS_PMU_NAME " event\n");
@ -327,7 +327,7 @@ static int intel_bts_snapshot_start(struct auxtrace_record *itr)
container_of(itr, struct intel_bts_recording, itr);
struct perf_evsel *evsel;
evlist__for_each(btsr->evlist, evsel) {
evlist__for_each_entry(btsr->evlist, evsel) {
if (evsel->attr.type == btsr->intel_bts_pmu->type)
return perf_evsel__disable(evsel);
}
@ -340,7 +340,7 @@ static int intel_bts_snapshot_finish(struct auxtrace_record *itr)
container_of(itr, struct intel_bts_recording, itr);
struct perf_evsel *evsel;
evlist__for_each(btsr->evlist, evsel) {
evlist__for_each_entry(btsr->evlist, evsel) {
if (evsel->attr.type == btsr->intel_bts_pmu->type)
return perf_evsel__enable(evsel);
}
@ -422,7 +422,7 @@ static int intel_bts_read_finish(struct auxtrace_record *itr, int idx)
container_of(itr, struct intel_bts_recording, itr);
struct perf_evsel *evsel;
evlist__for_each(btsr->evlist, evsel) {
evlist__for_each_entry(btsr->evlist, evsel) {
if (evsel->attr.type == btsr->intel_bts_pmu->type)
return perf_evlist__enable_event_idx(btsr->evlist,
evsel, idx);

View File

@ -131,7 +131,7 @@ static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str,
if (!mask)
return -EINVAL;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type == intel_pt_pmu->type) {
*res = intel_pt_masked_bits(mask, evsel->attr.config);
return 0;
@ -511,7 +511,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
ptr->evlist = evlist;
ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type == intel_pt_pmu->type) {
if (intel_pt_evsel) {
pr_err("There may be only one " INTEL_PT_PMU_NAME " event\n");
@ -725,7 +725,7 @@ static int intel_pt_snapshot_start(struct auxtrace_record *itr)
container_of(itr, struct intel_pt_recording, itr);
struct perf_evsel *evsel;
evlist__for_each(ptr->evlist, evsel) {
evlist__for_each_entry(ptr->evlist, evsel) {
if (evsel->attr.type == ptr->intel_pt_pmu->type)
return perf_evsel__disable(evsel);
}
@ -738,7 +738,7 @@ static int intel_pt_snapshot_finish(struct auxtrace_record *itr)
container_of(itr, struct intel_pt_recording, itr);
struct perf_evsel *evsel;
evlist__for_each(ptr->evlist, evsel) {
evlist__for_each_entry(ptr->evlist, evsel) {
if (evsel->attr.type == ptr->intel_pt_pmu->type)
return perf_evsel__enable(evsel);
}
@ -1011,7 +1011,7 @@ static int intel_pt_read_finish(struct auxtrace_record *itr, int idx)
container_of(itr, struct intel_pt_recording, itr);
struct perf_evsel *evsel;
evlist__for_each(ptr->evlist, evsel) {
evlist__for_each_entry(ptr->evlist, evsel) {
if (evsel->attr.type == ptr->intel_pt_pmu->type)
return perf_evlist__enable_event_idx(ptr->evlist, evsel,
idx);

View File

@ -236,7 +236,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
perf_session__fprintf_dsos(session, stdout);
total_nr_samples = 0;
evlist__for_each(session->evlist, pos) {
evlist__for_each_entry(session->evlist, pos) {
struct hists *hists = evsel__hists(pos);
u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];

View File

@ -209,7 +209,7 @@ static int build_id_cache__purge_path(const char *pathname)
if (err)
goto out;
strlist__for_each(pos, list) {
strlist__for_each_entry(pos, list) {
err = build_id_cache__remove_s(pos->s);
pr_debug("Removing %s %s: %s\n", pos->s, pathname,
err ? "FAIL" : "Ok");
@ -343,7 +343,7 @@ int cmd_buildid_cache(int argc, const char **argv,
if (add_name_list_str) {
list = strlist__new(add_name_list_str, NULL);
if (list) {
strlist__for_each(pos, list)
strlist__for_each_entry(pos, list)
if (build_id_cache__add_file(pos->s)) {
if (errno == EEXIST) {
pr_debug("%s already in the cache\n",
@ -361,7 +361,7 @@ int cmd_buildid_cache(int argc, const char **argv,
if (remove_name_list_str) {
list = strlist__new(remove_name_list_str, NULL);
if (list) {
strlist__for_each(pos, list)
strlist__for_each_entry(pos, list)
if (build_id_cache__remove_file(pos->s)) {
if (errno == ENOENT) {
pr_debug("%s wasn't in the cache\n",
@ -379,7 +379,7 @@ int cmd_buildid_cache(int argc, const char **argv,
if (purge_name_list_str) {
list = strlist__new(purge_name_list_str, NULL);
if (list) {
strlist__for_each(pos, list)
strlist__for_each_entry(pos, list)
if (build_id_cache__purge_path(pos->s)) {
if (errno == ENOENT) {
pr_debug("%s wasn't in the cache\n",
@ -400,7 +400,7 @@ int cmd_buildid_cache(int argc, const char **argv,
if (update_name_list_str) {
list = strlist__new(update_name_list_str, NULL);
if (list) {
strlist__for_each(pos, list)
strlist__for_each_entry(pos, list)
if (build_id_cache__update_file(pos->s)) {
if (errno == ENOENT) {
pr_debug("%s wasn't in the cache\n",
@ -419,8 +419,7 @@ int cmd_buildid_cache(int argc, const char **argv,
pr_warning("Couldn't add %s\n", kcore_filename);
out:
if (session)
perf_session__delete(session);
perf_session__delete(session);
return ret;
}

View File

@ -37,23 +37,16 @@ static int show_config(struct perf_config_set *set)
{
struct perf_config_section *section;
struct perf_config_item *item;
struct list_head *sections;
if (set == NULL)
return -1;
sections = &set->sections;
if (list_empty(sections))
return -1;
perf_config_set__for_each_entry(set, section, item) {
char *value = item->value;
list_for_each_entry(section, sections, node) {
list_for_each_entry(item, &section->items, node) {
char *value = item->value;
if (value)
printf("%s.%s=%s\n", section->name,
item->name, value);
}
if (value)
printf("%s.%s=%s\n", section->name,
item->name, value);
}
return 0;
@ -80,6 +73,10 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
else if (use_user_config)
config_exclusive_filename = user_config;
/*
* At only 'config' sub-command, individually use the config set
* because of reinitializing with options config file location.
*/
set = perf_config_set__new();
if (!set) {
ret = -1;

View File

@ -363,7 +363,7 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
{
struct perf_evsel *e;
evlist__for_each(evlist, e) {
evlist__for_each_entry(evlist, e) {
if (perf_evsel__match2(evsel, e))
return e;
}
@ -375,7 +375,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
struct hists *hists = evsel__hists(evsel);
hists__collapse_resort(hists, NULL);
@ -681,7 +681,7 @@ static void data_process(void)
struct perf_evsel *evsel_base;
bool first = true;
evlist__for_each(evlist_base, evsel_base) {
evlist__for_each_entry(evlist_base, evsel_base) {
struct hists *hists_base = evsel__hists(evsel_base);
struct data__file *d;
int i;
@ -756,9 +756,7 @@ static int __cmd_diff(void)
out_delete:
data__for_each_file(i, d) {
if (d->session)
perf_session__delete(d->session);
perf_session__delete(d->session);
data__free(d);
}

View File

@ -32,7 +32,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
if (session == NULL)
return -1;
evlist__for_each(session->evlist, pos) {
evlist__for_each_entry(session->evlist, pos) {
perf_evsel__fprintf(pos, details, stdout);
if (pos->attr.type == PERF_TYPE_TRACEPOINT)

View File

@ -4,7 +4,7 @@
* Builtin help command
*/
#include "perf.h"
#include "util/cache.h"
#include "util/config.h"
#include "builtin.h"
#include <subcmd/exec-cmd.h>
#include "common-cmds.h"

View File

@ -562,7 +562,7 @@ static void strip_init(struct perf_inject *inject)
inject->tool.context_switch = perf_event__drop;
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
evsel->handler = drop_sample;
}
@ -590,7 +590,7 @@ static bool ok_to_remove(struct perf_evlist *evlist,
if (!has_tracking(evsel_to_remove))
return true;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->handler != drop_sample) {
cnt += 1;
if ((evsel->attr.sample_type & COMPAT_MASK) ==
@ -608,7 +608,7 @@ static void strip_fini(struct perf_inject *inject)
struct perf_evsel *evsel, *tmp;
/* Remove non-synthesized evsels if possible */
evlist__for_each_safe(evlist, tmp, evsel) {
evlist__for_each_entry_safe(evlist, tmp, evsel) {
if (evsel->handler == drop_sample &&
ok_to_remove(evlist, evsel)) {
pr_debug("Deleting %s\n", perf_evsel__name(evsel));
@ -643,7 +643,7 @@ static int __cmd_inject(struct perf_inject *inject)
} else if (inject->sched_stat) {
struct perf_evsel *evsel;
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
const char *name = perf_evsel__name(evsel);
if (!strcmp(name, "sched:sched_switch")) {

View File

@ -4,7 +4,7 @@
#include "util/evlist.h"
#include "util/evsel.h"
#include "util/util.h"
#include "util/cache.h"
#include "util/config.h"
#include "util/symbol.h"
#include "util/thread.h"
#include "util/header.h"
@ -1354,7 +1354,7 @@ static int __cmd_kmem(struct perf_session *session)
goto out;
}
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") &&
perf_evsel__field(evsel, "pfn")) {
use_pfn = true;

View File

@ -988,7 +988,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
* Note: exclude_{guest,host} do not apply here.
* This command processes KVM tracepoints from host only
*/
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
struct perf_event_attr *attr = &pos->attr;
/* make sure these *are* set */
@ -1426,11 +1426,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
err = kvm_events_live_report(kvm);
out:
if (kvm->session)
perf_session__delete(kvm->session);
perf_session__delete(kvm->session);
kvm->session = NULL;
if (kvm->evlist)
perf_evlist__delete(kvm->evlist);
perf_evlist__delete(kvm->evlist);
return err;
}

View File

@ -389,7 +389,7 @@ static int perf_del_probe_events(struct strfilter *filter)
ret = probe_file__get_events(kfd, filter, klist);
if (ret == 0) {
strlist__for_each(ent, klist)
strlist__for_each_entry(ent, klist)
pr_info("Removed event: %s\n", ent->s);
ret = probe_file__del_strlist(kfd, klist);
@ -399,7 +399,7 @@ static int perf_del_probe_events(struct strfilter *filter)
ret2 = probe_file__get_events(ufd, filter, ulist);
if (ret2 == 0) {
strlist__for_each(ent, ulist)
strlist__for_each_entry(ent, ulist)
pr_info("Removed event: %s\n", ent->s);
ret2 = probe_file__del_strlist(ufd, ulist);

View File

@ -13,6 +13,7 @@
#include "util/util.h"
#include <subcmd/parse-options.h>
#include "util/parse-events.h"
#include "util/config.h"
#include "util/callchain.h"
#include "util/cgroup.h"
@ -352,7 +353,7 @@ static int record__open(struct record *rec)
perf_evlist__config(evlist, opts, &callchain_param);
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
try_again:
if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {

View File

@ -8,7 +8,7 @@
#include "builtin.h"
#include "util/util.h"
#include "util/cache.h"
#include "util/config.h"
#include "util/annotate.h"
#include "util/color.h"
@ -361,7 +361,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
struct perf_evsel *pos;
fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples);
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
struct hists *hists = evsel__hists(pos);
const char *evname = perf_evsel__name(pos);
@ -478,7 +478,7 @@ static int report__collapse_hists(struct report *rep)
ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
evlist__for_each(rep->session->evlist, pos) {
evlist__for_each_entry(rep->session->evlist, pos) {
struct hists *hists = evsel__hists(pos);
if (pos->idx == 0)
@ -511,7 +511,7 @@ static void report__output_resort(struct report *rep)
ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
evlist__for_each(rep->session->evlist, pos)
evlist__for_each_entry(rep->session->evlist, pos)
perf_evsel__output_resort(pos, &prog);
ui_progress__finish();
@ -552,7 +552,7 @@ static int __cmd_report(struct report *rep)
report__warn_kptr_restrict(rep);
evlist__for_each(session->evlist, pos)
evlist__for_each_entry(session->evlist, pos)
rep->nr_entries += evsel__hists(pos)->nr_entries;
if (use_browser == 0) {
@ -583,7 +583,7 @@ static int __cmd_report(struct report *rep)
* might be changed during the collapse phase.
*/
rep->nr_entries = 0;
evlist__for_each(session->evlist, pos)
evlist__for_each_entry(session->evlist, pos)
rep->nr_entries += evsel__hists(pos)->nr_entries;
if (rep->nr_entries == 0) {

View File

@ -21,6 +21,7 @@
#include "util/cpumap.h"
#include "util/thread_map.h"
#include "util/stat.h"
#include "util/thread-stack.h"
#include <linux/bitmap.h>
#include <linux/stringify.h>
#include "asm/bug.h"
@ -63,6 +64,7 @@ enum perf_output_field {
PERF_OUTPUT_DATA_SRC = 1U << 17,
PERF_OUTPUT_WEIGHT = 1U << 18,
PERF_OUTPUT_BPF_OUTPUT = 1U << 19,
PERF_OUTPUT_CALLINDENT = 1U << 20,
};
struct output_option {
@ -89,6 +91,7 @@ struct output_option {
{.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
{.str = "weight", .field = PERF_OUTPUT_WEIGHT},
{.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT},
{.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
};
/* default set to maintain compatibility with current format */
@ -369,7 +372,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
if (!no_callchain) {
bool use_callchain = false;
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
use_callchain = true;
break;
@ -389,7 +392,7 @@ static int perf_session__check_output_opt(struct perf_session *session)
j = PERF_TYPE_TRACEPOINT;
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
if (evsel->attr.type != j)
continue;
@ -562,6 +565,62 @@ static void print_sample_addr(struct perf_sample *sample,
}
}
static void print_sample_callindent(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
struct addr_location *al)
{
struct perf_event_attr *attr = &evsel->attr;
size_t depth = thread_stack__depth(thread);
struct addr_location addr_al;
const char *name = NULL;
static int spacing;
int len = 0;
u64 ip = 0;
/*
* The 'return' has already been popped off the stack so the depth has
* to be adjusted to match the 'call'.
*/
if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
depth += 1;
if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
if (sample_addr_correlates_sym(attr)) {
thread__resolve(thread, &addr_al, sample);
if (addr_al.sym)
name = addr_al.sym->name;
else
ip = sample->addr;
} else {
ip = sample->addr;
}
} else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
if (al->sym)
name = al->sym->name;
else
ip = sample->ip;
}
if (name)
len = printf("%*s%s", (int)depth * 4, "", name);
else if (ip)
len = printf("%*s%16" PRIx64, (int)depth * 4, "", ip);
if (len < 0)
return;
/*
* Try to keep the output length from changing frequently so that the
* output lines up more nicely.
*/
if (len > spacing || (len && len < spacing - 52))
spacing = round_up(len + 4, 32);
if (len < spacing)
printf("%*s", spacing - len, "");
}
static void print_sample_bts(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
@ -570,6 +629,9 @@ static void print_sample_bts(struct perf_sample *sample,
struct perf_event_attr *attr = &evsel->attr;
bool print_srcline_last = false;
if (PRINT_FIELD(CALLINDENT))
print_sample_callindent(sample, evsel, thread, al);
/* print branch_from information */
if (PRINT_FIELD(IP)) {
unsigned int print_opts = output[attr->type].print_ip_opts;
@ -606,13 +668,42 @@ static void print_sample_bts(struct perf_sample *sample,
printf("\n");
}
static struct {
u32 flags;
const char *name;
} sample_flags[] = {
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "jcc"},
{PERF_IP_FLAG_BRANCH, "jmp"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, "int"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, "iret"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, "syscall"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, "sysret"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "async"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_INTERRUPT, "hw int"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"},
{PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},
{0, NULL}
};
static void print_sample_flags(u32 flags)
{
const char *chars = PERF_IP_FLAG_CHARS;
const int n = strlen(PERF_IP_FLAG_CHARS);
bool in_tx = flags & PERF_IP_FLAG_IN_TX;
const char *name = NULL;
char str[33];
int i, pos = 0;
for (i = 0; sample_flags[i].name ; i++) {
if (sample_flags[i].flags == (flags & ~PERF_IP_FLAG_IN_TX)) {
name = sample_flags[i].name;
break;
}
}
for (i = 0; i < n; i++, flags >>= 1) {
if (flags & 1)
str[pos++] = chars[i];
@ -622,7 +713,11 @@ static void print_sample_flags(u32 flags)
str[pos++] = '?';
}
str[pos] = 0;
printf(" %-4s ", str);
if (name)
printf(" %-7s%4s ", name, in_tx ? "(x)" : "");
else
printf(" %-11s ", str);
}
struct printer_data {
@ -720,7 +815,7 @@ static int perf_evlist__max_name_len(struct perf_evlist *evlist)
struct perf_evsel *evsel;
int max = 0;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
int len = strlen(perf_evsel__name(evsel));
max = MAX(len, max);
@ -945,7 +1040,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
if (evsel->attr.type >= PERF_TYPE_MAX)
return 0;
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
if (pos->attr.type == evsel->attr.type && pos != evsel)
return 0;
}
@ -1671,7 +1766,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
snprintf(evname, len + 1, "%s", p);
match = 0;
evlist__for_each(session->evlist, pos) {
evlist__for_each_entry(session->evlist, pos) {
if (!strcmp(perf_evsel__name(pos), evname)) {
match = 1;
break;
@ -1873,7 +1968,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
struct stat_round_event *round = &event->stat_round;
struct perf_evsel *counter;
evlist__for_each(session->evlist, counter) {
evlist__for_each_entry(session->evlist, counter) {
perf_stat_process_counter(&stat_config, counter);
process_stat(counter, round->time);
}
@ -2020,7 +2115,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
"comma separated output fields prepend with 'type:'. "
"Valid types: hw,sw,trace,raw. "
"Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
"addr,symoff,period,iregs,brstack,brstacksym,flags", parse_output_fields),
"addr,symoff,period,iregs,brstack,brstacksym,flags,"
"callindent", parse_output_fields),
OPT_BOOLEAN('a', "all-cpus", &system_wide,
"system-wide collection from all CPUs"),
OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@ -2259,6 +2355,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
script.session = session;
script__setup_sample_type(&script);
if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT)
itrace_synth_opts.thread_stack = true;
session->itrace_synth_opts = &itrace_synth_opts;
if (cpu_list) {

View File

@ -331,7 +331,7 @@ static void read_counters(bool close_counters)
{
struct perf_evsel *counter;
evlist__for_each(evsel_list, counter) {
evlist__for_each_entry(evsel_list, counter) {
if (read_counter(counter))
pr_debug("failed to read counter %s\n", counter->name);
@ -417,7 +417,7 @@ static int perf_stat_synthesize_config(bool is_pipe)
* Synthesize other events stuff not carried within
* attr event - unit, scale, name
*/
evlist__for_each(evsel_list, counter) {
evlist__for_each_entry(evsel_list, counter) {
if (!counter->supported)
continue;
@ -550,7 +550,7 @@ static int __run_perf_stat(int argc, const char **argv)
if (group)
perf_evlist__set_leader(evsel_list);
evlist__for_each(evsel_list, counter) {
evlist__for_each_entry(evsel_list, counter) {
try_again:
if (create_perf_stat_counter(counter) < 0) {
/*
@ -1134,7 +1134,7 @@ static void aggr_update_shadow(void)
for (s = 0; s < aggr_map->nr; s++) {
id = aggr_map->map[s];
evlist__for_each(evsel_list, counter) {
evlist__for_each_entry(evsel_list, counter) {
val = 0;
for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
s2 = aggr_get_id(evsel_list->cpus, cpu);
@ -1173,7 +1173,7 @@ static void print_aggr(char *prefix)
id = aggr_map->map[s];
first = true;
evlist__for_each(evsel_list, counter) {
evlist__for_each_entry(evsel_list, counter) {
val = ena = run = 0;
nr = 0;
for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
@ -1292,7 +1292,7 @@ static void print_no_aggr_metric(char *prefix)
if (prefix)
fputs(prefix, stat_config.output);
evlist__for_each(evsel_list, counter) {
evlist__for_each_entry(evsel_list, counter) {
if (first) {
aggr_printout(counter, cpu, 0);
first = false;
@ -1346,7 +1346,7 @@ static void print_metric_headers(const char *prefix, bool no_indent)
}
/* Print metrics headers only */
evlist__for_each(evsel_list, counter) {
evlist__for_each_entry(evsel_list, counter) {
os.evsel = counter;
out.ctx = &os;
out.print_metric = print_metric_header;
@ -1482,11 +1482,11 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
print_aggr(prefix);
break;
case AGGR_THREAD:
evlist__for_each(evsel_list, counter)
evlist__for_each_entry(evsel_list, counter)
print_aggr_thread(counter, prefix);
break;
case AGGR_GLOBAL:
evlist__for_each(evsel_list, counter)
evlist__for_each_entry(evsel_list, counter)
print_counter_aggr(counter, prefix);
if (metric_only)
fputc('\n', stat_config.output);
@ -1495,7 +1495,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
if (metric_only)
print_no_aggr_metric(prefix);
else {
evlist__for_each(evsel_list, counter)
evlist__for_each_entry(evsel_list, counter)
print_counter(counter, prefix);
}
break;
@ -2149,7 +2149,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
const char **argv = session->header.env.cmdline_argv;
int argc = session->header.env.nr_cmdline;
evlist__for_each(evsel_list, counter)
evlist__for_each_entry(evsel_list, counter)
perf_stat_process_counter(&stat_config, counter);
if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL)

View File

@ -22,7 +22,7 @@
#include "perf.h"
#include "util/annotate.h"
#include "util/cache.h"
#include "util/config.h"
#include "util/color.h"
#include "util/evlist.h"
#include "util/evsel.h"
@ -479,7 +479,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
fprintf(stderr, "\nAvailable events:");
evlist__for_each(top->evlist, top->sym_evsel)
evlist__for_each_entry(top->evlist, top->sym_evsel)
fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel));
prompt_integer(&counter, "Enter details event counter");
@ -490,7 +490,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
sleep(1);
break;
}
evlist__for_each(top->evlist, top->sym_evsel)
evlist__for_each_entry(top->evlist, top->sym_evsel)
if (top->sym_evsel->idx == counter)
break;
} else
@ -583,7 +583,7 @@ static void *display_thread_tui(void *arg)
* Zooming in/out UIDs. For now juse use whatever the user passed
* via --uid.
*/
evlist__for_each(top->evlist, pos) {
evlist__for_each_entry(top->evlist, pos) {
struct hists *hists = evsel__hists(pos);
hists->uid_filter_str = top->record_opts.target.uid_str;
}
@ -888,7 +888,7 @@ static int perf_top__start_counters(struct perf_top *top)
perf_evlist__config(evlist, opts, &callchain_param);
evlist__for_each(evlist, counter) {
evlist__for_each_entry(evlist, counter) {
try_again:
if (perf_evsel__open(counter, top->evlist->cpus,
top->evlist->threads) < 0) {

View File

@ -1247,7 +1247,7 @@ static int trace__validate_ev_qualifier(struct trace *trace)
i = 0;
strlist__for_each(pos, trace->ev_qualifier) {
strlist__for_each_entry(pos, trace->ev_qualifier) {
const char *sc = pos->s;
int id = syscalltbl__id(trace->sctbl, sc);
@ -2483,7 +2483,7 @@ static int trace__replay(struct trace *trace)
goto out;
}
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
(evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
@ -2550,7 +2550,7 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
resort_rb__for_each(nd, syscall_stats) {
resort_rb__for_each_entry(nd, syscall_stats) {
struct stats *stats = syscall_stats_entry->stats;
if (stats) {
double min = (double)(stats->min) / NSEC_PER_MSEC;
@ -2627,7 +2627,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
return 0;
}
resort_rb__for_each(nd, threads)
resort_rb__for_each_entry(nd, threads)
printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
resort_rb__delete(threads);
@ -2714,7 +2714,7 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
evsel->handler = handler;
}

View File

@ -10,7 +10,7 @@
#include "util/env.h"
#include <subcmd/exec-cmd.h>
#include "util/cache.h"
#include "util/config.h"
#include "util/quote.h"
#include <subcmd/run-command.h>
#include "util/parse-events.h"
@ -355,6 +355,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
perf_env__set_cmdline(&perf_env, argc, argv);
status = p->fn(argc, argv, prefix);
perf_config__exit();
exit_browser(status);
perf_env__exit(&perf_env);
bpf__clear();
@ -522,6 +523,7 @@ int main(int argc, const char **argv)
srandom(time(NULL));
perf_config__init();
perf_config(perf_default_config, NULL);
set_buildid_dir(NULL);

View File

@ -1,5 +1,3 @@
#!/usr/bin/perl -w
#
# stackcollapse.py - format perf samples with one line per distinct call stack
#
# This script's output has two space-separated fields. The first is a semicolon

View File

@ -118,7 +118,7 @@ int test__backward_ring_buffer(int subtest __maybe_unused)
perf_evlist__config(evlist, &opts, NULL);
/* Set backward bit, ring buffer should be writing from end */
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
evsel->attr.write_backward = 1;
err = perf_evlist__open(evlist);

View File

@ -200,8 +200,7 @@ static int test_times(int (attach)(struct perf_evlist *),
count.ena, count.run);
out_err:
if (evlist)
perf_evlist__delete(evlist);
perf_evlist__delete(evlist);
return !err ? TEST_OK : TEST_FAIL;
}

View File

@ -80,7 +80,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names)
}
err = 0;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) {
--err;
pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]);

View File

@ -56,7 +56,7 @@ static int add_hist_entries(struct perf_evlist *evlist,
* (perf [perf] main) will be collapsed to an existing entry
* so total 9 entries will be in the tree.
*/
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
struct hist_entry_iter iter = {
.evsel = evsel,
@ -136,7 +136,7 @@ int test__hists_filter(int subtest __maybe_unused)
if (err < 0)
goto out;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
struct hists *hists = evsel__hists(evsel);
hists__collapse_resort(hists, NULL);

View File

@ -72,7 +72,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
* However the second evsel also has a collapsed entry for
* "bash [libc] malloc" so total 9 entries will be in the tree.
*/
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
struct hists *hists = evsel__hists(evsel);
for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) {
@ -301,7 +301,7 @@ int test__hists_link(int subtest __maybe_unused)
if (err < 0)
goto out;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
hists = evsel__hists(evsel);
hists__collapse_resort(hists, NULL);

View File

@ -126,7 +126,7 @@ int test__basic_mmap(int subtest __maybe_unused)
}
err = 0;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
pr_debug("expected %d %s events, got %d\n",
expected_nr_events[evsel->idx],

View File

@ -32,7 +32,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups);
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
TEST_ASSERT_VAL("wrong type",
PERF_TYPE_TRACEPOINT == evsel->attr.type);
TEST_ASSERT_VAL("wrong sample_type",
@ -207,7 +207,7 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
TEST_ASSERT_VAL("wrong exclude_user",
!evsel->attr.exclude_user);
TEST_ASSERT_VAL("wrong exclude_kernel",

View File

@ -44,8 +44,7 @@ static int process_events(union perf_event **events, size_t count)
for (i = 0; i < count && !err; i++)
err = process_event(&evlist, events[i]);
if (evlist)
perf_evlist__delete(evlist);
perf_evlist__delete(evlist);
return err;
}

View File

@ -432,7 +432,7 @@ int test__switch_tracking(int subtest __maybe_unused)
}
/* Check non-tracking events are not tracking */
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel != tracking_evsel) {
if (evsel->attr.mmap || evsel->attr.comm) {
pr_debug("Non-tracking event is tracking\n");

View File

@ -1,5 +1,5 @@
#include "../util.h"
#include "../cache.h"
#include "../config.h"
#include "../../perf.h"
#include "libslang.h"
#include "ui.h"

View File

@ -8,6 +8,7 @@
#include "../../util/sort.h"
#include "../../util/symbol.h"
#include "../../util/evsel.h"
#include "../../util/config.h"
#include <pthread.h>
struct disasm_line_samples {

View File

@ -12,35 +12,17 @@
#include "../../util/top.h"
#include "../../arch/common.h"
#include "../browser.h"
#include "../browsers/hists.h"
#include "../helpline.h"
#include "../util.h"
#include "../ui.h"
#include "map.h"
#include "annotate.h"
struct hist_browser {
struct ui_browser b;
struct hists *hists;
struct hist_entry *he_selection;
struct map_symbol *selection;
struct hist_browser_timer *hbt;
struct pstack *pstack;
struct perf_env *env;
int print_seq;
bool show_dso;
bool show_headers;
float min_pcnt;
u64 nr_non_filtered_entries;
u64 nr_hierarchy_entries;
u64 nr_callchain_rows;
};
extern void hist_browser__init_hpp(void);
static int hists__browser_title(struct hists *hists,
struct hist_browser_timer *hbt,
char *bf, size_t size);
static int perf_evsel_browser_title(struct hist_browser *browser,
char *bf, size_t size);
static void hist_browser__update_nr_entries(struct hist_browser *hb);
static struct rb_node *hists__filter_entries(struct rb_node *nd,
@ -585,7 +567,12 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser)
"Or reduce the sampling frequency.");
}
static int hist_browser__run(struct hist_browser *browser, const char *help)
static int hist_browser__title(struct hist_browser *browser, char *bf, size_t size)
{
return browser->title ? browser->title(browser, bf, size) : 0;
}
int hist_browser__run(struct hist_browser *browser, const char *help)
{
int key;
char title[160];
@ -595,7 +582,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *help)
browser->b.entries = &browser->hists->entries;
browser->b.nr_entries = hist_browser__nr_entries(browser);
hists__browser_title(browser->hists, hbt, title, sizeof(title));
hist_browser__title(browser, title, sizeof(title));
if (ui_browser__show(&browser->b, title, "%s", help) < 0)
return -1;
@ -621,8 +608,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *help)
ui_browser__warn_lost_events(&browser->b);
}
hists__browser_title(browser->hists,
hbt, title, sizeof(title));
hist_browser__title(browser, title, sizeof(title));
ui_browser__show_title(&browser->b, title);
continue;
}
@ -2056,27 +2042,50 @@ static int hist_browser__dump(struct hist_browser *browser)
return 0;
}
static struct hist_browser *hist_browser__new(struct hists *hists,
struct hist_browser_timer *hbt,
struct perf_env *env)
void hist_browser__init(struct hist_browser *browser,
struct hists *hists)
{
struct perf_hpp_fmt *fmt;
browser->hists = hists;
browser->b.refresh = hist_browser__refresh;
browser->b.refresh_dimensions = hist_browser__refresh_dimensions;
browser->b.seek = ui_browser__hists_seek;
browser->b.use_navkeypressed = true;
browser->show_headers = symbol_conf.show_hist_headers;
hists__for_each_format(hists, fmt) {
perf_hpp__reset_width(fmt, hists);
++browser->b.columns;
}
}
struct hist_browser *hist_browser__new(struct hists *hists)
{
struct hist_browser *browser = zalloc(sizeof(*browser));
if (browser) {
browser->hists = hists;
browser->b.refresh = hist_browser__refresh;
browser->b.refresh_dimensions = hist_browser__refresh_dimensions;
browser->b.seek = ui_browser__hists_seek;
browser->b.use_navkeypressed = true;
browser->show_headers = symbol_conf.show_hist_headers;
browser->hbt = hbt;
browser->env = env;
}
if (browser)
hist_browser__init(browser, hists);
return browser;
}
static void hist_browser__delete(struct hist_browser *browser)
static struct hist_browser *
perf_evsel_browser__new(struct perf_evsel *evsel,
struct hist_browser_timer *hbt,
struct perf_env *env)
{
struct hist_browser *browser = hist_browser__new(evsel__hists(evsel));
if (browser) {
browser->hbt = hbt;
browser->env = env;
browser->title = perf_evsel_browser_title;
}
return browser;
}
void hist_browser__delete(struct hist_browser *browser)
{
free(browser);
}
@ -2097,10 +2106,11 @@ static inline bool is_report_browser(void *timer)
return timer == NULL;
}
static int hists__browser_title(struct hists *hists,
struct hist_browser_timer *hbt,
static int perf_evsel_browser_title(struct hist_browser *browser,
char *bf, size_t size)
{
struct hist_browser_timer *hbt = browser->hbt;
struct hists *hists = browser->hists;
char unit;
int printed;
const struct dso *dso = hists->dso_filter;
@ -2657,7 +2667,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
struct perf_env *env)
{
struct hists *hists = evsel__hists(evsel);
struct hist_browser *browser = hist_browser__new(hists, hbt, env);
struct hist_browser *browser = perf_evsel_browser__new(evsel, hbt, env);
struct branch_info *bi;
#define MAX_OPTIONS 16
char *options[MAX_OPTIONS];
@ -2666,7 +2676,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
int key = -1;
char buf[64];
int delay_secs = hbt ? hbt->refresh : 0;
struct perf_hpp_fmt *fmt;
#define HIST_BROWSER_HELP_COMMON \
"h/?/F1 Show this window\n" \
@ -2725,18 +2734,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
memset(options, 0, sizeof(options));
memset(actions, 0, sizeof(actions));
hists__for_each_format(browser->hists, fmt) {
perf_hpp__reset_width(fmt, hists);
/*
* This is done just once, and activates the horizontal scrolling
* code in the ui_browser code, it would be better to have a the
* counter in the perf_hpp code, but I couldn't find doing it here
* works, FIXME by setting this in hist_browser__new, for now, be
* clever 8-)
*/
++browser->b.columns;
}
if (symbol_conf.col_width_list_str)
perf_hpp__set_user_width(symbol_conf.col_width_list_str);
@ -3202,7 +3199,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
ui_helpline__push("Press ESC to exit");
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
const char *ev_name = perf_evsel__name(pos);
size_t line_len = strlen(ev_name) + 7;
@ -3233,7 +3230,7 @@ single_entry:
struct perf_evsel *pos;
nr_entries = 0;
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
if (perf_evsel__is_group_leader(pos))
nr_entries++;
}

View File

@ -0,0 +1,32 @@
#ifndef _PERF_UI_BROWSER_HISTS_H_
#define _PERF_UI_BROWSER_HISTS_H_ 1
#include "ui/browser.h"
struct hist_browser {
struct ui_browser b;
struct hists *hists;
struct hist_entry *he_selection;
struct map_symbol *selection;
struct hist_browser_timer *hbt;
struct pstack *pstack;
struct perf_env *env;
int print_seq;
bool show_dso;
bool show_headers;
float min_pcnt;
u64 nr_non_filtered_entries;
u64 nr_hierarchy_entries;
u64 nr_callchain_rows;
/* Get title string. */
int (*title)(struct hist_browser *browser,
char *bf, size_t size);
};
struct hist_browser *hist_browser__new(struct hists *hists);
void hist_browser__delete(struct hist_browser *browser);
int hist_browser__run(struct hist_browser *browser, const char *help);
void hist_browser__init(struct hist_browser *browser,
struct hists *hists);
#endif /* _PERF_UI_BROWSER_HISTS_H_ */

View File

@ -627,7 +627,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
gtk_container_add(GTK_CONTAINER(window), vbox);
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
struct hists *hists = evsel__hists(pos);
const char *evname = perf_evsel__name(pos);
GtkWidget *scrolled_window;

View File

@ -766,7 +766,7 @@ int perf_hpp__setup_hists_formats(struct perf_hpp_list *list,
if (!symbol_conf.report_hierarchy)
return 0;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
hists = evsel__hists(evsel);
perf_hpp_list__for_each_sort_list(list, fmt) {

View File

@ -1,4 +1,5 @@
#include "cache.h"
#include "config.h"
static const char *alias_key;
static char *alias_val;

View File

@ -63,6 +63,7 @@ enum itrace_period_type {
* @calls: limit branch samples to calls (can be combined with @returns)
* @returns: limit branch samples to returns (can be combined with @calls)
* @callchain: add callchain to 'instructions' events
* @thread_stack: feed branches to the thread_stack
* @last_branch: add branch context to 'instruction' events
* @callchain_sz: maximum callchain size
* @last_branch_sz: branch context size
@ -82,6 +83,7 @@ struct itrace_synth_opts {
bool calls;
bool returns;
bool callchain;
bool thread_stack;
bool last_branch;
unsigned int callchain_sz;
unsigned int last_branch_sz;

View File

@ -18,17 +18,6 @@
#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
#define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
extern const char *config_exclusive_filename;
typedef int (*config_fn_t)(const char *, const char *, void *);
int perf_default_config(const char *, const char *, void *);
int perf_config(config_fn_t fn, void *);
int perf_config_int(const char *, const char *);
u64 perf_config_u64(const char *, const char *);
int perf_config_bool(const char *, const char *);
int config_error_nonbool(const char *);
const char *perf_etc_perfconfig(void);
char *alias_lookup(const char *alias);
int split_cmdline(char *cmdline, const char ***argv);

View File

@ -81,7 +81,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
/*
* check if cgrp is already defined, if so we reuse it
*/
evlist__for_each(evlist, counter) {
evlist__for_each_entry(evlist, counter) {
cgrp = counter->cgrp;
if (!cgrp)
continue;
@ -110,7 +110,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
* if add cgroup N, then need to find event N
*/
n = 0;
evlist__for_each(evlist, counter) {
evlist__for_each_entry(evlist, counter) {
if (n == nr_cgroups)
goto found;
n++;

View File

@ -1,5 +1,6 @@
#include <linux/kernel.h>
#include "cache.h"
#include "config.h"
#include "color.h"
#include <math.h>

View File

@ -26,6 +26,7 @@ static FILE *config_file;
static const char *config_file_name;
static int config_linenr;
static int config_file_eof;
static struct perf_config_set *config_set;
const char *config_exclusive_filename;
@ -478,51 +479,6 @@ static int perf_config_global(void)
return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0);
}
int perf_config(config_fn_t fn, void *data)
{
int ret = -1;
const char *home = NULL;
/* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
if (config_exclusive_filename)
return perf_config_from_file(fn, config_exclusive_filename, data);
if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) {
if (perf_config_from_file(fn, perf_etc_perfconfig(), data) < 0)
goto out;
}
home = getenv("HOME");
if (perf_config_global() && home) {
char *user_config = strdup(mkpath("%s/.perfconfig", home));
struct stat st;
if (user_config == NULL) {
warning("Not enough memory to process %s/.perfconfig, "
"ignoring it.", home);
goto out;
}
if (stat(user_config, &st) < 0)
goto out_free;
if (st.st_uid && (st.st_uid != geteuid())) {
warning("File %s not owned by current user or root, "
"ignoring it.", user_config);
goto out_free;
}
if (!st.st_size)
goto out_free;
ret = perf_config_from_file(fn, user_config, data);
out_free:
free(user_config);
}
out:
return ret;
}
static struct perf_config_section *find_section(struct list_head *sections,
const char *section_name)
{
@ -706,6 +662,52 @@ struct perf_config_set *perf_config_set__new(void)
return set;
}
int perf_config(config_fn_t fn, void *data)
{
int ret = 0;
char key[BUFSIZ];
struct perf_config_section *section;
struct perf_config_item *item;
if (config_set == NULL)
return -1;
perf_config_set__for_each_entry(config_set, section, item) {
char *value = item->value;
if (value) {
scnprintf(key, sizeof(key), "%s.%s",
section->name, item->name);
ret = fn(key, value, data);
if (ret < 0) {
pr_err("Error: wrong config key-value pair %s=%s\n",
key, value);
break;
}
}
}
return ret;
}
void perf_config__init(void)
{
if (config_set == NULL)
config_set = perf_config_set__new();
}
void perf_config__exit(void)
{
perf_config_set__delete(config_set);
config_set = NULL;
}
void perf_config__refresh(void)
{
perf_config__exit();
perf_config__init();
}
static void perf_config_item__delete(struct perf_config_item *item)
{
zfree(&item->name);

View File

@ -20,7 +20,47 @@ struct perf_config_set {
struct list_head sections;
};
extern const char *config_exclusive_filename;
typedef int (*config_fn_t)(const char *, const char *, void *);
int perf_default_config(const char *, const char *, void *);
int perf_config(config_fn_t fn, void *);
int perf_config_int(const char *, const char *);
u64 perf_config_u64(const char *, const char *);
int perf_config_bool(const char *, const char *);
int config_error_nonbool(const char *);
const char *perf_etc_perfconfig(void);
struct perf_config_set *perf_config_set__new(void);
void perf_config_set__delete(struct perf_config_set *set);
void perf_config__init(void);
void perf_config__exit(void);
void perf_config__refresh(void);
/**
* perf_config_sections__for_each - iterate thru all the sections
* @list: list_head instance to iterate
* @section: struct perf_config_section iterator
*/
#define perf_config_sections__for_each_entry(list, section) \
list_for_each_entry(section, list, node)
/**
* perf_config_items__for_each - iterate thru all the items
* @list: list_head instance to iterate
* @item: struct perf_config_item iterator
*/
#define perf_config_items__for_each_entry(list, item) \
list_for_each_entry(item, list, node)
/**
* perf_config_set__for_each - iterate thru all the config section-item pairs
* @set: evlist instance to iterate
* @section: struct perf_config_section iterator
* @item: struct perf_config_item iterator
*/
#define perf_config_set__for_each_entry(set, section, item) \
perf_config_sections__for_each_entry(&set->sections, section) \
perf_config_items__for_each_entry(&section->items, item)
#endif /* __PERF_CONFIG_H */

View File

@ -997,7 +997,7 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session)
struct perf_evsel *evsel;
int ret;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
ret = add_event(cw, evsel);
if (ret)
return ret;
@ -1010,7 +1010,7 @@ static void cleanup_events(struct perf_session *session)
struct perf_evlist *evlist = session->evlist;
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
struct evsel_priv *priv;
priv = evsel->priv;

View File

@ -100,7 +100,7 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
perf_evsel__calc_id_pos(evsel);
perf_evlist__set_id_pos(evlist);
@ -110,7 +110,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
{
struct perf_evsel *pos, *n;
evlist__for_each_safe(evlist, n, pos) {
evlist__for_each_entry_safe(evlist, n, pos) {
list_del_init(&pos->node);
pos->evlist = NULL;
perf_evsel__delete(pos);
@ -127,6 +127,9 @@ void perf_evlist__exit(struct perf_evlist *evlist)
void perf_evlist__delete(struct perf_evlist *evlist)
{
if (evlist == NULL)
return;
perf_evlist__munmap(evlist);
perf_evlist__close(evlist);
cpu_map__put(evlist->cpus);
@ -161,7 +164,7 @@ static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
__perf_evlist__propagate_maps(evlist, evsel);
}
@ -190,7 +193,7 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
{
struct perf_evsel *evsel, *temp;
__evlist__for_each_safe(list, temp, evsel) {
__evlist__for_each_entry_safe(list, temp, evsel) {
list_del_init(&evsel->node);
perf_evlist__add(evlist, evsel);
}
@ -205,7 +208,7 @@ void __perf_evlist__set_leader(struct list_head *list)
leader->nr_members = evsel->idx - leader->idx + 1;
__evlist__for_each(list, evsel) {
__evlist__for_each_entry(list, evsel) {
evsel->leader = leader;
}
}
@ -296,7 +299,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist,
return 0;
out_delete_partial_list:
__evlist__for_each_safe(&head, n, evsel)
__evlist__for_each_entry_safe(&head, n, evsel)
perf_evsel__delete(evsel);
return -1;
}
@ -317,7 +320,7 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
(int)evsel->attr.config == id)
return evsel;
@ -332,7 +335,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) &&
(strcmp(evsel->name, name) == 0))
return evsel;
@ -367,7 +370,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
{
struct perf_evsel *pos;
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
if (!perf_evsel__is_group_leader(pos) || !pos->fd)
continue;
perf_evsel__disable(pos);
@ -380,7 +383,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
{
struct perf_evsel *pos;
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
if (!perf_evsel__is_group_leader(pos) || !pos->fd)
continue;
perf_evsel__enable(pos);
@ -448,7 +451,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
int nfds = 0;
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->system_wide)
nfds += nr_cpus;
else
@ -1012,7 +1015,7 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
struct perf_evsel *evsel;
int revent;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
int fd;
if (evsel->overwrite != (evlist->overwrite && evlist->backward))
@ -1259,7 +1262,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len,
auxtrace_pages, auxtrace_overwrite);
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
evsel->sample_id == NULL &&
perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
@ -1335,7 +1338,7 @@ void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
__perf_evsel__set_sample_bit(evsel, bit);
}
@ -1344,7 +1347,7 @@ void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
__perf_evsel__reset_sample_bit(evsel, bit);
}
@ -1355,7 +1358,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
const int ncpus = cpu_map__nr(evlist->cpus),
nthreads = thread_map__nr(evlist->threads);
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->filter == NULL)
continue;
@ -1378,7 +1381,7 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
struct perf_evsel *evsel;
int err = 0;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
continue;
@ -1432,7 +1435,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
if (evlist->id_pos < 0 || evlist->is_pos < 0)
return false;
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
if (pos->id_pos != evlist->id_pos ||
pos->is_pos != evlist->is_pos)
return false;
@ -1448,7 +1451,7 @@ u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist)
if (evlist->combined_sample_type)
return evlist->combined_sample_type;
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
evlist->combined_sample_type |= evsel->attr.sample_type;
return evlist->combined_sample_type;
@ -1465,7 +1468,7 @@ u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist)
struct perf_evsel *evsel;
u64 branch_type = 0;
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
branch_type |= evsel->attr.branch_sample_type;
return branch_type;
}
@ -1476,7 +1479,7 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
u64 read_format = first->attr.read_format;
u64 sample_type = first->attr.sample_type;
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
if (read_format != pos->attr.read_format)
return false;
}
@ -1533,7 +1536,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
{
struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
evlist__for_each_continue(evlist, pos) {
evlist__for_each_entry_continue(evlist, pos) {
if (first->attr.sample_id_all != pos->attr.sample_id_all)
return false;
}
@ -1560,7 +1563,7 @@ void perf_evlist__close(struct perf_evlist *evlist)
int nthreads = thread_map__nr(evlist->threads);
int n;
evlist__for_each_reverse(evlist, evsel) {
evlist__for_each_entry_reverse(evlist, evsel) {
n = evsel->cpus ? evsel->cpus->nr : ncpus;
perf_evsel__close(evsel, n, nthreads);
}
@ -1614,7 +1617,7 @@ int perf_evlist__open(struct perf_evlist *evlist)
perf_evlist__update_id_pos(evlist);
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
err = perf_evsel__open(evsel, evsel->cpus, evsel->threads);
if (err < 0)
goto out_err;
@ -1775,7 +1778,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
struct perf_evsel *evsel;
size_t printed = 0;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
perf_evsel__name(evsel));
}
@ -1877,7 +1880,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
if (move_evsel == perf_evlist__first(evlist))
return;
evlist__for_each_safe(evlist, n, evsel) {
evlist__for_each_entry_safe(evlist, n, evsel) {
if (evsel->leader == move_evsel->leader)
list_move_tail(&evsel->node, &move);
}
@ -1893,7 +1896,7 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
if (tracking_evsel->tracking)
return;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel != tracking_evsel)
evsel->tracking = false;
}
@ -1907,7 +1910,7 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (!evsel->name)
continue;
if (strcmp(str, evsel->name) == 0)

View File

@ -251,70 +251,70 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
struct perf_evsel *move_evsel);
/**
* __evlist__for_each - iterate thru all the evsels
* __evlist__for_each_entry - iterate thru all the evsels
* @list: list_head instance to iterate
* @evsel: struct evsel iterator
*/
#define __evlist__for_each(list, evsel) \
#define __evlist__for_each_entry(list, evsel) \
list_for_each_entry(evsel, list, node)
/**
* evlist__for_each - iterate thru all the evsels
* evlist__for_each_entry - iterate thru all the evsels
* @evlist: evlist instance to iterate
* @evsel: struct evsel iterator
*/
#define evlist__for_each(evlist, evsel) \
__evlist__for_each(&(evlist)->entries, evsel)
#define evlist__for_each_entry(evlist, evsel) \
__evlist__for_each_entry(&(evlist)->entries, evsel)
/**
* __evlist__for_each_continue - continue iteration thru all the evsels
* __evlist__for_each_entry_continue - continue iteration thru all the evsels
* @list: list_head instance to iterate
* @evsel: struct evsel iterator
*/
#define __evlist__for_each_continue(list, evsel) \
#define __evlist__for_each_entry_continue(list, evsel) \
list_for_each_entry_continue(evsel, list, node)
/**
* evlist__for_each_continue - continue iteration thru all the evsels
* evlist__for_each_entry_continue - continue iteration thru all the evsels
* @evlist: evlist instance to iterate
* @evsel: struct evsel iterator
*/
#define evlist__for_each_continue(evlist, evsel) \
__evlist__for_each_continue(&(evlist)->entries, evsel)
#define evlist__for_each_entry_continue(evlist, evsel) \
__evlist__for_each_entry_continue(&(evlist)->entries, evsel)
/**
* __evlist__for_each_reverse - iterate thru all the evsels in reverse order
* __evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
* @list: list_head instance to iterate
* @evsel: struct evsel iterator
*/
#define __evlist__for_each_reverse(list, evsel) \
#define __evlist__for_each_entry_reverse(list, evsel) \
list_for_each_entry_reverse(evsel, list, node)
/**
* evlist__for_each_reverse - iterate thru all the evsels in reverse order
* evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
* @evlist: evlist instance to iterate
* @evsel: struct evsel iterator
*/
#define evlist__for_each_reverse(evlist, evsel) \
__evlist__for_each_reverse(&(evlist)->entries, evsel)
#define evlist__for_each_entry_reverse(evlist, evsel) \
__evlist__for_each_entry_reverse(&(evlist)->entries, evsel)
/**
* __evlist__for_each_safe - safely iterate thru all the evsels
* __evlist__for_each_entry_safe - safely iterate thru all the evsels
* @list: list_head instance to iterate
* @tmp: struct evsel temp iterator
* @evsel: struct evsel iterator
*/
#define __evlist__for_each_safe(list, tmp, evsel) \
#define __evlist__for_each_entry_safe(list, tmp, evsel) \
list_for_each_entry_safe(evsel, tmp, list, node)
/**
* evlist__for_each_safe - safely iterate thru all the evsels
* evlist__for_each_entry_safe - safely iterate thru all the evsels
* @evlist: evlist instance to iterate
* @evsel: struct evsel iterator
* @tmp: struct evsel temp iterator
*/
#define evlist__for_each_safe(evlist, tmp, evsel) \
__evlist__for_each_safe(&(evlist)->entries, tmp, evsel)
#define evlist__for_each_entry_safe(evlist, tmp, evsel) \
__evlist__for_each_entry_safe(&(evlist)->entries, tmp, evsel)
void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
struct perf_evsel *tracking_evsel);

View File

@ -336,7 +336,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
if (ret < 0)
return ret;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
ret = do_write(fd, &evsel->attr, sz);
if (ret < 0)
return ret;
@ -801,7 +801,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
if (ret < 0)
return ret;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (perf_evsel__is_group_leader(evsel) &&
evsel->nr_members > 1) {
const char *name = evsel->group_name ?: "{anon_group}";
@ -1425,7 +1425,7 @@ static void print_group_desc(struct perf_header *ph, int fd __maybe_unused,
session = container_of(ph, struct perf_session, header);
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
if (perf_evsel__is_group_leader(evsel) &&
evsel->nr_members > 1) {
fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
@ -1703,7 +1703,7 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->idx == idx)
return evsel;
}
@ -2075,7 +2075,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
session->evlist->nr_groups = nr_groups;
i = nr = 0;
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
if (evsel->idx == (int) desc[i].leader_idx) {
evsel->leader = evsel;
/* {anon_group} is a dummy name */
@ -2383,7 +2383,7 @@ int perf_session__write_header(struct perf_session *session,
lseek(fd, sizeof(f_header), SEEK_SET);
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
evsel->id_offset = lseek(fd, 0, SEEK_CUR);
err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
if (err < 0) {
@ -2394,7 +2394,7 @@ int perf_session__write_header(struct perf_session *session,
attr_offset = lseek(fd, 0, SEEK_CUR);
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
f_attr = (struct perf_file_attr){
.attr = evsel->attr,
.ids = {
@ -2828,7 +2828,7 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
{
struct perf_evsel *pos;
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
perf_evsel__prepare_tracepoint_event(pos, pevent))
return -1;
@ -3127,7 +3127,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
struct perf_evsel *evsel;
int err = 0;
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
evsel->id, process);
if (err) {

View File

@ -1,4 +1,5 @@
#include "cache.h"
#include "config.h"
#include <subcmd/help.h>
#include "../builtin.h"
#include "levenshtein.h"

View File

@ -79,7 +79,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
len = thread__comm_len(h->thread);
if (hists__new_col_len(hists, HISTC_COMM, len))
hists__set_col_len(hists, HISTC_THREAD, len + 6);
hists__set_col_len(hists, HISTC_THREAD, len + 8);
if (h->ms.map) {
len = dso__name_len(h->ms.map->dso);
@ -2199,7 +2199,7 @@ size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp)
struct perf_evsel *pos;
size_t ret = 0;
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp);
}

View File

@ -422,7 +422,8 @@ static int intel_bts_get_branch_type(struct intel_bts_queue *btsq,
}
static int intel_bts_process_buffer(struct intel_bts_queue *btsq,
struct auxtrace_buffer *buffer)
struct auxtrace_buffer *buffer,
struct thread *thread)
{
struct branch *branch;
size_t sz, bsz = sizeof(struct branch);
@ -444,6 +445,12 @@ static int intel_bts_process_buffer(struct intel_bts_queue *btsq,
if (!branch->from && !branch->to)
continue;
intel_bts_get_branch_type(btsq, branch);
if (btsq->bts->synth_opts.thread_stack)
thread_stack__event(thread, btsq->sample_flags,
le64_to_cpu(branch->from),
le64_to_cpu(branch->to),
btsq->intel_pt_insn.length,
buffer->buffer_nr + 1);
if (filter && !(filter & btsq->sample_flags))
continue;
err = intel_bts_synth_branch_sample(btsq, branch);
@ -507,12 +514,13 @@ static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp)
goto out_put;
}
if (!btsq->bts->synth_opts.callchain && thread &&
if (!btsq->bts->synth_opts.callchain &&
!btsq->bts->synth_opts.thread_stack && thread &&
(!old_buffer || btsq->bts->sampling_mode ||
(btsq->bts->snapshot_mode && !buffer->consecutive)))
thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1);
err = intel_bts_process_buffer(btsq, buffer);
err = intel_bts_process_buffer(btsq, buffer, thread);
auxtrace_buffer__drop_data(buffer);
@ -777,7 +785,7 @@ static int intel_bts_synth_events(struct intel_bts *bts,
u64 id;
int err;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type == bts->pmu_type && evsel->ids) {
found = true;
break;
@ -905,10 +913,14 @@ int intel_bts_process_auxtrace_info(union perf_event *event,
if (dump_trace)
return 0;
if (session->itrace_synth_opts && session->itrace_synth_opts->set)
if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
bts->synth_opts = *session->itrace_synth_opts;
else
} else {
itrace_synth_opts__set_default(&bts->synth_opts);
if (session->itrace_synth_opts)
bts->synth_opts.thread_stack =
session->itrace_synth_opts->thread_stack;
}
if (bts->synth_opts.calls)
bts->branches_filter |= PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |

View File

@ -39,6 +39,7 @@
#include "auxtrace.h"
#include "tsc.h"
#include "intel-pt.h"
#include "config.h"
#include "intel-pt-decoder/intel-pt-log.h"
#include "intel-pt-decoder/intel-pt-decoder.h"
@ -556,7 +557,7 @@ static bool intel_pt_exclude_kernel(struct intel_pt *pt)
{
struct perf_evsel *evsel;
evlist__for_each(pt->session->evlist, evsel) {
evlist__for_each_entry(pt->session->evlist, evsel) {
if (intel_pt_get_config(pt, &evsel->attr, NULL) &&
!evsel->attr.exclude_kernel)
return false;
@ -572,7 +573,7 @@ static bool intel_pt_return_compression(struct intel_pt *pt)
if (!pt->noretcomp_bit)
return true;
evlist__for_each(pt->session->evlist, evsel) {
evlist__for_each_entry(pt->session->evlist, evsel) {
if (intel_pt_get_config(pt, &evsel->attr, &config) &&
(config & pt->noretcomp_bit))
return false;
@ -592,7 +593,7 @@ static unsigned int intel_pt_mtc_period(struct intel_pt *pt)
for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++)
config >>= 1;
evlist__for_each(pt->session->evlist, evsel) {
evlist__for_each_entry(pt->session->evlist, evsel) {
if (intel_pt_get_config(pt, &evsel->attr, &config))
return (config & pt->mtc_freq_bits) >> shift;
}
@ -608,7 +609,7 @@ static bool intel_pt_timeless_decoding(struct intel_pt *pt)
if (!pt->tsc_bit || !pt->cap_user_time_zero)
return true;
evlist__for_each(pt->session->evlist, evsel) {
evlist__for_each_entry(pt->session->evlist, evsel) {
if (!(evsel->attr.sample_type & PERF_SAMPLE_TIME))
return true;
if (intel_pt_get_config(pt, &evsel->attr, &config)) {
@ -625,7 +626,7 @@ static bool intel_pt_tracing_kernel(struct intel_pt *pt)
{
struct perf_evsel *evsel;
evlist__for_each(pt->session->evlist, evsel) {
evlist__for_each_entry(pt->session->evlist, evsel) {
if (intel_pt_get_config(pt, &evsel->attr, NULL) &&
!evsel->attr.exclude_kernel)
return true;
@ -642,7 +643,7 @@ static bool intel_pt_have_tsc(struct intel_pt *pt)
if (!pt->tsc_bit)
return false;
evlist__for_each(pt->session->evlist, evsel) {
evlist__for_each_entry(pt->session->evlist, evsel) {
if (intel_pt_get_config(pt, &evsel->attr, &config)) {
if (config & pt->tsc_bit)
have_tsc = true;
@ -1233,7 +1234,7 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
if (!(state->type & INTEL_PT_BRANCH))
return 0;
if (pt->synth_opts.callchain)
if (pt->synth_opts.callchain || pt->synth_opts.thread_stack)
thread_stack__event(ptq->thread, ptq->flags, state->from_ip,
state->to_ip, ptq->insn_len,
state->trace_nr);
@ -1850,7 +1851,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
u64 id;
int err;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type == pt->pmu_type && evsel->ids) {
found = true;
break;
@ -1930,7 +1931,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
pt->sample_transactions = true;
pt->transactions_id = id;
id += 1;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->id && evsel->id[0] == pt->transactions_id) {
if (evsel->name)
zfree(&evsel->name);
@ -1968,7 +1969,7 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist)
{
struct perf_evsel *evsel;
evlist__for_each_reverse(evlist, evsel) {
evlist__for_each_entry_reverse(evlist, evsel) {
const char *name = perf_evsel__name(evsel);
if (!strcmp(name, "sched:sched_switch"))
@ -1982,7 +1983,7 @@ static bool intel_pt_find_switch(struct perf_evlist *evlist)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.context_switch)
return true;
}
@ -2136,6 +2137,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
pt->synth_opts.branches = false;
pt->synth_opts.callchain = true;
}
if (session->itrace_synth_opts)
pt->synth_opts.thread_stack =
session->itrace_synth_opts->thread_stack;
}
if (pt->synth_opts.log)

View File

@ -57,21 +57,21 @@ static inline struct int_node *intlist__next(struct int_node *in)
}
/**
* intlist_for_each - iterate over a intlist
* intlist__for_each_entry - iterate over a intlist
* @pos: the &struct int_node to use as a loop cursor.
* @ilist: the &struct intlist for loop.
*/
#define intlist__for_each(pos, ilist) \
#define intlist__for_each_entry(pos, ilist) \
for (pos = intlist__first(ilist); pos; pos = intlist__next(pos))
/**
* intlist_for_each_safe - iterate over a intlist safe against removal of
* intlist__for_each_entry_safe - iterate over a intlist safe against removal of
* int_node
* @pos: the &struct int_node to use as a loop cursor.
* @n: another &struct int_node to use as temporary storage.
* @ilist: the &struct intlist for loop.
*/
#define intlist__for_each_safe(pos, n, ilist) \
#define intlist__for_each_entry_safe(pos, n, ilist) \
for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\
pos = n, n = intlist__next(n))
#endif /* __PERF_INTLIST_H */

View File

@ -108,7 +108,7 @@ jit_validate_events(struct perf_session *session)
/*
* check that all events use CLOCK_MONOTONIC
*/
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC)
return -1;
}

View File

@ -13,7 +13,12 @@
#define REMOTE_UNWIND_LIBUNWIND
/* Define arch specific functions & regs for libunwind, should be
* defined before including "unwind.h"
*/
#define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__arm64_reg_id(regnum)
#define LIBUNWIND__ARCH_REG_IP PERF_REG_ARM64_PC
#define LIBUNWIND__ARCH_REG_SP PERF_REG_ARM64_SP
#include "unwind.h"
#include "debug.h"

View File

@ -12,7 +12,13 @@
*/
#define REMOTE_UNWIND_LIBUNWIND
/* Define arch specific functions & regs for libunwind, should be
* defined before including "unwind.h"
*/
#define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__x86_reg_id(regnum)
#define LIBUNWIND__ARCH_REG_IP PERF_REG_X86_IP
#define LIBUNWIND__ARCH_REG_SP PERF_REG_X86_SP
#include "unwind.h"
#include "debug.h"

View File

@ -8,6 +8,7 @@
#include <stdlib.h>
#include "debug.h"
#include "llvm-utils.h"
#include "config.h"
#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \
"$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\

View File

@ -138,8 +138,10 @@ void machine__exit(struct machine *machine)
void machine__delete(struct machine *machine)
{
machine__exit(machine);
free(machine);
if (machine) {
machine__exit(machine);
free(machine);
}
}
void machines__init(struct machines *machines)

View File

@ -1396,7 +1396,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
if (!add && get_event_modifier(&mod, str, NULL))
return -EINVAL;
__evlist__for_each(list, evsel) {
__evlist__for_each_entry(list, evsel) {
if (add && get_event_modifier(&mod, str, evsel))
return -EINVAL;
@ -1422,7 +1422,7 @@ int parse_events_name(struct list_head *list, char *name)
{
struct perf_evsel *evsel;
__evlist__for_each(list, evsel) {
__evlist__for_each_entry(list, evsel) {
if (!evsel->name)
evsel->name = strdup(name);
}

View File

@ -102,10 +102,8 @@ out:
void exit_probe_symbol_maps(void)
{
if (host_machine) {
machine__delete(host_machine);
host_machine = NULL;
}
machine__delete(host_machine);
host_machine = NULL;
symbol__exit();
}
@ -898,7 +896,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
goto end;
}
intlist__for_each(ln, lr->line_list) {
intlist__for_each_entry(ln, lr->line_list) {
for (; ln->i > l; l++) {
ret = show_one_line(fp, l - lr->offset);
if (ret < 0)
@ -982,7 +980,7 @@ static int show_available_vars_at(struct debuginfo *dinfo,
zfree(&vl->point.symbol);
nvars = 0;
if (vl->vars) {
strlist__for_each(node, vl->vars) {
strlist__for_each_entry(node, vl->vars) {
var = strchr(node->s, '\t') + 1;
if (strfilter__compare(_filter, var)) {
fprintf(stdout, "\t\t%s\n", node->s);
@ -2335,7 +2333,7 @@ static int __show_perf_probe_events(int fd, bool is_kprobe,
if (!rawlist)
return -ENOMEM;
strlist__for_each(ent, rawlist) {
strlist__for_each_entry(ent, rawlist) {
ret = parse_probe_trace_command(ent->s, &tev);
if (ret >= 0) {
if (!filter_probe_trace_event(&tev, filter))

View File

@ -178,7 +178,7 @@ static struct strlist *__probe_file__get_namelist(int fd, bool include_group)
if (!rawlist)
return NULL;
sl = strlist__new(NULL, NULL);
strlist__for_each(ent, rawlist) {
strlist__for_each_entry(ent, rawlist) {
ret = parse_probe_trace_command(ent->s, &tev);
if (ret < 0)
break;
@ -281,7 +281,7 @@ int probe_file__get_events(int fd, struct strfilter *filter,
if (!namelist)
return -ENOENT;
strlist__for_each(ent, namelist) {
strlist__for_each_entry(ent, namelist) {
p = strchr(ent->s, ':');
if ((p && strfilter__compare(filter, p + 1)) ||
strfilter__compare(filter, ent->s)) {
@ -299,7 +299,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist)
int ret = 0;
struct str_node *ent;
strlist__for_each(ent, namelist) {
strlist__for_each_entry(ent, namelist) {
ret = __del_trace_probe_event(fd, ent);
if (ret < 0)
break;
@ -612,7 +612,7 @@ static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
if (ret < (int)iov[1].iov_len + 2)
goto rollback;
strlist__for_each(snode, entry->tevlist) {
strlist__for_each_entry(snode, entry->tevlist) {
iov[0].iov_base = (void *)snode->s;
iov[0].iov_len = strlen(snode->s);
iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1;

View File

@ -957,7 +957,7 @@ static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
if (i >= pevlist->evlist.nr_entries)
return NULL;
evlist__for_each(&pevlist->evlist, pos) {
evlist__for_each_entry(&pevlist->evlist, pos) {
if (i-- == 0)
break;
}

View File

@ -35,7 +35,7 @@ DEFINE_RB_RESORT_RB(threads, strcmp(a->thread->shortname,
struct rb_node *nd;
resort_rb__for_each(nd, threads) {
resort_rb__for_each_entry(nd, threads) {
struct thread *t = threads_entry;
printf("%s: %d\n", t->shortname, t->tid);
}
@ -123,7 +123,7 @@ static void __name##_sorted__init_entry(struct rb_node *nd, \
struct __name##_sorted_entry *__name##_entry; \
struct __name##_sorted *__name = __name##_sorted__new
#define resort_rb__for_each(__nd, __name) \
#define resort_rb__for_each_entry(__nd, __name) \
for (__nd = rb_first(&__name->entries); \
__name##_entry = rb_entry(__nd, struct __name##_sorted_entry, \
rb_node), __nd; \

View File

@ -148,7 +148,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
use_comm_exec = perf_can_comm_exec();
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
perf_evsel__config(evsel, opts, callchain);
if (evsel->tracking && use_comm_exec)
evsel->attr.comm_exec = 1;
@ -161,18 +161,18 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
* match the id.
*/
use_sample_identifier = perf_can_sample_identifier();
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
perf_evsel__set_sample_id(evsel, use_sample_identifier);
} else if (evlist->nr_entries > 1) {
struct perf_evsel *first = perf_evlist__first(evlist);
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.sample_type == first->attr.sample_type)
continue;
use_sample_identifier = perf_can_sample_identifier();
break;
}
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
perf_evsel__set_sample_id(evsel, use_sample_identifier);
}

View File

@ -83,7 +83,7 @@ static bool perf_session__has_comm_exec(struct perf_session *session)
{
struct perf_evsel *evsel;
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
if (evsel->attr.comm_exec)
return true;
}
@ -178,6 +178,8 @@ static void perf_session__delete_threads(struct perf_session *session)
void perf_session__delete(struct perf_session *session)
{
if (session == NULL)
return;
auxtrace__free(session);
auxtrace_index__free(&session->auxtrace_index);
perf_session__destroy_kernel_maps(session);
@ -1870,7 +1872,7 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg)
{
struct perf_evsel *evsel;
evlist__for_each(session->evlist, evsel) {
evlist__for_each_entry(session->evlist, evsel) {
if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
return true;
}
@ -1952,7 +1954,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
{
struct perf_evsel *pos;
evlist__for_each(session->evlist, pos) {
evlist__for_each_entry(session->evlist, pos) {
if (pos->attr.type == type)
return pos;
}
@ -2107,7 +2109,7 @@ int perf_event__synthesize_id_index(struct perf_tool *tool,
max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
sizeof(struct id_index_entry);
evlist__for_each(evlist, evsel)
evlist__for_each_entry(evlist, evsel)
nr += evsel->ids;
n = nr > max_nr ? max_nr : nr;
@ -2120,7 +2122,7 @@ int perf_event__synthesize_id_index(struct perf_tool *tool,
ev->id_index.header.size = sz;
ev->id_index.nr = n;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
u32 j;
for (j = 0; j < evsel->ids; j++) {

View File

@ -79,8 +79,8 @@ static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
{
const char *comm = thread__comm_str(he->thread);
width = max(7U, width) - 6;
return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid,
width = max(7U, width) - 8;
return repsep_snprintf(bf, size, "%7d:%-*.*s", he->thread->tid,
width, width, comm ?: "");
}
@ -95,7 +95,7 @@ static int hist_entry__thread_filter(struct hist_entry *he, int type, const void
}
struct sort_entry sort_thread = {
.se_header = " Pid:Command",
.se_header = " Pid:Command",
.se_cmp = sort__thread_cmp,
.se_snprintf = hist_entry__thread_snprintf,
.se_filter = hist_entry__thread_filter,
@ -2069,7 +2069,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
}
full_name = !!strchr(event_name, ':');
evlist__for_each(evlist, pos) {
evlist__for_each_entry(evlist, pos) {
/* case 2 */
if (full_name && !strcmp(pos->name, event_name))
return pos;
@ -2125,7 +2125,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
int ret;
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
continue;
@ -2143,7 +2143,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
struct perf_evsel *evsel;
struct format_field *field;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
continue;
@ -2456,7 +2456,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist)
if (evlist == NULL)
goto out_no_evlist;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
use_trace = false;
break;

View File

@ -162,7 +162,7 @@ int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
if (perf_evsel__alloc_stats(evsel, alloc_raw))
goto out_free;
}
@ -178,7 +178,7 @@ void perf_evlist__free_stats(struct perf_evlist *evlist)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
perf_evsel__free_stat_priv(evsel);
perf_evsel__free_counts(evsel);
perf_evsel__free_prev_raw_counts(evsel);
@ -189,7 +189,7 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist)
{
struct perf_evsel *evsel;
evlist__for_each(evlist, evsel) {
evlist__for_each_entry(evlist, evsel) {
perf_evsel__reset_stat_priv(evsel);
perf_evsel__reset_counts(evsel);
}

View File

@ -73,7 +73,7 @@ static inline struct str_node *strlist__next(struct str_node *sn)
* @pos: the &struct str_node to use as a loop cursor.
* @slist: the &struct strlist for loop.
*/
#define strlist__for_each(pos, slist) \
#define strlist__for_each_entry(pos, slist) \
for (pos = strlist__first(slist); pos; pos = strlist__next(pos))
/**
@ -83,7 +83,7 @@ static inline struct str_node *strlist__next(struct str_node *sn)
* @n: another &struct str_node to use as temporary storage.
* @slist: the &struct strlist for loop.
*/
#define strlist__for_each_safe(pos, n, slist) \
#define strlist__for_each_entry_safe(pos, n, slist) \
for (pos = strlist__first(slist), n = strlist__next(pos); pos;\
pos = n, n = strlist__next(n))
#endif /* __PERF_STRLIST_H */

View File

@ -1626,7 +1626,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
if (!dirs)
return -1;
strlist__for_each(nd, dirs) {
strlist__for_each_entry(nd, dirs) {
scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
"%s/%s/kallsyms", dir, nd->s);
if (!validate_kcore_addresses(kallsyms_filename, map)) {

View File

@ -616,3 +616,10 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
return err;
}
size_t thread_stack__depth(struct thread *thread)
{
if (!thread->ts)
return 0;
return thread->ts->cnt;
}

View File

@ -87,6 +87,7 @@ void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
size_t sz, u64 ip);
int thread_stack__flush(struct thread *thread);
void thread_stack__free(struct thread *thread);
size_t thread_stack__depth(struct thread *thread);
struct call_return_processor *
call_return_processor__new(int (*process)(struct call_return *cr, void *data),

View File

@ -202,7 +202,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
if (!slist)
return NULL;
strlist__for_each(pos, slist) {
strlist__for_each_entry(pos, slist) {
pid = strtol(pos->s, &end_ptr, 10);
if (pid == INT_MIN || pid == INT_MAX ||
@ -278,7 +278,7 @@ struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
if (!slist)
return NULL;
strlist__for_each(pos, slist) {
strlist__for_each_entry(pos, slist) {
tid = strtol(pos->s, &end_ptr, 10);
if (tid == INT_MIN || tid == INT_MAX ||

View File

@ -462,7 +462,8 @@ static int access_mem(unw_addr_space_t __maybe_unused as,
return 0;
}
ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
ret = perf_reg_value(&start, &ui->sample->user_regs,
LIBUNWIND__ARCH_REG_SP);
if (ret)
return ret;
@ -621,7 +622,8 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
unw_cursor_t c;
int ret, i = 0;
ret = perf_reg_value(&val, &ui->sample->user_regs, PERF_REG_IP);
ret = perf_reg_value(&val, &ui->sample->user_regs,
LIBUNWIND__ARCH_REG_IP);
if (ret)
return ret;

View File

@ -32,6 +32,15 @@ int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
#ifndef LIBUNWIND__ARCH_REG_ID
#define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__arch_reg_id(regnum)
#endif
#ifndef LIBUNWIND__ARCH_REG_SP
#define LIBUNWIND__ARCH_REG_SP PERF_REG_SP
#endif
#ifndef LIBUNWIND__ARCH_REG_IP
#define LIBUNWIND__ARCH_REG_IP PERF_REG_IP
#endif
int LIBUNWIND__ARCH_REG_ID(int regnum);
int unwind__prepare_access(struct thread *thread, struct map *map);
void unwind__flush_access(struct thread *thread);

View File

@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *s
return dso;
}
#if BITS_PER_LONG == 64
static enum dso_type machine__thread_dso_type(struct machine *machine,
struct thread *thread)
{
@ -156,6 +154,8 @@ static enum dso_type machine__thread_dso_type(struct machine *machine,
return dso_type;
}
#if BITS_PER_LONG == 64
static int vdso__do_copy_compat(FILE *f, int fd)
{
char buf[4096];
@ -283,8 +283,38 @@ static int __machine__findnew_vdso_compat(struct machine *machine,
#endif
static struct dso *machine__find_vdso(struct machine *machine,
struct thread *thread)
{
struct dso *dso = NULL;
enum dso_type dso_type;
dso_type = machine__thread_dso_type(machine, thread);
switch (dso_type) {
case DSO__TYPE_32BIT:
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO32, true);
if (!dso) {
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO,
true);
if (dso && dso_type != dso__type(dso, machine))
dso = NULL;
}
break;
case DSO__TYPE_X32BIT:
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSOX32, true);
break;
case DSO__TYPE_64BIT:
case DSO__TYPE_UNKNOWN:
default:
dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
break;
}
return dso;
}
struct dso *machine__findnew_vdso(struct machine *machine,
struct thread *thread __maybe_unused)
struct thread *thread)
{
struct vdso_info *vdso_info;
struct dso *dso = NULL;
@ -297,6 +327,10 @@ struct dso *machine__findnew_vdso(struct machine *machine,
if (!vdso_info)
goto out_unlock;
dso = machine__find_vdso(machine, thread);
if (dso)
goto out_unlock;
#if BITS_PER_LONG == 64
if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso))
goto out_unlock;