Skip to content
Snippets Groups Projects
Commit 1f6075f9 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull more perf updates from Ingo Molnar:
 "A second (and last) round of late coming fixes and changes, almost all
  of them in perf tooling:

  User visible tooling changes:

   - Add period data column and make it default in 'perf script' (Jiri
     Olsa)

   - Add a visual cue for toggle zeroing of samples in 'perf top'
     (Taeung Song)

   - Improve callchains when using libunwind (Namhyung Kim)

  Tooling fixes and infrastructure changes:

   - Fix for double free in 'perf stat' when using some specific invalid
     command line combo (Yasser Shalabi)

   - 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)

   - Document sysfs events/ interfaces (Cody P Schafer)

   - Fix typos in perf/Documentation (Masanari Iida)

   - Add missing 'struct option' forward declaration (Arnaldo Carvalho
     de Melo)

   - Add option to copy events when queuing for sorting across cpu
     buffers and enable it for 'perf kvm stat live', to avoid having
     events left in the queue pointing to the ring buffer be rewritten
     in high volume sessions.  (Alexander Yarygin, improving work done
     by David Ahern):

   - 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)

   - Move exit stuff from perf_evsel__delete to perf_evsel__exit, delete
     should be just a front end for exit + free (Arnaldo Carvalho de
     Melo)

   - Add support to new style format of kernel PMU event.  (Kan Liang)

  and other misc fixes"

* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (45 commits)
  perf script: Add period as a default output column
  perf script: Add period data column
  perf evsel: No need to drag util/cgroup.h
  perf evlist: Add missing 'struct option' forward declaration
  perf evsel: Move exit stuff from __delete to __exit
  kprobes/x86: Remove stale ARCH_SUPPORTS_KPROBES_ON_FTRACE define
  perf kvm stat live: Enable events copying
  perf session: Add option to copy events when queueing
  perf Documentation: Fix typos in perf/Documentation
  perf trace: Use thread_{,_set}_priv helpers
  perf kvm: Use thread_{,_set}_priv helpers
  perf callchain: Create an address space per thread
  perf report: Set callchain_param.record_mode for future use
  perf evlist: Fix for double free in tools/perf stat
  perf test: Add test case for pmu event new style format
  perf tools: Add support to new style format of kernel PMU event
  perf tools: Parse the pmu event prefix and suffix
  Revert "perf tools: Default to cpu// for events v5"
  perf Documentation: Remove Ruplicated docs for powerpc cpu specific events
  perf Documentation: sysfs events/ interfaces
  ...
