perf/core improvements and fixes
Arnaldo Carvalho de Melo
maintainerHi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit cc6cd47e7395bc05c5077009808b820633eb3f18:
perf/x86: Tone down kernel messages when the PMU check fails in a virtual environment (2014-10-03 06:04:41 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.git tags/perf-core-for-mingo
for you to fetch changes up to 2c241bd35e6f626ad6f867dcf9fefdc2315f125f:
perf symbols: Make sym->end be the first address after the symbol range (2014-10-14 17:50:58 -0300)
----------------------------------------------------------------
perf/core improvements and fixes:
Infrastructure:
. Do not include a struct hists per perf_evsel, untangling the histogram code
from perf_evsel, to pave the way for exporting a minimalistic tools/lib/api/perf/ library usable by tools/perf and initially by the rasd daemon being developed by Borislav Petkov, Robert Richter and Jean Pihet. (Arnaldo Carvalho de Melo)
. Make perf_evlist__open(evlist, NULL, NULL), i.e. without cpu and thread
maps mean syswide monitoring, reducing the boilerplate for tools that only want system wide mode. (Arnaldo Carvalho de Melo)
. Fix off-by-one bugs in map->end handling (Stephane Eranian)
. Fix off-by-one bug in maps__find(), also related to map->end handling (Namhyung Kim)
. Make struct symbol->end be the first addr after the symbol range, to make it
match the convention used for struct map->end. (Arnaldo Carvalho de Melo)
. Fix perf_evlist__add_pollfd() error handling in 'perf kvm stat live' (Jiri Olsa)
. Fix python test build by moving callchain_param to an object linked into the
python binding (Jiri Olsa)
----------------------------------------------------------------
Arnaldo Carvalho de Melo (18):
perf sched: Stop updating hists stats, not used
perf script: Stop updating hists stats, not used
perf evsel: Add hists helper
perf session: Don't count per evsel events
perf tools: Move events_stats struct to event.h
perf ui browsers: Add missing include
perf session: Remove last reference to hists struct
perf evsel: Subclassing
perf callchain: Move the callchain_param extern to callchain.h perf tools: Remove hists from evsel
perf thread_map: Create dummy constructor out of open coded equivalent perf evlist: Check that there is a thread_map when preparing a workload perf evlist: Default to syswide target when no thread/cpu maps set perf evsel: Add missing 'target' struct forward declaration perf evsel: Make some exit routines static
perf machine: Add missing dsos->root rbtree root initialization perf symbols: Fix map->end fixup
perf symbols: Make sym->end be the first address after the symbol range
Jiri Olsa (4):
perf kvm stat live: Fix perf_evlist__add_pollfd error handling perf kvm stat live: Use perf_evlist__add_pollfd return fd position perf kvm stat live: Use fdarray object instead of pollfd perf callchain: Move callchain_param to util object in to fix python test
Namhyung Kim (1):
perf tools: Fixup off-by-one comparision in maps__find
Stephane Eranian (1):
perf tools: fix off-by-one error in maps
tools/perf/builtin-annotate.c | 14 +++-- tools/perf/builtin-diff.c | 21 ++++--- tools/perf/builtin-kvm.c | 22 +++---- tools/perf/builtin-record.c | 1 + tools/perf/builtin-report.c | 24 ++++--- tools/perf/builtin-sched.c | 3 - tools/perf/builtin-script.c | 1 - tools/perf/builtin-top.c | 60 ++++++++++-------- tools/perf/tests/builtin-test.c | 5 ++ tools/perf/tests/hists_cumulate.c | 8 +-- tools/perf/tests/hists_filter.c | 23 +++---- tools/perf/tests/hists_link.c | 23 ++++--- tools/perf/tests/hists_output.c | 20 +++--- tools/perf/ui/browsers/header.c | 1 + tools/perf/ui/browsers/hists.c | 20 +++--- tools/perf/ui/gtk/hists.c | 2 +- tools/perf/util/annotate.c | 8 +-- tools/perf/util/callchain.h | 2 + tools/perf/util/event.h | 26 ++++++++ tools/perf/util/evlist.c | 48 +++++++++++++- tools/perf/util/evsel.c | 66 ++++++++++++++----- tools/perf/util/evsel.h | 14 ++--- tools/perf/util/hist.c | 73 +++++++++++++++++----- tools/perf/util/hist.h | 49 +++++++-------- tools/perf/util/machine.c | 10 ++- tools/perf/util/map.c | 8 +-- .../util/scripting-engines/trace-event-python.c | 1 + tools/perf/util/session.c | 23 ------- tools/perf/util/session.h | 1 - tools/perf/util/sort.c | 4 +- tools/perf/util/symbol.c | 8 +-- tools/perf/util/symbol.h | 2 +- tools/perf/util/thread_map.c | 21 ++++--- tools/perf/util/thread_map.h | 1 + tools/perf/util/util.c | 8 +++ 35 files changed, 392 insertions(+), 229 deletions(-)
Arnaldo Carvalho de Melo
maintainerPATCH 1/24 perf kvm stat live: Fix perf_evlist__add_pollfd error handling
From: Jiri Olsa <[email protected]>
With the interface changed in following commit:
2171a9256862 tools lib fd array: Allow associating an integer cookie with each entry
the perf_evlist__add_pollfd function now returns the fd position in the pollfd array.
We need to change this function's error check condition.
--- tools/perf/builtin-kvm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/builtin-kvm.c +2 -2
@@ -928,12 +928,12 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) goto out; } -if (perf_evlist__add_pollfd (kvm->evlist, kvm->timerfd)) +if (perf_evlist__add_pollfd (kvm->evlist, kvm->timerfd) <0 ) goto out; nr_fds++; -if (perf_evlist__add_pollfd (kvm->evlist,fileno (stdin))) +if (perf_evlist__add_pollfd (kvm->evlist,fileno (stdin)) <0 ) goto out; nr_stdin = nr_fds;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 2/24 perf kvm stat live: Use perf_evlist__add_pollfd return fd position
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
With the interface changed in following commit:
2171a9256862 tools lib fd array: Allow associating an integer cookie with each entry
the perf_evlist__add_pollfd function now returns the fd position in the pollfd array.
Hence we no longer need to count the fd position, because we get it as the return value.
--- tools/perf/builtin-kvm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/perf/builtin-kvm.c +2 -2
@@ -933,10 +933,10 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm) nr_fds++; -if (perf_evlist__add_pollfd (kvm->evlist,fileno (stdin)) <0 ) + nr_stdin =perf_evlist__add_pollfd (kvm->evlist,fileno (stdin)); +if (nr_stdin <0 ) goto out; - nr_stdin = nr_fds; nr_fds++;if (fd_set_nonblock (fileno (stdin)) !=0 ) goto out;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 3/24 perf kvm stat live: Use fdarray object instead of pollfd
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
The reason is that we don't need to count the number of file descriptors because it's already handled in fdarray object.
--- tools/perf/builtin-kvm.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-)
tools/perf/builtin-kvm.c +4 -12
@@ -896,8 +896,7 @@ static int perf_kvm__handle_stdin(void)static int kvm_events_live_report (struct perf_kvm_stat *kvm) { -struct pollfd *pollfds =NULL ; -int nr_fds, nr_stdin, ret, err = -EINVAL ; +int nr_stdin, ret, err = -EINVAL ;struct termios save;/* live flag must be set first */
@@ -919,9 +918,6 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)signal (SIGINT , sig_handler);signal (SIGTERM , sig_handler); -/* use pollfds -- need to add timerfd and stdin */ - nr_fds = kvm->evlist->pollfd.nr; -/* add timer fd */ if (perf_kvm__timerfd_create (kvm) <0 ) { err =-1 ;
@@ -931,22 +927,18 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)if (perf_evlist__add_pollfd (kvm->evlist, kvm->timerfd) <0 ) goto out; - nr_fds++; - nr_stdin =perf_evlist__add_pollfd (kvm->evlist,fileno (stdin));if (nr_stdin <0 ) goto out; - nr_fds++;if (fd_set_nonblock (fileno (stdin)) !=0 ) goto out; - pollfds = kvm->evlist->pollfd.entries; -/* everything is good - enable the events and process */ perf_evlist__enable (kvm->evlist);while (!done) { +struct fdarray *fda = &kvm->evlist->pollfd;int rc; rc =perf_kvm__mmap_read (kvm);
@@ -957,11 +949,11 @@ static int kvm_events_live_report(struct perf_kvm_stat *kvm)if (err) goto out; -if (pollfds[nr_stdin].revents &POLLIN ) +if (fda->entries[nr_stdin].revents &POLLIN ) done =perf_kvm__handle_stdin ();if (!rc && !done) - err =poll (pollfds, nr_fds,100 ); + err =fdarray__poll (fda,100 ); }perf_evlist__disable (kvm->evlist);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 4/24 perf callchain: Move callchain_param to util object in to fix python test
In reply to Arnaldo Carvalho de MeloFrom: Jiri Olsa <[email protected]>
In following commit we changed the location of callchains data:
72a128aa083a7f4cc4f800718aaae05d9c698e26
perf tools: Move callchain config from record_opts to callchain_param
Now all callchains stuff stays in callchain_param struct, which adds its dependency for evsel.c object and breaks python perf.so usage (unresolved callchain_param).
Moving callchain_param into callchain.c and adding it into python-ext-sources unleash just another dependency hell, so I ended up adding callchain_param into util.c for now.
--- tools/perf/util/hist.c | 7 ------- tools/perf/util/util.c | 8 ++++++++ 2 files changed, 8 insertions(+), 7 deletions(-)
tools/perf/util/hist.c +0 -7
@@ -14,13 +14,6 @@ static bool hists__filter_entry_by_thread(struct hists *hists,static bool hists__filter_entry_by_symbol (struct hists *hists,struct hist_entry *he); -struct callchain_param callchain_param = { - .mode =CHAIN_GRAPH_REL , - .min_percent =0.5 , - .order =ORDER_CALLEE , - .key =CCKEY_FUNCTION -}; -u16 hists__col_len (struct hists *hists,enum hist_column col) {return hists->col_len[col];
tools/perf/util/util.c +8 -0
@@ -14,6 +14,14 @@#include <byteswap.h> #include <linux/kernel.h> #include <unistd.h> +#include "callchain.h" + +struct callchain_param callchain_param = { + .mode =CHAIN_GRAPH_REL , + .min_percent =0.5 , + .order =ORDER_CALLEE , + .key =CCKEY_FUNCTION +};/* * XXX We need to find a better place for these things...
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 5/24 perf sched: Stop updating hists stats, not used
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Not used here, remove to reduce perf_evsel/hists structs interaction.
--- tools/perf/builtin-sched.c | 3 --- 1 file changed, 3 deletions(-)
tools/perf/builtin-sched.c +0 -3
@@ -1431,9 +1431,6 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_ {int err =0 ; - evsel->hists.stats.total_period += sample->period; -hists__inc_nr_samples (&evsel->hists, true); -if (evsel->handler !=NULL ) {tracepoint_handler f = evsel->handler; err =f (tool, evsel, sample, machine);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 6/24 perf script: Stop updating hists stats, not used
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Not used here, remove to reduce perf_evsel/hists structs interaction.
--- tools/perf/builtin-script.c | 1 - 1 file changed, 1 deletion(-)
tools/perf/builtin-script.c +0 -1
@@ -572,7 +572,6 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, scripting_ops->process_event (event, sample, evsel, thread, &al); - evsel->hists.stats.total_period += sample->period;return 0 ; }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 7/24 perf evsel: Add hists helper
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Not all tools need a hists instance per perf_evsel, so lets pave the way to remove evsel->hists while leaving a way to access the hists from a specially allocated evsel, one that comes with space at the end where lives the evsel.
--- tools/perf/builtin-annotate.c | 8 +++--- tools/perf/builtin-diff.c | 21 ++++++++------- tools/perf/builtin-report.c | 18 +++++++------ tools/perf/builtin-top.c | 55 +++++++++++++++++++++------------------ tools/perf/tests/hists_cumulate.c | 8 +++--- tools/perf/tests/hists_filter.c | 23 ++++++++-------- tools/perf/tests/hists_link.c | 23 ++++++++++------ tools/perf/tests/hists_output.c | 20 +++++++------- tools/perf/ui/browsers/hists.c | 20 ++++++++------ tools/perf/ui/gtk/hists.c | 2 +- tools/perf/util/evsel.h | 5 ++++ tools/perf/util/hist.c | 22 +++++++++------- tools/perf/util/session.c | 4 +-- tools/perf/util/sort.c | 4 +-- 14 files changed, 132 insertions(+), 101 deletions(-)
tools/perf/builtin-annotate.c +4 -4
@@ -51,6 +51,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,struct addr_location *al, struct perf_annotate *ann) { + struct hists *hists = evsel__hists(evsel);struct hist_entry *he;int ret;
@@ -66,13 +67,12 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,return 0 ; } - he =__hists__add_entry (&evsel->hists, al,NULL ,NULL ,NULL ,1 ,1 ,0 , - true); + he =__hists__add_entry (hists, al,NULL ,NULL ,NULL ,1 ,1 ,0 , true);if (he ==NULL )return -ENOMEM ; ret =hist_entry__inc_addr_samples (he, evsel->idx, al->addr); -hists__inc_nr_samples (&evsel->hists, true); +hists__inc_nr_samples (hists, true);return ret; }
@@ -225,7 +225,7 @@ static int __cmd_annotate(struct perf_annotate *ann) total_nr_samples =0 ;evlist__for_each (session->evlist, pos) { -struct hists *hists = &pos->hists; +struct hists *hists =evsel__hists (pos);u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE ];if (nr_samples >0 ) {
tools/perf/builtin-diff.c +12 -9
@@ -327,6 +327,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, struct machine *machine) {struct addr_location al; +struct hists *hists =evsel__hists (evsel);if (perf_event__preprocess_sample (event, machine, &al, sample) <0 ) { pr_warning("problem processing %d event, skipping it.\n",
@@ -334,7 +335,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,return -1 ; } -if (hists__add_entry (&evsel->hists, &al, sample->period, +if (hists__add_entry (hists, &al, sample->period, sample->weight, sample->transaction)) {pr_warning ("problem incrementing symbol period, skipping event\n" );return -1 ;
@@ -346,9 +347,9 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,* hists__output_resort() and precompute needs the total * period in order to sort entries by percentage delta. */ - evsel->hists.stats.total_period += sample->period; + hists->stats.total_period += sample->period;if (!al.filtered) - evsel->hists.stats.total_non_filtered_period += sample->period; + hists->stats.total_non_filtered_period += sample->period;return 0 ; }
@@ -382,7 +383,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)struct perf_evsel *evsel;evlist__for_each (evlist, evsel) { -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);hists__collapse_resort (hists,NULL ); }
@@ -631,24 +632,26 @@ static void data_process(void)bool first = true;evlist__for_each (evlist_base, evsel_base) { +struct hists *hists_base =evsel__hists (evsel_base);struct data__file *d;int i;data__for_each_file_new (i, d) {struct perf_evlist *evlist = d->session->evlist;struct perf_evsel *evsel; +struct hists *hists; evsel =evsel_match (evsel_base, evlist);if (!evsel)continue ; - d->hists = &evsel->hists; + hists =evsel__hists (evsel); + d->hists = hists; -hists__match (&evsel_base->hists, &evsel->hists); +hists__match (hists_base, hists);if (!show_baseline_only) -hists__link (&evsel_base->hists, - &evsel->hists); +hists__link (hists_base, hists); } fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
@@ -659,7 +662,7 @@ static void data_process(void)if (verbose || data__files_cnt >2 )data__fprintf (); -hists__process (&evsel_base->hists); +hists__process (hists_base); } }
tools/perf/builtin-report.c +10 -8
@@ -288,12 +288,14 @@ static size_t hists__fprintf_nr_sample_events(struct hists *hists, struct report evname = buf;for_each_group_member (pos, evsel) { +const struct hists *pos_hists =evsel__hists (pos); +if (symbol_conf.filter_relative) { - nr_samples += pos->hists.stats.nr_non_filtered_samples; - nr_events += pos->hists.stats.total_non_filtered_period; + nr_samples += pos_hists->stats.nr_non_filtered_samples; + nr_events += pos_hists->stats.total_non_filtered_period; }else { - nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE ]; - nr_events += pos->hists.stats.total_period; + nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE ]; + nr_events += pos_hists->stats.total_period; } } }
@@ -318,7 +320,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,struct perf_evsel *pos;evlist__for_each (evlist, pos) { -struct hists *hists = &pos->hists; +struct hists *hists =evsel__hists (pos);const char *evname =perf_evsel__name (pos); if (symbol_conf.event_group &&
@@ -427,7 +429,7 @@ static void report__collapse_hists(struct report *rep)ui_progress__init (&prog, rep->nr_entries,"Merging related events..." );evlist__for_each (rep->session->evlist, pos) { -struct hists *hists = &pos->hists; +struct hists *hists =evsel__hists (pos);if (pos->idx ==0 ) hists->symbol_filter_str = rep->symbol_filter_str;
@@ -437,7 +439,7 @@ static void report__collapse_hists(struct report *rep)/* Non-group events are considered as leader */ if (symbol_conf.event_group && !perf_evsel__is_group_leader (pos)) { -struct hists *leader_hists = &pos->leader->hists; +struct hists *leader_hists =evsel__hists (pos->leader);hists__match (leader_hists, hists);hists__link (leader_hists, hists);
@@ -500,7 +502,7 @@ static int __cmd_report(struct report *rep) }evlist__for_each (session->evlist, pos) -hists__output_resort (&pos->hists); +hists__output_resort (evsel__hists (pos));return report__browse_hists (rep); }
tools/perf/builtin-top.c +30 -25
139 lines not on this page · raw message
tools/perf/tests/hists_cumulate.c +4 -4
@@ -245,7 +245,7 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expecstatic int test1 (struct perf_evsel *evsel,struct machine *machine) {int err; -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);/* * expected output: *
@@ -295,7 +295,7 @@ out:static int test2 (struct perf_evsel *evsel,struct machine *machine) {int err; -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);/* * expected output: *
@@ -442,7 +442,7 @@ out:static int test3 (struct perf_evsel *evsel,struct machine *machine) {int err; -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);/* * expected output: *
@@ -498,7 +498,7 @@ out:static int test4 (struct perf_evsel *evsel,struct machine *machine) {int err; -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);/* * expected output: *
tools/perf/tests/hists_filter.c +12 -11
@@ -66,11 +66,12 @@ static int add_hist_entries(struct perf_evlist *evlist, .ops = &hist_iter_normal, .hide_unresolved = false, }; +struct hists *hists =evsel__hists (evsel);/* make sure it has no filter at first */ - evsel->hists.thread_filter =NULL ; - evsel->hists.dso_filter =NULL ; - evsel->hists.symbol_filter_str =NULL ; + hists->thread_filter =NULL ; + hists->dso_filter =NULL ; + hists->symbol_filter_str =NULL ; sample.pid = fake_samples[i].pid; sample.tid = fake_samples[i].pid;
@@ -134,7 +135,7 @@ int test__hists_filter(void) goto out;evlist__for_each (evlist, evsel) { -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);hists__collapse_resort (hists,NULL );hists__output_resort (hists);
@@ -160,7 +161,7 @@ int test__hists_filter(void) hists->stats.total_non_filtered_period);/* now applying thread filter for 'bash' */ - evsel->hists.thread_filter = fake_samples[9 ].thread; + hists->thread_filter = fake_samples[9 ].thread;hists__filter_by_thread (hists);if (verbose >2 ) {
@@ -185,11 +186,11 @@ int test__hists_filter(void) hists->stats.total_non_filtered_period == 400);/* remove thread filter first */ - evsel->hists.thread_filter =NULL ; + hists->thread_filter =NULL ;hists__filter_by_thread (hists);/* now applying dso filter for 'kernel' */ - evsel->hists.dso_filter = fake_samples[0 ].map->dso; + hists->dso_filter = fake_samples[0 ].map->dso;hists__filter_by_dso (hists);if (verbose >2 ) {
@@ -214,7 +215,7 @@ int test__hists_filter(void) hists->stats.total_non_filtered_period == 300);/* remove dso filter first */ - evsel->hists.dso_filter =NULL ; + hists->dso_filter =NULL ;hists__filter_by_dso (hists);/*
@@ -224,7 +225,7 @@ int test__hists_filter(void)* be counted as a separate entry but the sample count and * total period will be remained. */ - evsel->hists.symbol_filter_str ="main" ; + hists->symbol_filter_str ="main" ;hists__filter_by_symbol (hists);if (verbose >2 ) {
@@ -249,8 +250,8 @@ int test__hists_filter(void) hists->stats.total_non_filtered_period == 300);/* now applying all filters at once. */ - evsel->hists.thread_filter = fake_samples[1 ].thread; - evsel->hists.dso_filter = fake_samples[1 ].map->dso; + hists->thread_filter = fake_samples[1 ].thread; + hists->dso_filter = fake_samples[1 ].map->dso;hists__filter_by_thread (hists);hists__filter_by_dso (hists);
tools/perf/tests/hists_link.c +15 -8
@@ -73,6 +73,8 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)* "bash [libc] malloc" so total 9 entries will be in the tree. */ evlist__for_each (evlist, evsel) { +struct hists *hists =evsel__hists (evsel); +for (k =0 ; k <ARRAY_SIZE (fake_common_samples); k++) {const union perf_event event = { .header = {
@@ -87,7 +89,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) &sample) < 0) goto out; - he =__hists__add_entry (&evsel->hists, &al,NULL , + he =__hists__add_entry (hists, &al,NULL ,NULL ,NULL ,1 ,1 ,0 , true);if (he ==NULL ) goto out;
@@ -111,7 +113,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) &sample) < 0) goto out; - he =__hists__add_entry (&evsel->hists, &al,NULL , + he =__hists__add_entry (hists, &al,NULL ,NULL ,NULL ,1 ,1 ,0 , true);if (he ==NULL ) goto out;
@@ -271,6 +273,7 @@ static int validate_link(struct hists *leader, struct hists *other)int test__hists_link (void ) {int err =-1 ; +struct hists *hists, *first_hists;struct machines machines;struct machine *machine =NULL ;struct perf_evsel *evsel, *first;
@@ -306,24 +309,28 @@ int test__hists_link(void) goto out;evlist__for_each (evlist, evsel) { -hists__collapse_resort (&evsel->hists,NULL ); + hists =evsel__hists (evsel); +hists__collapse_resort (hists,NULL );if (verbose >2 ) -print_hists_in (&evsel->hists); +print_hists_in (hists); } first =perf_evlist__first (evlist); evsel =perf_evlist__last (evlist); + first_hists =evsel__hists (first); + hists =evsel__hists (evsel); +/* match common entries */ -hists__match (&first->hists, &evsel->hists); - err =validate_match (&first->hists, &evsel->hists); +hists__match (first_hists, hists); + err =validate_match (first_hists, hists);if (err) goto out;/* link common and/or dummy entries */ -hists__link (&first->hists, &evsel->hists); - err =validate_link (&first->hists, &evsel->hists); +hists__link (first_hists, hists); + err =validate_link (first_hists, hists);if (err) goto out;
tools/perf/tests/hists_output.c +10 -10
@@ -122,7 +122,7 @@ typedef int (*test_fn_t)(struct perf_evsel *, struct machine *);static int test1 (struct perf_evsel *evsel,struct machine *machine) {int err; -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);struct hist_entry *he;struct rb_root *root;struct rb_node *node;
@@ -159,7 +159,7 @@ static int test1(struct perf_evsel *evsel, struct machine *machine)print_hists_out (hists); } - root = &evsel->hists.entries; + root = &hists->entries; node =rb_first (root); he = rb_entry(node, struct hist_entry, rb_node); TEST_ASSERT_VAL("Invalid hist entry",
@@ -224,7 +224,7 @@ out:static int test2 (struct perf_evsel *evsel,struct machine *machine) {int err; -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);struct hist_entry *he;struct rb_root *root;struct rb_node *node;
@@ -259,7 +259,7 @@ static int test2(struct perf_evsel *evsel, struct machine *machine)print_hists_out (hists); } - root = &evsel->hists.entries; + root = &hists->entries; node =rb_first (root); he = rb_entry(node, struct hist_entry, rb_node); TEST_ASSERT_VAL("Invalid hist entry",
@@ -280,7 +280,7 @@ out:static int test3 (struct perf_evsel *evsel,struct machine *machine) {int err; -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);struct hist_entry *he;struct rb_root *root;struct rb_node *node;
@@ -313,7 +313,7 @@ static int test3(struct perf_evsel *evsel, struct machine *machine)print_hists_out (hists); } - root = &evsel->hists.entries; + root = &hists->entries; node =rb_first (root); he = rb_entry(node, struct hist_entry, rb_node); TEST_ASSERT_VAL("Invalid hist entry",
@@ -354,7 +354,7 @@ out:static int test4 (struct perf_evsel *evsel,struct machine *machine) {int err; -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);struct hist_entry *he;struct rb_root *root;struct rb_node *node;
@@ -391,7 +391,7 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)print_hists_out (hists); } - root = &evsel->hists.entries; + root = &hists->entries; node =rb_first (root); he = rb_entry(node, struct hist_entry, rb_node); TEST_ASSERT_VAL("Invalid hist entry",
@@ -456,7 +456,7 @@ out:static int test5 (struct perf_evsel *evsel,struct machine *machine) {int err; -struct hists *hists = &evsel->hists; +struct hists *hists =evsel__hists (evsel);struct hist_entry *he;struct rb_root *root;struct rb_node *node;
@@ -494,7 +494,7 @@ static int test5(struct perf_evsel *evsel, struct machine *machine)print_hists_out (hists); } - root = &evsel->hists.entries; + root = &hists->entries; node =rb_first (root); he = rb_entry(node, struct hist_entry, rb_node);
tools/perf/ui/browsers/hists.c +12 -8
@@ -1229,12 +1229,14 @@ static int hists__browser_title(struct hists *hists, char *bf, size_t size) ev_name = buf;for_each_group_member (pos, evsel) { +struct hists *pos_hists =evsel__hists (pos); +if (symbol_conf.filter_relative) { - nr_samples += pos->hists.stats.nr_non_filtered_samples; - nr_events += pos->hists.stats.total_non_filtered_period; + nr_samples += pos_hists->stats.nr_non_filtered_samples; + nr_events += pos_hists->stats.total_non_filtered_period; }else { - nr_samples += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE ]; - nr_events += pos->hists.stats.total_period; + nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE ]; + nr_events += pos_hists->stats.total_period; } } }
@@ -1387,7 +1389,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,float min_pcnt, struct perf_session_env *env) { - struct hists *hists = &evsel->hists; + struct hists *hists = evsel__hists(evsel);struct hist_browser *browser =hist_browser__new (hists);struct branch_info *bi;struct pstack *fstack;
@@ -1802,8 +1804,9 @@ static void perf_evsel_menu__write(struct ui_browser *browser,struct perf_evsel_menu *menu =container_of (browser, struct perf_evsel_menu, b); struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node); +struct hists *hists =evsel__hists (evsel);bool current_entry =ui_browser__is_current_entry (browser, row); -unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE ]; +unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE ];const char *ev_name =perf_evsel__name (evsel);char bf[256 ], unit;const char *warn =" " ;
@@ -1818,7 +1821,8 @@ static void perf_evsel_menu__write(struct ui_browser *browser, ev_name =perf_evsel__group_name (evsel);for_each_group_member (pos, evsel) { - nr_events += pos->hists.stats.nr_events[PERF_RECORD_SAMPLE ]; +struct hists *pos_hists =evsel__hists (pos); + nr_events += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE ]; } }
@@ -1827,7 +1831,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser, unit, unit == ' ' ? "" : " ", ev_name);slsmg_printf ("%s" , bf); - nr_events = evsel->hists.stats.nr_events[PERF_RECORD_LOST ]; + nr_events = hists->stats.nr_events[PERF_RECORD_LOST ];if (nr_events !=0 ) { menu->lost_events = true;if (!current_entry)
tools/perf/ui/gtk/hists.c +1 -1
@@ -319,7 +319,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,gtk_container_add (GTK_CONTAINER (window), vbox);evlist__for_each (evlist, pos) { -struct hists *hists = &pos->hists; +struct hists *hists =evsel__hists (pos);const char *evname =perf_evsel__name (pos);GtkWidget *scrolled_window;GtkWidget *tab_label;
tools/perf/util/evsel.h +5 -0
@@ -102,6 +102,11 @@ union u64_swap {#define hists_to_evsel (h) container_of(h, struct perf_evsel, hists) +static inline struct hists *evsel__hists (struct perf_evsel *evsel) +{ +return &evsel->hists; +} +struct cpu_map ;struct thread_map ;struct perf_evlist ;
tools/perf/util/hist.c +13 -9
@@ -509,6 +509,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al {u64 cost;struct mem_info *mi = iter->priv; +struct hists *hists =evsel__hists (iter->evsel);struct hist_entry *he;if (mi ==NULL )
@@ -525,7 +526,7 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al* and this is indirectly achieved by passing period=weight here * and the he_stat__add_period() function. */ - he =__hists__add_entry (&iter->evsel->hists, al, iter->parent,NULL , mi, + he =__hists__add_entry (hists, al, iter->parent,NULL , mi, cost, cost,0 , true);if (!he)return -ENOMEM ;
@@ -539,13 +540,14 @@ iter_finish_mem_entry(struct hist_entry_iter *iter, struct addr_location *al __maybe_unused) {struct perf_evsel *evsel = iter->evsel; +struct hists *hists =evsel__hists (evsel);struct hist_entry *he = iter->he;int err = -EINVAL ;if (he ==NULL ) goto out; -hists__inc_nr_samples (&evsel->hists, he->filtered); +hists__inc_nr_samples (hists, he->filtered); err =hist_entry__append_callchain (he, iter->sample);
@@ -611,6 +613,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a {struct branch_info *bi;struct perf_evsel *evsel = iter->evsel; +struct hists *hists =evsel__hists (evsel);struct hist_entry *he =NULL ;int i = iter->curr;int err =0 ;
@@ -624,12 +627,12 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a* The report shows the percentage of total branches captured * and not events sampled. Thus we use a pseudo period of 1. */ - he =__hists__add_entry (&evsel->hists, al, iter->parent, &bi[i],NULL , + he =__hists__add_entry (hists, al, iter->parent, &bi[i],NULL ,1 ,1 ,0 , true);if (he ==NULL )return -ENOMEM ; -hists__inc_nr_samples (&evsel->hists, he->filtered); +hists__inc_nr_samples (hists, he->filtered); out: iter->he = he;
@@ -661,7 +664,7 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_locationstruct perf_sample *sample = iter->sample;struct hist_entry *he; - he =__hists__add_entry (&evsel->hists, al, iter->parent,NULL ,NULL , + he =__hists__add_entry (evsel__hists (evsel), al, iter->parent,NULL ,NULL , sample->period, sample->weight, sample->transaction, true);if (he ==NULL )
@@ -684,7 +687,7 @@ iter_finish_normal_entry(struct hist_entry_iter *iter, iter->he =NULL ; -hists__inc_nr_samples (&evsel->hists, he->filtered); +hists__inc_nr_samples (evsel__hists (evsel), he->filtered);return hist_entry__append_callchain (he, sample); }
@@ -717,12 +720,13 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter, struct addr_location *al) {struct perf_evsel *evsel = iter->evsel; +struct hists *hists =evsel__hists (evsel);struct perf_sample *sample = iter->sample;struct hist_entry **he_cache = iter->priv;struct hist_entry *he;int err =0 ; - he =__hists__add_entry (&evsel->hists, al, iter->parent,NULL ,NULL , + he =__hists__add_entry (hists, al, iter->parent,NULL ,NULL , sample->period, sample->weight, sample->transaction, true);if (he ==NULL )
@@ -739,7 +743,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,*/ callchain_cursor_commit (&callchain_cursor); -hists__inc_nr_samples (&evsel->hists, he->filtered); +hists__inc_nr_samples (hists, he->filtered);return err; }
@@ -795,7 +799,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter, } } - he =__hists__add_entry (&evsel->hists, al, iter->parent,NULL ,NULL , + he =__hists__add_entry (evsel__hists (evsel), al, iter->parent,NULL ,NULL , sample->period, sample->weight, sample->transaction, false);if (he ==NULL )
tools/perf/util/session.c +2 -2
@@ -827,7 +827,7 @@ int perf_session__deliver_event(struct perf_session *session,* future probably it'll be a good idea to restrict event * processing via perf_session to files with both set. */ -hists__inc_nr_events (&evsel->hists, event->header.type); +hists__inc_nr_events (evsel__hists (evsel), event->header.type); } machine = perf_session__find_machine_for_cpumode(session, event,
@@ -1398,7 +1398,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)evlist__for_each (session->evlist, pos) { ret +=fprintf (fp,"%s stats:\n" ,perf_evsel__name (pos)); - ret +=events_stats__fprintf (&pos->hists.stats, fp); + ret +=events_stats__fprintf (&evsel__hists (pos)->stats, fp); }return ret;
tools/perf/util/sort.c +2 -2
@@ -1218,7 +1218,7 @@ static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, hse = container_of(fmt, struct hpp_sort_entry, hpp);if (!len) - len =hists__col_len (&evsel->hists, hse->se->se_width_idx); + len =hists__col_len (evsel__hists (evsel), hse->se->se_width_idx);return scnprintf (hpp->buf, hpp->size,"%-*.*s" , len, len, fmt->name); }
@@ -1233,7 +1233,7 @@ static int __sort__hpp_width(struct perf_hpp_fmt *fmt, hse = container_of(fmt, struct hpp_sort_entry, hpp);if (!len) - len =hists__col_len (&evsel->hists, hse->se->se_width_idx); + len =hists__col_len (evsel__hists (evsel), hse->se->se_width_idx);return len; }
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 8/24 perf session: Don't count per evsel events
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
PERF_RECORD_SAMPLE was not being counted here and is the only per-evsel thing anyway, the other events were not mapping to a evsel.
With this we don't require that evsels used with a perf_session need to have space for hists, like the ones in annotate, report, top.
--- tools/perf/util/session.c | 16 ---------------- 1 file changed, 16 deletions(-)
tools/perf/util/session.c +0 -16
@@ -813,22 +813,6 @@ int perf_session__deliver_event(struct perf_session *session,dump_event (session, event, file_offset, sample); evsel =perf_evlist__id2evsel (session->evlist, sample->id); -if (evsel !=NULL && event->header.type !=PERF_RECORD_SAMPLE ) { -/* -* XXX We're leaving PERF_RECORD_SAMPLE unnacounted here -* because the tools right now may apply filters, discarding -* some of the samples. For consistency, in the future we -* should have something like nr_filtered_samples and remove -* the sample->period from total_sample_period, etc, KISS for -* now tho. -* -* Also testing against NULL allows us to handle files without -* attr.sample_id_all and/or without PERF_SAMPLE_ID. In the -* future probably it'll be a good idea to restrict event -* processing via perf_session to files with both set. -*/ -hists__inc_nr_events (evsel__hists (evsel), event->header.type); - } machine =perf_session__find_machine_for_cpumode (session, event, sample);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 9/24 perf tools: Move events_stats struct to event.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This is the only bit of hist.h that session.[ch] will end up using, so move it out of hist.h to make that abundantly clear.
--- tools/perf/util/event.h | 26 ++++++++++++++++++++++++++ tools/perf/util/hist.h | 26 -------------------------- 2 files changed, 26 insertions(+), 26 deletions(-)
tools/perf/util/event.h +26 -0
@@ -190,6 +190,32 @@ enum perf_user_event_type { /* above any possible kernel type */PERF_RECORD_HEADER_MAX }; +/* +* The kernel collects the number of events it couldn't send in a stretch and +* when possible sends this number in a PERF_RECORD_LOST event. The number of +* such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while +* total_lost tells exactly how many events the kernel in fact lost, i.e. it is +* the sum of all struct lost_event.lost fields reported. +* +* The total_period is needed because by default auto-freq is used, so +* multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get +* the total number of low level events, it is necessary to to sum all struct +* sample_event.period and stash the result in total_period. +*/ +struct events_stats { +u64 total_period; +u64 total_non_filtered_period; +u64 total_lost; +u64 total_invalid_chains; +u32 nr_events[PERF_RECORD_HEADER_MAX ]; +u32 nr_non_filtered_samples; +u32 nr_lost_warned; +u32 nr_unknown_events; +u32 nr_invalid_chains; +u32 nr_unknown_id; +u32 nr_unprocessable_samples; +}; +struct attr_event {struct perf_event_header header;struct perf_event_attr attr;
tools/perf/util/hist.h +0 -26
@@ -23,32 +23,6 @@ enum hist_filter { HIST_FILTER__HOST, }; -/* -* The kernel collects the number of events it couldn't send in a stretch and -* when possible sends this number in a PERF_RECORD_LOST event. The number of -* such "chunks" of lost events is stored in .nr_events[PERF_EVENT_LOST] while -* total_lost tells exactly how many events the kernel in fact lost, i.e. it is -* the sum of all struct lost_event.lost fields reported. -* -* The total_period is needed because by default auto-freq is used, so -* multipling nr_events[PERF_EVENT_SAMPLE] by a frequency isn't possible to get -* the total number of low level events, it is necessary to to sum all struct -* sample_event.period and stash the result in total_period. -*/ -struct events_stats { -u64 total_period; -u64 total_non_filtered_period; -u64 total_lost; -u64 total_invalid_chains; -u32 nr_events[PERF_RECORD_HEADER_MAX ]; -u32 nr_non_filtered_samples; -u32 nr_lost_warned; -u32 nr_unknown_events; -u32 nr_invalid_chains; -u32 nr_unknown_id; -u32 nr_unprocessable_samples; -}; -enum hist_column {HISTC_SYMBOL ,HISTC_DSO ,
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 10/24 perf ui browsers: Add missing include
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
This file needs the K_{RIGHT,etc} definitions but isn't including the file where they are defined, ui/keysyms.h, fix it.
--- tools/perf/ui/browsers/header.c | 1 + 1 file changed, 1 insertion(+)
tools/perf/ui/browsers/header.c +1 -0
@@ -1,6 +1,7 @@#include "util/cache.h" #include "util/debug.h" #include "ui/browser.h" +#include "ui/keysyms.h" #include "ui/ui.h" #include "ui/util.h" #include "ui/libslang.h"
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 11/24 perf session: Remove last reference to hists struct
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Now perf_session doesn't require that the evsels in its evlist are hists containing ones.
Tools that are hists based and want to do per evsel events_stats updates, if at some point this turns into a necessity, should do it in the tool specific code, keeping the session class hists agnostic.
--- tools/perf/builtin-annotate.c | 1 + tools/perf/builtin-report.c | 1 + tools/perf/util/hist.c | 16 ++++++++++++++++ tools/perf/util/hist.h | 1 + tools/perf/util/session.c | 7 ------- tools/perf/util/session.h | 1 - 6 files changed, 19 insertions(+), 8 deletions(-)
tools/perf/builtin-annotate.c +1 -0
@@ -214,6 +214,7 @@ static int __cmd_annotate(struct perf_annotate *ann)if (dump_trace) {perf_session__fprintf_nr_events (session, stdout); +perf_evlist__fprintf_nr_events (session->evlist, stdout); goto out; }
tools/perf/builtin-report.c +1 -0
@@ -487,6 +487,7 @@ static int __cmd_report(struct report *rep)if (dump_trace) {perf_session__fprintf_nr_events (session, stdout); +perf_evlist__fprintf_nr_events (session->evlist, stdout);return 0 ; } }
tools/perf/util/hist.c +16 -0
@@ -3,6 +3,7 @@#include "hist.h" #include "session.h" #include "sort.h" +#include "evlist.h" #include "evsel.h" #include "annotate.h" #include <math.h>
@@ -1405,6 +1406,21 @@ int hists__link(struct hists *leader, struct hists *other)return 0 ; } + +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) { + ret +=fprintf (fp,"%s stats:\n" ,perf_evsel__name (pos)); + ret +=events_stats__fprintf (&evsel__hists (pos)->stats, fp); + } + +return ret; +} + +u64 hists__total_period (struct hists *hists) { return symbol_conf.filter_relative ? hists->stats.total_non_filtered_period :
tools/perf/util/hist.h +1 -0
@@ -139,6 +139,7 @@ size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);size_t hists__fprintf (struct hists *hists,bool show_header,int max_rows,int max_cols,float min_pcnt,FILE *fp); +size_t perf_evlist__fprintf_nr_events (struct perf_evlist *evlist,FILE *fp);void hists__filter_by_dso (struct hists *hists);void hists__filter_by_thread (struct hists *hists);
tools/perf/util/session.c +0 -7
@@ -1375,16 +1375,9 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *session, FILE *fpsize_t perf_session__fprintf_nr_events (struct perf_session *session,FILE *fp) { -struct perf_evsel *pos;size_t ret =fprintf (fp,"Aggregated stats:\n" ); ret +=events_stats__fprintf (&session->stats, fp); - -evlist__for_each (session->evlist, pos) { - ret +=fprintf (fp,"%s stats:\n" ,perf_evsel__name (pos)); - ret +=events_stats__fprintf (&evsel__hists (pos)->stats, fp); - } -return ret; }
tools/perf/util/session.h +0 -1
@@ -2,7 +2,6 @@#define __PERF_SESSION_H#include "trace-event.h" -#include "hist.h" #include "event.h" #include "header.h" #include "machine.h"
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 12/24 perf evsel: Subclassing
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Provide a method to be called at tool start to config the perf_evsel instance size, together with optional constructor and destructor.
This will be used so that perf_evsel doesn't always include a struct hists, tools that works with hists/hist_entries, like report, top and annotate, will, at start, tell the evsel class the size they need per instance.
v2: Don't use exit as a name of a member of function parameter, as this
breaks the build on at least fedora14 and rhel6.
--- tools/perf/util/evsel.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- tools/perf/util/evsel.h | 4 ++++ 2 files changed, 50 insertions(+), 2 deletions(-)
tools/perf/util/evsel.c +46 -2
@@ -32,6 +32,48 @@ static struct {bool cloexec; } perf_missing_features; +static int perf_evsel__no_extra_init (struct perf_evsel *evsel__maybe_unused ) +{ +return 0 ; +} + +static void perf_evsel__no_extra_fini (struct perf_evsel *evsel__maybe_unused ) +{ +} + +static struct { +size_t size; +int (*init)(struct perf_evsel *evsel); +void (*fini)(struct perf_evsel *evsel); +} perf_evsel__object = { + .size =sizeof (struct perf_evsel ), + .init = perf_evsel__no_extra_init, + .fini = perf_evsel__no_extra_fini, +}; + +int perf_evsel__object_config (size_t object_size, +int (*init)(struct perf_evsel *evsel), +void (*fini)(struct perf_evsel *evsel)) +{ + +if (object_size ==0 ) + goto set_methods; + +if (perf_evsel__object.size > object_size) +return -EINVAL ; + + perf_evsel__object.size = object_size; + +set_methods: +if (init !=NULL ) + perf_evsel__object.init = init; + +if (fini !=NULL ) + perf_evsel__object.fini = fini; + +return 0 ; +} +#define FD (e, x, y) (*(int *)xyarray__entry(e->fd, x, y))int __perf_evsel__sample_size (u64 sample_type)
@@ -169,13 +211,14 @@ void perf_evsel__init(struct perf_evsel *evsel, evsel->scale =1.0 ;INIT_LIST_HEAD (&evsel->node);hists__init (&evsel->hists); + perf_evsel__object.init (evsel); evsel->sample_size =__perf_evsel__sample_size (attr->sample_type);perf_evsel__calc_id_pos (evsel); }struct perf_evsel *perf_evsel__new_idx (struct perf_event_attr *attr,int idx) { -struct perf_evsel *evsel =zalloc (sizeof (*evsel)); +struct perf_evsel *evsel =zalloc (perf_evsel__object.size);if (evsel !=NULL )perf_evsel__init (evsel, attr, idx);
@@ -185,7 +228,7 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)struct perf_evsel *perf_evsel__newtp_idx (const char *sys,const char *name,int idx) { -struct perf_evsel *evsel =zalloc (sizeof (*evsel)); +struct perf_evsel *evsel =zalloc (perf_evsel__object.size);if (evsel !=NULL ) { struct perf_event_attr attr = {
@@ -817,6 +860,7 @@ void perf_evsel__exit(struct perf_evsel *evsel)assert (list_empty (&evsel->node));perf_evsel__free_fd (evsel);perf_evsel__free_id (evsel); + perf_evsel__object.fini (evsel); }void perf_evsel__delete (struct perf_evsel *evsel)
tools/perf/util/evsel.h +4 -0
@@ -112,6 +112,10 @@ struct thread_map;struct perf_evlist ;struct record_opts ; +int perf_evsel__object_config (size_t object_size, +int (*init)(struct perf_evsel *evsel), +void (*fini)(struct perf_evsel *evsel)); +struct perf_evsel *perf_evsel__new_idx (struct perf_event_attr *attr,int idx);static inline struct perf_evsel *perf_evsel__new (struct perf_event_attr *attr)
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 13/24 perf callchain: Move the callchain_param extern to callchain.h
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
It was lost in hist.h, move it to where it belongs, callchain.h, as there are places that gets hist.h by means of evsel.h, and since evsel.h is being untangled from hist.h...
--- tools/perf/builtin-record.c | 1 + tools/perf/util/callchain.h | 2 ++ tools/perf/util/evsel.c | 1 + tools/perf/util/hist.h | 2 -- tools/perf/util/scripting-engines/trace-event-python.c | 1 + 5 files changed, 5 insertions(+), 2 deletions(-)
tools/perf/builtin-record.c +1 -0
@@ -14,6 +14,7 @@#include "util/parse-options.h" #include "util/parse-events.h" +#include "util/callchain.h" #include "util/header.h" #include "util/event.h" #include "util/evlist.h"
tools/perf/util/callchain.h +2 -0
@@ -65,6 +65,8 @@ struct callchain_param {enum chain_key key; }; +extern struct callchain_param callchain_param; +struct callchain_list {u64 ip;struct map_symbol ms;
tools/perf/util/evsel.c +1 -0
@@ -15,6 +15,7 @@#include <linux/perf_event.h> #include <sys/resource.h> #include "asm/bug.h" +#include "callchain.h" #include "evsel.h" #include "evlist.h" #include "util.h"
tools/perf/util/hist.h +0 -2
@@ -8,8 +8,6 @@#include "color.h" #include "ui/progress.h" -extern struct callchain_param callchain_param; -struct hist_entry ;struct addr_location ;struct symbol ;
tools/perf/util/scripting-engines/trace-event-python.c +1 -0
@@ -28,6 +28,7 @@#include "../../perf.h" #include "../debug.h" +#include "../callchain.h" #include "../evsel.h" #include "../util.h" #include "../event.h"
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 14/24 perf tools: Remove hists from evsel
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Now tools that deals want to have an hists per evsel need to call hists__init() before creating any evsels, which can be as early as when parsing the command line, so do it before calling parse_options().
The current tools using hists/hist_entries are report, top and annotate, change them to request per evsel hists.
This is in preparation for making evsels usable by 3rd party tools, that not necessarily live in perf's source code repository.
--- tools/perf/builtin-annotate.c | 5 ++++- tools/perf/builtin-report.c | 5 ++++- tools/perf/builtin-top.c | 5 ++++- tools/perf/tests/builtin-test.c | 5 +++++ tools/perf/util/evsel.c | 11 ----------- tools/perf/util/evsel.h | 11 ----------- tools/perf/util/hist.c | 28 ++++++++++++++++++++++++++++ tools/perf/util/hist.h | 20 ++++++++++++++++++++ 8 files changed, 65 insertions(+), 25 deletions(-)
tools/perf/builtin-annotate.c +4 -1
@@ -326,7 +326,10 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused) "Show event group information together"), OPT_END() }; -int ret; +int ret =hists__init (); + +if (ret <0 ) +return ret; argc =parse_options (argc, argv, options, annotate_usage,0 );
tools/perf/builtin-report.c +4 -1
@@ -568,7 +568,6 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)struct stat st;bool has_br_stack = false;int branch_mode =-1 ; -int ret =-1 ;char callchain_default_opt[] ="fractal,0.5,callee" ;const char *const report_usage[] = {"perf report [<options>]" ,
@@ -695,6 +694,10 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)struct perf_data_file file = { .mode =PERF_DATA_MODE_READ , }; +int ret =hists__init (); + +if (ret <0 ) +return ret;perf_config (report__config, &report);
tools/perf/builtin-top.c +4 -1
@@ -1047,7 +1047,6 @@ parse_percent_limit(const struct option *opt, const char *arg,int cmd_top (int argc,const char **argv,const char *prefix__maybe_unused ) { -int status =-1 ;char errbuf[BUFSIZ ];struct perf_top top = { .count_filter =5 ,
@@ -1165,6 +1164,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)"perf top [<options>]" , NULL }; +int status =hists__init (); + +if (status <0 ) +return status; top.evlist =perf_evlist__new ();if (top.evlist ==NULL )
tools/perf/tests/builtin-test.c +5 -0
@@ -6,6 +6,7 @@#include <unistd.h> #include <string.h> #include "builtin.h" +#include "hist.h" #include "intlist.h" #include "tests.h" #include "debug.h"
@@ -302,6 +303,10 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused) OPT_END() };struct intlist *skiplist =NULL ; +int ret =hists__init (); + +if (ret <0 ) +return ret; argc =parse_options (argc, argv, test_options, test_usage,0 );if (argc >=1 && !strcmp (argv[0 ],"list" ))
tools/perf/util/evsel.c +0 -11
@@ -159,16 +159,6 @@ void perf_evsel__calc_id_pos(struct perf_evsel *evsel) evsel->is_pos =__perf_evsel__calc_is_pos (evsel->attr.sample_type); } -void hists__init (struct hists *hists) -{ -memset (hists,0 ,sizeof (*hists)); - hists->entries_in_array[0 ] = hists->entries_in_array[1 ] =RB_ROOT ; - hists->entries_in = &hists->entries_in_array[0 ]; - hists->entries_collapsed =RB_ROOT ; - hists->entries =RB_ROOT ; -pthread_mutex_init (&hists->lock,NULL ); -} -void __perf_evsel__set_sample_bit (struct perf_evsel *evsel,enum perf_event_sample_format bit) {
@@ -211,7 +201,6 @@ void perf_evsel__init(struct perf_evsel *evsel, evsel->unit ="" ; evsel->scale =1.0 ;INIT_LIST_HEAD (&evsel->node); -hists__init (&evsel->hists); perf_evsel__object.init (evsel); evsel->sample_size =__perf_evsel__sample_size (attr->sample_type);perf_evsel__calc_id_pos (evsel);
tools/perf/util/evsel.h +0 -11
@@ -8,7 +8,6 @@#include <linux/types.h> #include "xyarray.h" #include "cgroup.h" -#include "hist.h" #include "symbol.h" struct perf_counts_values {
@@ -66,7 +65,6 @@ struct perf_evsel {struct perf_counts *prev_raw_counts;int idx;u32 ids; -struct hists hists;char *name;double scale;const char *unit;
@@ -100,13 +98,6 @@ union u64_swap {u32 val32[2 ]; }; -#define hists_to_evsel (h) container_of(h, struct perf_evsel, hists) - -static inline struct hists *evsel__hists (struct perf_evsel *evsel) -{ -return &evsel->hists; -} -struct cpu_map ;struct thread_map ;struct perf_evlist ;
@@ -290,8 +281,6 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,return __perf_evsel__read (evsel, ncpus, nthreads, true); } -void hists__init (struct hists *hists); -int perf_evsel__parse_sample (struct perf_evsel *evsel,union perf_event *event,struct perf_sample *sample);
tools/perf/util/hist.c +28 -0
@@ -1447,3 +1447,31 @@ int perf_hist_config(const char *var, const char *value)return 0 ; } + +static int hists_evsel__init (struct perf_evsel *evsel) +{ +struct hists *hists =evsel__hists (evsel); + +memset (hists,0 ,sizeof (*hists)); + hists->entries_in_array[0 ] = hists->entries_in_array[1 ] =RB_ROOT ; + hists->entries_in = &hists->entries_in_array[0 ]; + hists->entries_collapsed =RB_ROOT ; + hists->entries =RB_ROOT ; +pthread_mutex_init (&hists->lock,NULL ); +return 0 ; +} + +/* +* XXX We probably need a hists_evsel__exit() to free the hist_entries +* stored in the rbtree... +*/ + +int hists__init (void ) +{ +int err =perf_evsel__object_config (sizeof (struct hists_evsel ), + hists_evsel__init,NULL ); +if (err) +fputs ("FATAL ERROR: Couldn't setup hists class\n" , stderr); + +return err; +}
tools/perf/util/hist.h +20 -0
@@ -4,6 +4,7 @@#include <linux/types.h> #include <pthread.h> #include "callchain.h" +#include "evsel.h" #include "header.h" #include "color.h" #include "ui/progress.h"
@@ -158,6 +159,25 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *he);void hists__match (struct hists *leader,struct hists *other);int hists__link (struct hists *leader,struct hists *other); +struct hists_evsel { +struct perf_evsel evsel; +struct hists hists; +}; + +static inline struct perf_evsel *hists_to_evsel (struct hists *hists) +{ + struct hists_evsel *hevsel = container_of(hists, struct hists_evsel, hists); +return &hevsel->evsel; +} + +static inline struct hists *evsel__hists (struct perf_evsel *evsel) +{ +struct hists_evsel *hevsel = (struct hists_evsel *)evsel; +return &hevsel->hists; +} + +int hists__init (void ); +struct perf_hpp {char *buf;size_t size;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 15/24 perf thread_map: Create dummy constructor out of open coded equivalent
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Create a dummy thread_map, one that has just one entry and it is -1, meaning 'all threads', as this ends up going down to perf_event_open().
--- tools/perf/util/thread_map.c | 21 +++++++++++++-------- tools/perf/util/thread_map.h | 1 + 2 files changed, 14 insertions(+), 8 deletions(-)
tools/perf/util/thread_map.c +13 -8
@@ -214,6 +214,17 @@ out_free_threads: goto out; } +struct thread_map *thread_map__new_dummy (void ) +{ +struct thread_map *threads =malloc (sizeof (*threads) +sizeof (pid_t)); + +if (threads !=NULL ) { + threads->map[0 ] =-1 ; + threads->nr =1 ; + } +return threads; +} +static struct thread_map *thread_map__new_by_tid_str (const char *tid_str) {struct thread_map *threads =NULL , *nt;
@@ -224,14 +235,8 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)struct strlist *slist;/* perf-stat expects threads to be generated even if tid not given */ -if (!tid_str) { - threads =malloc (sizeof (*threads) +sizeof (pid_t)); -if (threads !=NULL ) { - threads->map[0 ] =-1 ; - threads->nr =1 ; - } -return threads; - } +if (!tid_str) +return thread_map__new_dummy (); slist =strlist__new (false, tid_str);if (!slist)
tools/perf/util/thread_map.h +1 -0
@@ -9,6 +9,7 @@ struct thread_map {pid_t map[]; }; +struct thread_map *thread_map__new_dummy (void );struct thread_map *thread_map__new_by_pid (pid_t pid);struct thread_map *thread_map__new_by_tid (pid_t tid);struct thread_map *thread_map__new_by_uid (uid_t uid);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 16/24 perf evlist: Check that there is a thread_map when preparing a workload
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
The perf_evlist__prepare_workload expects a thread map to be in place so that it can store the pid of the workload being started, so check it and tell the developer about it instead of segfaulting.
--- tools/perf/util/evlist.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
tools/perf/util/evlist.c +7 -1
@@ -1276,8 +1276,14 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *tarsigaction (SIGUSR1 , &act,NULL ); } -if (target__none (target)) +if (target__none (target)) { +if (evlist->threads ==NULL ) { +fprintf (stderr,"FATAL: evlist->threads need to be set at this point (%s:%d).\n" , + __func__, __LINE__); + goto out_close_pipes; + } evlist->threads->map[0 ] = evlist->workload.pid; + }close (child_ready_pipe[1 ]);close (go_pipe[0 ]);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 17/24 perf evlist: Default to syswide target when no thread/cpu maps set
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
If all a tool wants is to do system wide event monitoring, there is no more the need to setup thread_map and cpu_map objects, just call perf_evlist__open() and it will do create one fd per CPU monitoring all threads.
--- tools/perf/util/evlist.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+)
tools/perf/util/evlist.c +40 -0
@@ -1175,11 +1175,51 @@ void perf_evlist__close(struct perf_evlist *evlist) } } +static int perf_evlist__create_syswide_maps (struct perf_evlist *evlist) +{ +int err = -ENOMEM ; + +/* +* Try reading /sys/devices/system/cpu/online to get +* an all cpus map. +* +* FIXME: -ENOMEM is the best we can do here, the cpu_map +* code needs an overhaul to properly forward the +* error, and we may not want to do that fallback to a +* default cpu identity map :-\ +*/ + evlist->cpus =cpu_map__new (NULL ); +if (evlist->cpus ==NULL ) + goto out; + + evlist->threads =thread_map__new_dummy (); +if (evlist->threads ==NULL ) + goto out_free_cpus; + + err =0 ; +out: +return err; +out_free_cpus: +cpu_map__delete (evlist->cpus); + evlist->cpus =NULL ; + goto out; +} +int perf_evlist__open (struct perf_evlist *evlist) {struct perf_evsel *evsel;int err; +/* +* Default: one fd per CPU, all threads, aka systemwide +* as sys_perf_event_open(cpu = -1, thread = -1) is EINVAL +*/ +if (evlist->threads ==NULL && evlist->cpus ==NULL ) { + err =perf_evlist__create_syswide_maps (evlist); +if (err <0 ) + goto out_err; + } +perf_evlist__update_id_pos (evlist);evlist__for_each (evlist, evsel) {
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 18/24 perf evsel: Add missing 'target' struct forward declaration
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
We use it in evsel.h but were getting it indirectly, fix it.
Noticed while working on having evsel.h usable by rasd.c.
--- tools/perf/util/evsel.h | 1 + 1 file changed, 1 insertion(+)
tools/perf/util/evsel.h +1 -0
@@ -99,6 +99,7 @@ union u64_swap { };struct cpu_map ; +struct target ;struct thread_map ;struct perf_evlist ;struct record_opts ;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 19/24 perf evsel: Make some exit routines static
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
Since they are automatically called by other methods used by tools.
--- tools/perf/util/evsel.c | 6 +++--- tools/perf/util/evsel.h | 3 --- 2 files changed, 3 insertions(+), 6 deletions(-)
tools/perf/util/evsel.c +3 -3
@@ -725,7 +725,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) } } -int perf_evsel__alloc_fd (struct perf_evsel *evsel,int ncpus,int nthreads) +static int perf_evsel__alloc_fd (struct perf_evsel *evsel,int ncpus,int nthreads) {int cpu, thread;
@@ -813,13 +813,13 @@ int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus)return evsel->counts !=NULL ?0 : -ENOMEM ; } -void perf_evsel__free_fd (struct perf_evsel *evsel) +static void perf_evsel__free_fd (struct perf_evsel *evsel) {xyarray__delete (evsel->fd); evsel->fd =NULL ; } -void perf_evsel__free_id (struct perf_evsel *evsel) +static void perf_evsel__free_id (struct perf_evsel *evsel) {xyarray__delete (evsel->sample_id); evsel->sample_id =NULL ;
tools/perf/util/evsel.h +0 -3
@@ -154,12 +154,9 @@ const char *perf_evsel__name(struct perf_evsel *evsel);const char *perf_evsel__group_name (struct perf_evsel *evsel);int perf_evsel__group_desc (struct perf_evsel *evsel,char *buf,size_t size); -int perf_evsel__alloc_fd (struct perf_evsel *evsel,int ncpus,int nthreads);int perf_evsel__alloc_id (struct perf_evsel *evsel,int ncpus,int nthreads);int perf_evsel__alloc_counts (struct perf_evsel *evsel,int ncpus);void perf_evsel__reset_counts (struct perf_evsel *evsel,int ncpus); -void perf_evsel__free_fd (struct perf_evsel *evsel); -void perf_evsel__free_id (struct perf_evsel *evsel);void perf_evsel__free_counts (struct perf_evsel *evsel);void perf_evsel__close_fd (struct perf_evsel *evsel,int ncpus,int nthreads);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 20/24 perf machine: Add missing dsos->root rbtree root initialization
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
A segfault happens on 'perf test hists_link' because we end up using a struct machines on the stack, and then machines__init() was not initializing the newly introduced rb_root, just the existing list_head.
When we introduced struct dsos, to group the two ways to store dsos, i.e. the linked list and the rbtree, we didn't turned the initialization done in:
machines__init(machines->host) -> machine__init() -> INIT_LIST_HEAD
into a dsos__init() to keep on initializing the list_head but _as well_ initializing the rb_root, oops.
All worked because outside perf-test we probably zalloc the whole thing which ends up initializing it in to NULL.
So the problem looks contained to 'perf test' that uses it on stack, etc.
--- tools/perf/util/machine.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
tools/perf/util/machine.c +8 -2
@@ -13,12 +13,18 @@#include <symbol/kallsyms.h> #include "unwind.h" +static void dsos__init (struct dsos *dsos) +{ +INIT_LIST_HEAD (&dsos->head); + dsos->root =RB_ROOT ; +} +int machine__init (struct machine *machine,const char *root_dir,pid_t pid) {map_groups__init (&machine->kmaps);RB_CLEAR_NODE (&machine->rb_node); -INIT_LIST_HEAD (&machine->user_dsos.head); -INIT_LIST_HEAD (&machine->kernel_dsos.head); +dsos__init (&machine->user_dsos); +dsos__init (&machine->kernel_dsos); machine->threads =RB_ROOT ;INIT_LIST_HEAD (&machine->dead_threads);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 21/24 perf tools: fix off-by-one error in maps
In reply to Arnaldo Carvalho de MeloFrom: Stephane Eranian <[email protected]>
This patch fixes off-by-one errors in the management of maps.
A map is defined by start address and length as implemented by map__new():
map__init(map, type, start, start + len, pgoff, dso);
map->start = addr; map->end = end;
Consequently, the actual address range is [start; end[ map->end is the first byte outside the range.
This patch fixes two bugs where upper bound checking was off-by-one.
In V2, we fix map_groups__fixup_overlappings() some more where map->start was off-by-one as reported by Jiri.
--- tools/perf/util/map.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
tools/perf/util/map.c +3 -3
@@ -556,7 +556,7 @@ struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,int map_groups__find_ams (struct addr_map_symbol *ams,symbol_filter_t filter) { -if (ams->addr < ams->map->start || ams->addr > ams->map->end) { +if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {if (ams->map->groups ==NULL )return -1 ; ams->map = map_groups__find(ams->map->groups, ams->map->type,
@@ -664,7 +664,7 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, goto move_map; } - before->end = map->start -1 ; + before->end = map->start;map_groups__insert (mg, before);if (verbose >=2 )map__fprintf (before, fp);
@@ -678,7 +678,7 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, goto move_map; } - after->start = map->end +1 ; + after->start = map->end;map_groups__insert (mg, after);if (verbose >=2 )map__fprintf (after, fp);
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 22/24 perf tools: Fixup off-by-one comparision in maps__find
In reply to Arnaldo Carvalho de MeloFrom: Namhyung Kim <[email protected]>
map->end is the first addr _outside_ the a map, following the convention of vm_area_struct->vm_end.
--- tools/perf/util/map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/map.c +1 -1
@@ -752,7 +752,7 @@ struct map *maps__find(struct rb_root *maps, u64 ip) m = rb_entry(parent, struct map, rb_node);if (ip < m->start) p = &(*p)->rb_left; -else if (ip > m->end) +else if (ip >= m->end) p = &(*p)->rb_right;else return m;
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 23/24 perf symbols: Fix map->end fixup
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
When synthesizing maps from files that have incomplete symbol information, like kallsyms, we need to fixup the end of maps by seting its end from the ->start of the next map, fix it to set prev_map->end to curr_map->start, since ->end is the first byte outside prev_map address range.
--- tools/perf/util/symbol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/util/symbol.c +1 -1
@@ -207,7 +207,7 @@ void __map_groups__fixup_end(struct map_groups *mg, enum map_type type)for (nd =rb_next (prevnd); nd; nd =rb_next (nd)) { prev = curr; curr = rb_entry(nd, struct map, rb_node); - prev->end = curr->start -1 ; + prev->end = curr->start; }/*
Signature · 1 line
1.9.3
Arnaldo Carvalho de Melo
maintainerPATCH 24/24 perf symbols: Make sym->end be the first address after the symbol range
In reply to Arnaldo Carvalho de MeloFrom: Arnaldo Carvalho de Melo <[email protected]>
To follow vm_area_struct->vm_end convention.
By adhering to the convention that ->end is the first address outside the symbol's range we can do things like:
sym->end = start + len; len = sym->end - sym->start;
This is also now the convention used for struct map->end, fixing some off-by-one bugs.
--- tools/perf/util/annotate.c | 8 ++++---- tools/perf/util/symbol.c | 6 +++--- tools/perf/util/symbol.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-)
tools/perf/util/annotate.c +4 -4
@@ -478,7 +478,7 @@ static int __symbol__inc_addr_samples(struct symbol *sym, struct map *map,pr_debug3 ("%s: addr=%#" PRIx64"\n" , __func__, map->unmap_ip (map, addr)); -if (addr < sym->start || addr > sym->end) +if (addr < sym->start || addr >= sym->end)return -ERANGE ; offset = addr - sym->start;
@@ -836,7 +836,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map, end =map__rip_2objdump (map, sym->end); offset = line_ip - start; -if ((u64 )line_ip < start || (u64 )line_ip > end) +if ((u64 )line_ip < start || (u64 )line_ip >= end) offset =-1 ;else parsed_line = tmp2 +1 ;
@@ -966,7 +966,7 @@ fallback: kce.kcore_filename = symfs_filename; kce.addr =map__rip_2objdump (map, sym->start); kce.offs = sym->start; - kce.len = sym->end +1 - sym->start; + kce.len = sym->end - sym->start;if (!kcore_extract__create (&kce)) { delete_extract = true; strlcpy(symfs_filename, kce.extract_filename,
@@ -987,7 +987,7 @@ fallback: disassembler_style ?"-M " :"" , disassembler_style ? disassembler_style :"" ,map__rip_2objdump (map, sym->start), -map__rip_2objdump (map, sym->end+1 ), +map__rip_2objdump (map, sym->end), symbol_conf.annotate_asm_raw ?"" :"--no-show-raw" , symbol_conf.annotate_src ?"-S" :"" , symfs_filename, filename);
tools/perf/util/symbol.c +3 -3
@@ -186,7 +186,7 @@ void symbols__fixup_end(struct rb_root *symbols) curr = rb_entry(nd, struct symbol, rb_node);if (prev->end == prev->start && prev->end != curr->start) - prev->end = curr->start -1 ; + prev->end = curr->start; }/* Last entry */
@@ -229,7 +229,7 @@ struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name) sym = ((void *)sym) + symbol_conf.priv_size; sym->start = start; - sym->end = len ? start + len -1 : start; + sym->end = len ? start + len : start; sym->binding = binding; sym->namelen = namelen -1 ;
@@ -325,7 +325,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)if (ip < s->start) n = n->rb_left; -else if (ip > s->end) +else if (ip >= s->end) n = n->rb_right;else return s;
tools/perf/util/symbol.h +1 -1
@@ -95,7 +95,7 @@ void symbols__delete(struct rb_root *symbols);static inline size_t symbol__size (const struct symbol *sym) { -return sym->end - sym->start +1 ; +return sym->end - sym->start; }struct strlist ;
Signature · 1 line
1.9.3
Quoted 108 lines · Arnaldo Carvalho de Melo
Hi Ingo,
Please consider pulling,
- Arnaldo
The following changes since commit
cc6cd47e7395bc05c5077009808b820633eb3f18:perf/x86: Tone down kernel messages when the PMU check fails in a virtual environment (2014-10-03 06:04:41 +0200)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux.gittags/perf-core-for-mingofor you to fetch changes up to
2c241bd35e6f626ad6f867dcf9fefdc2315f125f:perf symbols: Make
sym->endbe the first address after the symbol range (2014-10-14 17:50:58 -0300)----------------------------------------------------------------
perf/core improvements and fixes:Infrastructure:
. Do not include a struct hists per
perf_evsel, untangling the histogram code
fromperf_evsel, to pave the way for exporting a minimalistictools/lib/api/perf/library usable bytools/perfand initially by the rasd daemon being developed by Borislav Petkov, Robert Richter and Jean Pihet. (Arnaldo Carvalho de Melo). Make
perf_evlist__open(evlist, NULL, NULL), i.e. without cpu and thread
maps mean syswide monitoring, reducing the boilerplate for tools that only want system wide mode. (Arnaldo Carvalho de Melo). Fix off-by-one bugs in
map->endhandling (Stephane Eranian). Fix off-by-one bug in
maps__find(), also related tomap->endhandling (Namhyung Kim). Make struct
symbol->endbe the first addr after the symbol range, to make it
match the convention used for structmap->end. (Arnaldo Carvalho de Melo). Fix
perf_evlist__add_pollfd()error handling in 'perf kvm stat live' (Jiri Olsa). Fix python test build by moving
callchain_paramto an object linked into the
python binding (Jiri Olsa)Signed-off-by Arnaldo Carvalho de Melo <[email protected]>----------------------------------------------------------------
Arnaldo Carvalho de Melo (18):
perf sched: Stop updating hists stats, not used
perf script: Stop updating hists stats, not used
perf evsel: Add hists helper
perf session: Don't count per evsel events
perf tools: Moveevents_statsstruct toevent.h
perf ui browsers: Add missing include
perf session: Remove last reference to hists struct
perf evsel: Subclassing
perf callchain: Move thecallchain_paramextern tocallchain.hperf tools: Remove hists from evsel
perfthread_map: Create dummy constructor out of open coded equivalent perf evlist: Check that there is athread_mapwhen preparing a workload perf evlist: Default to syswide target when no thread/cpu maps set perf evsel: Add missing 'target' struct forward declaration perf evsel: Make some exit routines static
perf machine: Add missingdsos->rootrbtree root initialization perf symbols: Fixmap->endfixup
perf symbols: Makesym->endbe the first address after the symbol rangeJiri Olsa (4):
perf kvm stat live: Fixperf_evlist__add_pollfderror handling perf kvm stat live: Useperf_evlist__add_pollfdreturn fd position perf kvm stat live: Use fdarray object instead of pollfd perf callchain: Movecallchain_paramto util object in to fix python testNamhyung Kim (1):
perf tools: Fixup off-by-one comparision inmaps__findStephane Eranian (1):
perf tools: fix off-by-one error in mapstools/perf/builtin-annotate.c | 14 +++-- tools/perf/builtin-diff.c | 21 ++++--- tools/perf/builtin-kvm.c | 22 +++---- tools/perf/builtin-record.c | 1 + tools/perf/builtin-report.c | 24 ++++--- tools/perf/builtin-sched.c | 3 - tools/perf/builtin-script.c | 1 - tools/perf/builtin-top.c | 60 ++++++++++-------- tools/perf/tests/builtin-test.c | 5 ++ tools/perf/tests/hists_cumulate.c | 8 +-- tools/perf/tests/hists_filter.c | 23 +++---- tools/perf/tests/hists_link.c | 23 ++++--- tools/perf/tests/hists_output.c | 20 +++--- tools/perf/ui/browsers/header.c | 1 + tools/perf/ui/browsers/hists.c | 20 +++--- tools/perf/ui/gtk/hists.c | 2 +- tools/perf/util/annotate.c | 8 +-- tools/perf/util/callchain.h | 2 + tools/perf/util/event.h | 26 ++++++++ tools/perf/util/evlist.c | 48 +++++++++++++- tools/perf/util/evsel.c | 66 ++++++++++++++----- tools/perf/util/evsel.h | 14 ++--- tools/perf/util/hist.c | 73 +++++++++++++++++----- tools/perf/util/hist.h | 49 +++++++-------- tools/perf/util/machine.c | 10 ++- tools/perf/util/map.c | 8 +-- .../util/scripting-engines/trace-event-python.c | 1 + tools/perf/util/session.c | 23 -------
Quoted 8 lines
tools/perf/util/session.h | 1 - tools/perf/util/sort.c | 4 +- tools/perf/util/symbol.c | 8 +-- tools/perf/util/symbol.h | 2 +- tools/perf/util/thread_map.c | 21 ++++--- tools/perf/util/thread_map.h | 1 + tools/perf/util/util.c | 8 +++ 35 files changed, 392 insertions(+), 229 deletions(-)
Pulled, thanks a lot Arnaldo!
Ingo