parents 5e2ee7cd 3b10ea7f
No related branches found
No related tags found
No related merge requests found
Showing
with 173 additions and 654 deletions
......@@ -27,7 +27,6 @@
#include <asm/insn.h>
#define __ARCH_WANT_KPROBES_INSN_SLOT
#define ARCH_SUPPORTS_KPROBES_ON_FTRACE
struct pt_regs;
struct kprobe;
......
......@@ -196,10 +196,10 @@ If specified the 'Weighted diff' column is displayed with value 'd' computed as:
- period being the hist entry period value
- WEIGHT-A/WEIGHT-B being user suplied weights in the the '-c' option
- WEIGHT-A/WEIGHT-B being user supplied weights in the the '-c' option
behind ':' separator like '-c wdiff:1,2'.
- WIEGHT-A being the weight of the data file
- WIEGHT-B being the weight of the baseline data file
- WEIGHT-A being the weight of the data file
- WEIGHT-B being the weight of the baseline data file
SEE ALSO
--------
......
......@@ -100,7 +100,7 @@ OPTIONS
STAT REPORT OPTIONS
-------------------
--vcpu=<value>::
analyze events which occures on this vcpu. (default: all vcpus)
analyze events which occur on this vcpu. (default: all vcpus)
--event=<value>::
event to be analyzed. Possible values: vmexit, mmio (x86 only),
......@@ -134,7 +134,7 @@ STAT LIVE OPTIONS
Analyze events only for given process ID(s) (comma separated list).
--vcpu=<value>::
analyze events which occures on this vcpu. (default: all vcpus)
analyze events which occur on this vcpu. (default: all vcpus)
--event=<value>::
......
......@@ -19,7 +19,7 @@ various perf commands with the -e option.
EVENT MODIFIERS
---------------
Events can optionally have a modifer by appending a colon and one or
Events can optionally have a modifier by appending a colon and one or
more modifiers. Modifiers allow the user to restrict the events to be
counted. The following modifiers exist:
......
......@@ -146,7 +146,7 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
-N::
--no-buildid-cache::
Do not update the builid cache. This saves some overhead in situations
Do not update the buildid cache. This saves some overhead in situations
where the information in the perf.data file (which includes buildids)
is sufficient.
......
......@@ -181,8 +181,8 @@ strings for flag and symbolic fields. These correspond to the strings
and values parsed from the 'print fmt' fields of the event format
files:
flag_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the flag field $field_name of event $event_name
symbol_str($event_name, $field_name, $field_value) - returns the string represention corresponding to $field_value for the symbolic field $field_name of event $event_name
flag_str($event_name, $field_name, $field_value) - returns the string representation corresponding to $field_value for the flag field $field_name of event $event_name
symbol_str($event_name, $field_name, $field_value) - returns the string representation corresponding to $field_value for the symbolic field $field_name of event $event_name
Perf::Trace::Context Module
~~~~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -263,7 +263,7 @@ and having the counts we've tallied as values.
The print_syscall_totals() function iterates over the entries in the
dictionary and displays a line for each entry containing the syscall
name (the dictonary keys contain the syscall ids, which are passed to
name (the dictionary keys contain the syscall ids, which are passed to
the Util function syscall_name(), which translates the raw syscall
numbers to the corresponding syscall name strings). The output is
displayed after all the events in the trace have been processed, by
......@@ -576,8 +576,8 @@ strings for flag and symbolic fields. These correspond to the strings
and values parsed from the 'print fmt' fields of the event format
files:
flag_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the flag field field_name of event event_name
symbol_str(event_name, field_name, field_value) - returns the string represention corresponding to field_value for the symbolic field field_name of event event_name
flag_str(event_name, field_name, field_value) - returns the string representation corresponding to field_value for the flag field field_name of event event_name
symbol_str(event_name, field_name, field_value) - returns the string representation corresponding to field_value for the symbolic field field_name of event event_name
The *autodict* function returns a special kind of Python
dictionary that implements Perl's 'autovivifying' hashes in Python
......
......@@ -115,7 +115,7 @@ OPTIONS
-f::
--fields::
Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline.
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, srcline, period.
Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies.
e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
......@@ -140,7 +140,7 @@ OPTIONS
"Overriding previous field request for all events."
Alternativey, consider the order:
Alternatively, consider the order:
-f comm,tid,time,ip,sym -f trace:
......
......@@ -25,7 +25,7 @@ OPTIONS
-------
-s::
--skip::
Tests to skip (comma separater numeric list).
Tests to skip (comma separated numeric list).
-v::
--verbose::
......
......@@ -20,7 +20,7 @@ scheduling events, etc.
This is a live mode tool in addition to working with perf.data files like
the other perf tools. Files can be generated using the 'perf record' command
but the session needs to include the raw_syscalls events (-e 'raw_syscalls:*').
Alernatively, the 'perf trace record' can be used as a shortcut to
Alternatively, 'perf trace record' can be used as a shortcut to
automatically include the raw_syscalls events when writing events to a file.
The following options apply to perf trace; options to perf trace record are
......
......@@ -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;
}
......@@ -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;
}
......@@ -225,7 +226,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) {
......@@ -325,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);
......
......@@ -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);
}
}
......
......@@ -376,7 +376,7 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
struct perf_sample *sample)
{
/* Only kvm_entry records vcpu id. */
if (!thread->priv && kvm_entry_event(evsel)) {
if (!thread__priv(thread) && kvm_entry_event(evsel)) {
struct vcpu_event_record *vcpu_record;
vcpu_record = zalloc(sizeof(*vcpu_record));
......@@ -386,10 +386,10 @@ struct vcpu_event_record *per_vcpu_record(struct thread *thread,
}
vcpu_record->vcpu_id = perf_evsel__intval(evsel, sample, VCPU_ID);
thread->priv = vcpu_record;
thread__set_priv(thread, vcpu_record);
}
return thread->priv;
return thread__priv(thread);
}
static bool handle_kvm_event(struct perf_kvm_stat *kvm,
......@@ -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,34 +918,27 @@ 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;
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)))
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;
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);
......@@ -1366,6 +1358,7 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
}
kvm->session->evlist = kvm->evlist;
perf_session__set_id_hdr_size(kvm->session);
ordered_events__set_copy_on_queue(&kvm->session->ordered_events, true);
machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
kvm->evlist->threads, false);
err = kvm_live_open_events(kvm);
......
......@@ -14,6 +14,8 @@
#include "util/parse-options.h"
#include "util/parse-events.h"
#include "util/callchain.h"
#include "util/cgroup.h"
#include "util/header.h"
#include "util/event.h"
#include "util/evlist.h"
......
......@@ -257,6 +257,13 @@ static int report__setup_sample_type(struct report *rep)
}
}
if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
if ((sample_type & PERF_SAMPLE_REGS_USER) &&
(sample_type & PERF_SAMPLE_STACK_USER))
callchain_param.record_mode = CALLCHAIN_DWARF;
else
callchain_param.record_mode = CALLCHAIN_FP;
}
return 0;
}
......@@ -288,12 +295,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 +327,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 +436,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 +446,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);
......@@ -485,6 +494,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;
}
}
......@@ -500,7 +510,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);
}
......@@ -565,7 +575,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>]",
......@@ -692,6 +701,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);
......
......@@ -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);
......
......@@ -44,6 +44,7 @@ enum perf_output_field {
PERF_OUTPUT_ADDR = 1U << 10,
PERF_OUTPUT_SYMOFFSET = 1U << 11,
PERF_OUTPUT_SRCLINE = 1U << 12,
PERF_OUTPUT_PERIOD = 1U << 13,
};
struct output_option {
......@@ -63,6 +64,7 @@ struct output_option {
{.str = "addr", .field = PERF_OUTPUT_ADDR},
{.str = "symoff", .field = PERF_OUTPUT_SYMOFFSET},
{.str = "srcline", .field = PERF_OUTPUT_SRCLINE},
{.str = "period", .field = PERF_OUTPUT_PERIOD},
};
/* default set to maintain compatibility with current format */
......@@ -80,7 +82,8 @@ static struct {
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
PERF_OUTPUT_PERIOD,
.invalid_fields = PERF_OUTPUT_TRACE,
},
......@@ -91,7 +94,8 @@ static struct {
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
PERF_OUTPUT_PERIOD,
.invalid_fields = PERF_OUTPUT_TRACE,
},
......@@ -110,7 +114,8 @@ static struct {
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO |
PERF_OUTPUT_PERIOD,
.invalid_fields = PERF_OUTPUT_TRACE,
},
......@@ -229,6 +234,11 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
PERF_OUTPUT_CPU))
return -EINVAL;
if (PRINT_FIELD(PERIOD) &&
perf_evsel__check_stype(evsel, PERF_SAMPLE_PERIOD, "PERIOD",
PERF_OUTPUT_PERIOD))
return -EINVAL;
return 0;
}
......@@ -448,6 +458,9 @@ static void process_event(union perf_event *event, struct perf_sample *sample,
print_sample_start(sample, thread, evsel);
if (PRINT_FIELD(PERIOD))
printf("%10" PRIu64 " ", sample->period);
if (PRINT_FIELD(EVNAME)) {
const char *evname = perf_evsel__name(evsel);
printf("%s: ", evname ? evname : "[unknown]");
......@@ -572,7 +585,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;
}
......@@ -1544,7 +1556,7 @@ 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", parse_output_fields),
"addr,symoff,period", 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...]",
......
......@@ -43,6 +43,7 @@
#include "perf.h"
#include "builtin.h"
#include "util/cgroup.h"
#include "util/util.h"
#include "util/parse-options.h"
#include "util/parse-events.h"
......
......@@ -251,6 +251,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
char bf[160];
int printed = 0;
const int win_width = top->winsize.ws_col - 1;
struct hists *hists = evsel__hists(top->sym_evsel);
puts(CONSOLE_CLEAR);
......@@ -261,13 +262,13 @@ static void perf_top__print_sym_table(struct perf_top *top)
printf("%-*.*s\n", win_width, win_width, graph_dotted_line);
if (top->sym_evsel->hists.stats.nr_lost_warned !=
top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST]) {
top->sym_evsel->hists.stats.nr_lost_warned =
top->sym_evsel->hists.stats.nr_events[PERF_RECORD_LOST];
if (hists->stats.nr_lost_warned !=
hists->stats.nr_events[PERF_RECORD_LOST]) {
hists->stats.nr_lost_warned =
hists->stats.nr_events[PERF_RECORD_LOST];
color_fprintf(stdout, PERF_COLOR_RED,
"WARNING: LOST %d chunks, Check IO/CPU overload",
top->sym_evsel->hists.stats.nr_lost_warned);
hists->stats.nr_lost_warned);
++printed;
}
......@@ -277,21 +278,18 @@ static void perf_top__print_sym_table(struct perf_top *top)
}
if (top->zero) {
hists__delete_entries(&top->sym_evsel->hists);
hists__delete_entries(hists);
} else {
hists__decay_entries(&top->sym_evsel->hists,
top->hide_user_symbols,
hists__decay_entries(hists, top->hide_user_symbols,
top->hide_kernel_symbols);
}
hists__collapse_resort(&top->sym_evsel->hists, NULL);
hists__output_resort(&top->sym_evsel->hists);
hists__collapse_resort(hists, NULL);
hists__output_resort(hists);
hists__output_recalc_col_len(&top->sym_evsel->hists,
top->print_entries - printed);
hists__output_recalc_col_len(hists, top->print_entries - printed);
putchar('\n');
hists__fprintf(&top->sym_evsel->hists, false,
top->print_entries - printed, win_width,
hists__fprintf(hists, false, top->print_entries - printed, win_width,
top->min_percent, stdout);
}
......@@ -334,6 +332,7 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
{
char *buf = malloc(0), *p;
struct hist_entry *syme = top->sym_filter_entry, *n, *found = NULL;
struct hists *hists = evsel__hists(top->sym_evsel);
struct rb_node *next;
size_t dummy = 0;
......@@ -351,7 +350,7 @@ static void perf_top__prompt_symbol(struct perf_top *top, const char *msg)
if (p)
*p = 0;
next = rb_first(&top->sym_evsel->hists.entries);
next = rb_first(&hists->entries);
while (next) {
n = rb_entry(next, struct hist_entry, rb_node);
if (n->ms.sym && !strcmp(buf, n->ms.sym->name)) {
......@@ -538,21 +537,24 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
static void perf_top__sort_new_samples(void *arg)
{
struct perf_top *t = arg;
struct hists *hists;
perf_top__reset_sample_counters(t);
if (t->evlist->selected != NULL)
t->sym_evsel = t->evlist->selected;
hists = evsel__hists(t->sym_evsel);
if (t->zero) {
hists__delete_entries(&t->sym_evsel->hists);
hists__delete_entries(hists);
} else {
hists__decay_entries(&t->sym_evsel->hists,
t->hide_user_symbols,
hists__decay_entries(hists, t->hide_user_symbols,
t->hide_kernel_symbols);
}
hists__collapse_resort(&t->sym_evsel->hists, NULL);
hists__output_resort(&t->sym_evsel->hists);
hists__collapse_resort(hists, NULL);
hists__output_resort(hists);
}
static void *display_thread_tui(void *arg)
......@@ -573,8 +575,10 @@ 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)
pos->hists.uid_filter_str = top->record_opts.target.uid_str;
evlist__for_each(top->evlist, pos) {
struct hists *hists = evsel__hists(pos);
hists->uid_filter_str = top->record_opts.target.uid_str;
}
perf_evlist__tui_browse_hists(top->evlist, help, &hbt, top->min_percent,
&top->session->header.env);
......@@ -768,6 +772,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
}
if (al.sym == NULL || !al.sym->ignore) {
struct hists *hists = evsel__hists(evsel);
struct hist_entry_iter iter = {
.add_entry_cb = hist_iter__top_callback,
};
......@@ -777,14 +782,14 @@ static void perf_event__process_sample(struct perf_tool *tool,
else
iter.ops = &hist_iter_normal;
pthread_mutex_lock(&evsel->hists.lock);
pthread_mutex_lock(&hists->lock);
err = hist_entry_iter__add(&iter, &al, evsel, sample,
top->max_stack, top);
if (err < 0)
pr_err("Problem incrementing symbol period, skipping event\n");
pthread_mutex_unlock(&evsel->hists.lock);
pthread_mutex_unlock(&hists->lock);
}
return;
......@@ -849,7 +854,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
perf_event__process_sample(&top->tool, event, evsel,
&sample, machine);
} else if (event->header.type < PERF_RECORD_MAX) {
hists__inc_nr_events(&evsel->hists, event->header.type);
hists__inc_nr_events(evsel__hists(evsel), event->header.type);
machine__process_event(machine, event, &sample);
} else
++session->stats.nr_unknown_events;
......@@ -1042,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,
......@@ -1160,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)
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment