perf evsel: Introduce perf_evlist
Killing two more perf wide global variables: nr_counters and evsel_list as a list_head. There are more operations that will need more fields in perf_evlist, like the pollfd for polling all the fds in a list of evsel instances. Use option->value to pass the evsel_list to parse_{events,filters}. LKML-Reference: <new-submission> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Mike Galbraith <efault@gmx.de> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Stephane Eranian <eranian@google.com> Cc: Tom Zanussi <tzanussi@gmail.com> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
00e99a49f6
commit
361c99a661
|
@ -402,6 +402,7 @@ LIB_H += util/debug.h
|
||||||
LIB_H += util/debugfs.h
|
LIB_H += util/debugfs.h
|
||||||
LIB_H += util/event.h
|
LIB_H += util/event.h
|
||||||
LIB_H += util/evsel.h
|
LIB_H += util/evsel.h
|
||||||
|
LIB_H += util/evlist.h
|
||||||
LIB_H += util/exec_cmd.h
|
LIB_H += util/exec_cmd.h
|
||||||
LIB_H += util/types.h
|
LIB_H += util/types.h
|
||||||
LIB_H += util/levenshtein.h
|
LIB_H += util/levenshtein.h
|
||||||
|
@ -440,6 +441,7 @@ LIB_OBJS += $(OUTPUT)util/ctype.o
|
||||||
LIB_OBJS += $(OUTPUT)util/debugfs.o
|
LIB_OBJS += $(OUTPUT)util/debugfs.o
|
||||||
LIB_OBJS += $(OUTPUT)util/environment.o
|
LIB_OBJS += $(OUTPUT)util/environment.o
|
||||||
LIB_OBJS += $(OUTPUT)util/event.o
|
LIB_OBJS += $(OUTPUT)util/event.o
|
||||||
|
LIB_OBJS += $(OUTPUT)util/evlist.o
|
||||||
LIB_OBJS += $(OUTPUT)util/evsel.o
|
LIB_OBJS += $(OUTPUT)util/evsel.o
|
||||||
LIB_OBJS += $(OUTPUT)util/exec_cmd.o
|
LIB_OBJS += $(OUTPUT)util/exec_cmd.o
|
||||||
LIB_OBJS += $(OUTPUT)util/help.o
|
LIB_OBJS += $(OUTPUT)util/help.o
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
|
|
||||||
#include "util/header.h"
|
#include "util/header.h"
|
||||||
#include "util/event.h"
|
#include "util/event.h"
|
||||||
|
#include "util/evlist.h"
|
||||||
#include "util/evsel.h"
|
#include "util/evsel.h"
|
||||||
#include "util/debug.h"
|
#include "util/debug.h"
|
||||||
#include "util/session.h"
|
#include "util/session.h"
|
||||||
|
@ -66,6 +67,7 @@ static bool sample_address = false;
|
||||||
static bool sample_time = false;
|
static bool sample_time = false;
|
||||||
static bool no_buildid = false;
|
static bool no_buildid = false;
|
||||||
static bool no_buildid_cache = false;
|
static bool no_buildid_cache = false;
|
||||||
|
static struct perf_evlist *evsel_list;
|
||||||
|
|
||||||
static long samples = 0;
|
static long samples = 0;
|
||||||
static u64 bytes_written = 0;
|
static u64 bytes_written = 0;
|
||||||
|
@ -229,7 +231,8 @@ static struct perf_header_attr *get_header_attr(struct perf_event_attr *a, int n
|
||||||
return h_attr;
|
return h_attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_counter(struct perf_evsel *evsel, int cpu)
|
static void create_counter(struct perf_evlist *evlist,
|
||||||
|
struct perf_evsel *evsel, int cpu)
|
||||||
{
|
{
|
||||||
char *filter = evsel->filter;
|
char *filter = evsel->filter;
|
||||||
struct perf_event_attr *attr = &evsel->attr;
|
struct perf_event_attr *attr = &evsel->attr;
|
||||||
|
@ -263,7 +266,7 @@ static void create_counter(struct perf_evsel *evsel, int cpu)
|
||||||
|
|
||||||
attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
|
attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID;
|
||||||
|
|
||||||
if (nr_counters > 1)
|
if (evlist->nr_entries > 1)
|
||||||
attr->sample_type |= PERF_SAMPLE_ID;
|
attr->sample_type |= PERF_SAMPLE_ID;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -410,7 +413,7 @@ try_again:
|
||||||
|
|
||||||
if (evsel->idx || thread_index) {
|
if (evsel->idx || thread_index) {
|
||||||
struct perf_evsel *first;
|
struct perf_evsel *first;
|
||||||
first = list_entry(evsel_list.next, struct perf_evsel, node);
|
first = list_entry(evlist->entries.next, struct perf_evsel, node);
|
||||||
ret = ioctl(FD(evsel, nr_cpu, thread_index),
|
ret = ioctl(FD(evsel, nr_cpu, thread_index),
|
||||||
PERF_EVENT_IOC_SET_OUTPUT,
|
PERF_EVENT_IOC_SET_OUTPUT,
|
||||||
FD(first, nr_cpu, 0));
|
FD(first, nr_cpu, 0));
|
||||||
|
@ -449,14 +452,14 @@ try_again:
|
||||||
sample_type = attr->sample_type;
|
sample_type = attr->sample_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void open_counters(int cpu)
|
static void open_counters(struct perf_evlist *evlist, int cpu)
|
||||||
{
|
{
|
||||||
struct perf_evsel *pos;
|
struct perf_evsel *pos;
|
||||||
|
|
||||||
group_fd = -1;
|
group_fd = -1;
|
||||||
|
|
||||||
list_for_each_entry(pos, &evsel_list, node)
|
list_for_each_entry(pos, &evlist->entries, node)
|
||||||
create_counter(pos, cpu);
|
create_counter(evlist, pos, cpu);
|
||||||
|
|
||||||
nr_cpu++;
|
nr_cpu++;
|
||||||
}
|
}
|
||||||
|
@ -481,9 +484,9 @@ static void atexit_header(void)
|
||||||
|
|
||||||
if (!no_buildid)
|
if (!no_buildid)
|
||||||
process_buildids();
|
process_buildids();
|
||||||
perf_header__write(&session->header, output, true);
|
perf_header__write(&session->header, evsel_list, output, true);
|
||||||
perf_session__delete(session);
|
perf_session__delete(session);
|
||||||
perf_evsel_list__delete();
|
perf_evlist__delete(evsel_list);
|
||||||
symbol__exit();
|
symbol__exit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -611,7 +614,7 @@ static int __cmd_record(int argc, const char **argv)
|
||||||
goto out_delete_session;
|
goto out_delete_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_tracepoints(&evsel_list))
|
if (have_tracepoints(&evsel_list->entries))
|
||||||
perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
|
perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -674,10 +677,10 @@ static int __cmd_record(int argc, const char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!system_wide && no_inherit && !cpu_list) {
|
if (!system_wide && no_inherit && !cpu_list) {
|
||||||
open_counters(-1);
|
open_counters(evsel_list, -1);
|
||||||
} else {
|
} else {
|
||||||
for (i = 0; i < cpus->nr; i++)
|
for (i = 0; i < cpus->nr; i++)
|
||||||
open_counters(cpus->map[i]);
|
open_counters(evsel_list, cpus->map[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
perf_session__set_sample_type(session, sample_type);
|
perf_session__set_sample_type(session, sample_type);
|
||||||
|
@ -687,7 +690,8 @@ static int __cmd_record(int argc, const char **argv)
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
} else if (file_new) {
|
} else if (file_new) {
|
||||||
err = perf_header__write(&session->header, output, false);
|
err = perf_header__write(&session->header, evsel_list,
|
||||||
|
output, false);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -712,7 +716,7 @@ static int __cmd_record(int argc, const char **argv)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (have_tracepoints(&evsel_list)) {
|
if (have_tracepoints(&evsel_list->entries)) {
|
||||||
/*
|
/*
|
||||||
* FIXME err <= 0 here actually means that
|
* FIXME err <= 0 here actually means that
|
||||||
* there were no tracepoints so its not really
|
* there were no tracepoints so its not really
|
||||||
|
@ -721,7 +725,7 @@ static int __cmd_record(int argc, const char **argv)
|
||||||
* return this more properly and also
|
* return this more properly and also
|
||||||
* propagate errors that now are calling die()
|
* propagate errors that now are calling die()
|
||||||
*/
|
*/
|
||||||
err = event__synthesize_tracing_data(output, &evsel_list,
|
err = event__synthesize_tracing_data(output, evsel_list,
|
||||||
process_synthesized_event,
|
process_synthesized_event,
|
||||||
session);
|
session);
|
||||||
if (err <= 0) {
|
if (err <= 0) {
|
||||||
|
@ -797,7 +801,7 @@ static int __cmd_record(int argc, const char **argv)
|
||||||
for (i = 0; i < nr_cpu; i++) {
|
for (i = 0; i < nr_cpu; i++) {
|
||||||
struct perf_evsel *pos;
|
struct perf_evsel *pos;
|
||||||
|
|
||||||
list_for_each_entry(pos, &evsel_list, node) {
|
list_for_each_entry(pos, &evsel_list->entries, node) {
|
||||||
for (thread = 0;
|
for (thread = 0;
|
||||||
thread < threads->nr;
|
thread < threads->nr;
|
||||||
thread++)
|
thread++)
|
||||||
|
@ -838,10 +842,10 @@ static const char * const record_usage[] = {
|
||||||
static bool force, append_file;
|
static bool force, append_file;
|
||||||
|
|
||||||
const struct option record_options[] = {
|
const struct option record_options[] = {
|
||||||
OPT_CALLBACK('e', "event", NULL, "event",
|
OPT_CALLBACK('e', "event", &evsel_list, "event",
|
||||||
"event selector. use 'perf list' to list available events",
|
"event selector. use 'perf list' to list available events",
|
||||||
parse_events),
|
parse_events),
|
||||||
OPT_CALLBACK(0, "filter", NULL, "filter",
|
OPT_CALLBACK(0, "filter", &evsel_list, "filter",
|
||||||
"event filter", parse_filter),
|
"event filter", parse_filter),
|
||||||
OPT_INTEGER('p', "pid", &target_pid,
|
OPT_INTEGER('p', "pid", &target_pid,
|
||||||
"record events on existing process id"),
|
"record events on existing process id"),
|
||||||
|
@ -892,6 +896,10 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
|
||||||
int err = -ENOMEM;
|
int err = -ENOMEM;
|
||||||
struct perf_evsel *pos;
|
struct perf_evsel *pos;
|
||||||
|
|
||||||
|
evsel_list = perf_evlist__new();
|
||||||
|
if (evsel_list == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
argc = parse_options(argc, argv, record_options, record_usage,
|
argc = parse_options(argc, argv, record_options, record_usage,
|
||||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||||
if (!argc && target_pid == -1 && target_tid == -1 &&
|
if (!argc && target_pid == -1 && target_tid == -1 &&
|
||||||
|
@ -913,7 +921,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
|
||||||
if (no_buildid_cache || no_buildid)
|
if (no_buildid_cache || no_buildid)
|
||||||
disable_buildid_cache();
|
disable_buildid_cache();
|
||||||
|
|
||||||
if (list_empty(&evsel_list) && perf_evsel_list__create_default() < 0) {
|
if (evsel_list->nr_entries == 0 &&
|
||||||
|
perf_evlist__add_default(evsel_list) < 0) {
|
||||||
pr_err("Not enough memory for event selector list\n");
|
pr_err("Not enough memory for event selector list\n");
|
||||||
goto out_symbol_exit;
|
goto out_symbol_exit;
|
||||||
}
|
}
|
||||||
|
@ -933,7 +942,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(pos, &evsel_list, node) {
|
list_for_each_entry(pos, &evsel_list->entries, node) {
|
||||||
if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
|
if (perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
|
||||||
goto out_free_fd;
|
goto out_free_fd;
|
||||||
if (perf_header__push_event(pos->attr.config, event_name(pos)))
|
if (perf_header__push_event(pos->attr.config, event_name(pos)))
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
#include "util/parse-options.h"
|
#include "util/parse-options.h"
|
||||||
#include "util/parse-events.h"
|
#include "util/parse-events.h"
|
||||||
#include "util/event.h"
|
#include "util/event.h"
|
||||||
|
#include "util/evlist.h"
|
||||||
#include "util/evsel.h"
|
#include "util/evsel.h"
|
||||||
#include "util/debug.h"
|
#include "util/debug.h"
|
||||||
#include "util/header.h"
|
#include "util/header.h"
|
||||||
|
@ -71,6 +72,8 @@ static struct perf_event_attr default_attrs[] = {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct perf_evlist *evsel_list;
|
||||||
|
|
||||||
static bool system_wide = false;
|
static bool system_wide = false;
|
||||||
static struct cpu_map *cpus;
|
static struct cpu_map *cpus;
|
||||||
static int run_idx = 0;
|
static int run_idx = 0;
|
||||||
|
@ -309,7 +312,7 @@ static int run_perf_stat(int argc __used, const char **argv)
|
||||||
close(child_ready_pipe[0]);
|
close(child_ready_pipe[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(counter, &evsel_list, node) {
|
list_for_each_entry(counter, &evsel_list->entries, node) {
|
||||||
if (create_perf_stat_counter(counter) < 0) {
|
if (create_perf_stat_counter(counter) < 0) {
|
||||||
if (errno == -EPERM || errno == -EACCES) {
|
if (errno == -EPERM || errno == -EACCES) {
|
||||||
error("You may not have permission to collect %sstats.\n"
|
error("You may not have permission to collect %sstats.\n"
|
||||||
|
@ -347,12 +350,12 @@ static int run_perf_stat(int argc __used, const char **argv)
|
||||||
update_stats(&walltime_nsecs_stats, t1 - t0);
|
update_stats(&walltime_nsecs_stats, t1 - t0);
|
||||||
|
|
||||||
if (no_aggr) {
|
if (no_aggr) {
|
||||||
list_for_each_entry(counter, &evsel_list, node) {
|
list_for_each_entry(counter, &evsel_list->entries, node) {
|
||||||
read_counter(counter);
|
read_counter(counter);
|
||||||
perf_evsel__close_fd(counter, cpus->nr, 1);
|
perf_evsel__close_fd(counter, cpus->nr, 1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
list_for_each_entry(counter, &evsel_list, node) {
|
list_for_each_entry(counter, &evsel_list->entries, node) {
|
||||||
read_counter_aggr(counter);
|
read_counter_aggr(counter);
|
||||||
perf_evsel__close_fd(counter, cpus->nr, threads->nr);
|
perf_evsel__close_fd(counter, cpus->nr, threads->nr);
|
||||||
}
|
}
|
||||||
|
@ -555,10 +558,10 @@ static void print_stat(int argc, const char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (no_aggr) {
|
if (no_aggr) {
|
||||||
list_for_each_entry(counter, &evsel_list, node)
|
list_for_each_entry(counter, &evsel_list->entries, node)
|
||||||
print_counter(counter);
|
print_counter(counter);
|
||||||
} else {
|
} else {
|
||||||
list_for_each_entry(counter, &evsel_list, node)
|
list_for_each_entry(counter, &evsel_list->entries, node)
|
||||||
print_counter_aggr(counter);
|
print_counter_aggr(counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -610,7 +613,7 @@ static int stat__set_big_num(const struct option *opt __used,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
OPT_CALLBACK('e', "event", NULL, "event",
|
OPT_CALLBACK('e', "event", &evsel_list, "event",
|
||||||
"event selector. use 'perf list' to list available events",
|
"event selector. use 'perf list' to list available events",
|
||||||
parse_events),
|
parse_events),
|
||||||
OPT_BOOLEAN('i', "no-inherit", &no_inherit,
|
OPT_BOOLEAN('i', "no-inherit", &no_inherit,
|
||||||
|
@ -648,6 +651,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
|
evsel_list = perf_evlist__new();
|
||||||
|
if (evsel_list == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
argc = parse_options(argc, argv, options, stat_usage,
|
argc = parse_options(argc, argv, options, stat_usage,
|
||||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||||
|
|
||||||
|
@ -679,17 +686,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
|
||||||
usage_with_options(stat_usage, options);
|
usage_with_options(stat_usage, options);
|
||||||
|
|
||||||
/* Set attrs and nr_counters if no event is selected and !null_run */
|
/* Set attrs and nr_counters if no event is selected and !null_run */
|
||||||
if (!null_run && !nr_counters) {
|
if (!null_run && !evsel_list->nr_entries) {
|
||||||
size_t c;
|
size_t c;
|
||||||
|
|
||||||
nr_counters = ARRAY_SIZE(default_attrs);
|
|
||||||
|
|
||||||
for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
|
for (c = 0; c < ARRAY_SIZE(default_attrs); ++c) {
|
||||||
pos = perf_evsel__new(&default_attrs[c],
|
pos = perf_evsel__new(&default_attrs[c], c);
|
||||||
nr_counters);
|
|
||||||
if (pos == NULL)
|
if (pos == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
list_add(&pos->node, &evsel_list);
|
perf_evlist__add(evsel_list, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -713,7 +717,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_for_each_entry(pos, &evsel_list, node) {
|
list_for_each_entry(pos, &evsel_list->entries, node) {
|
||||||
if (perf_evsel__alloc_stat_priv(pos) < 0 ||
|
if (perf_evsel__alloc_stat_priv(pos) < 0 ||
|
||||||
perf_evsel__alloc_counts(pos, cpus->nr) < 0 ||
|
perf_evsel__alloc_counts(pos, cpus->nr) < 0 ||
|
||||||
perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
|
perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
|
||||||
|
@ -741,9 +745,9 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
|
||||||
if (status != -1)
|
if (status != -1)
|
||||||
print_stat(argc, argv);
|
print_stat(argc, argv);
|
||||||
out_free_fd:
|
out_free_fd:
|
||||||
list_for_each_entry(pos, &evsel_list, node)
|
list_for_each_entry(pos, &evsel_list->entries, node)
|
||||||
perf_evsel__free_stat_priv(pos);
|
perf_evsel__free_stat_priv(pos);
|
||||||
perf_evsel_list__delete();
|
perf_evlist__delete(evsel_list);
|
||||||
out:
|
out:
|
||||||
thread_map__delete(threads);
|
thread_map__delete(threads);
|
||||||
threads = NULL;
|
threads = NULL;
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "perf.h"
|
#include "perf.h"
|
||||||
|
|
||||||
#include "util/color.h"
|
#include "util/color.h"
|
||||||
|
#include "util/evlist.h"
|
||||||
#include "util/evsel.h"
|
#include "util/evsel.h"
|
||||||
#include "util/session.h"
|
#include "util/session.h"
|
||||||
#include "util/symbol.h"
|
#include "util/symbol.h"
|
||||||
|
@ -60,6 +61,8 @@
|
||||||
|
|
||||||
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
||||||
|
|
||||||
|
struct perf_evlist *evsel_list;
|
||||||
|
|
||||||
static bool system_wide = false;
|
static bool system_wide = false;
|
||||||
|
|
||||||
static int default_interval = 0;
|
static int default_interval = 0;
|
||||||
|
@ -267,7 +270,7 @@ static void __zero_source_counters(struct sym_entry *syme)
|
||||||
|
|
||||||
line = syme->src->lines;
|
line = syme->src->lines;
|
||||||
while (line) {
|
while (line) {
|
||||||
for (i = 0; i < nr_counters; i++)
|
for (i = 0; i < evsel_list->nr_entries; i++)
|
||||||
line->count[i] = 0;
|
line->count[i] = 0;
|
||||||
line = line->next;
|
line = line->next;
|
||||||
}
|
}
|
||||||
|
@ -414,7 +417,7 @@ static double sym_weight(const struct sym_entry *sym)
|
||||||
if (!display_weighted)
|
if (!display_weighted)
|
||||||
return weight;
|
return weight;
|
||||||
|
|
||||||
for (counter = 1; counter < nr_counters-1; counter++)
|
for (counter = 1; counter < evsel_list->nr_entries - 1; counter++)
|
||||||
weight *= sym->count[counter];
|
weight *= sym->count[counter];
|
||||||
|
|
||||||
weight /= (sym->count[counter] + 1);
|
weight /= (sym->count[counter] + 1);
|
||||||
|
@ -501,7 +504,7 @@ static void print_sym_table(void)
|
||||||
rb_insert_active_sym(&tmp, syme);
|
rb_insert_active_sym(&tmp, syme);
|
||||||
sum_ksamples += syme->snap_count;
|
sum_ksamples += syme->snap_count;
|
||||||
|
|
||||||
for (j = 0; j < nr_counters; j++)
|
for (j = 0; j < evsel_list->nr_entries; j++)
|
||||||
syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8;
|
syme->count[j] = zero ? 0 : syme->count[j] * 7 / 8;
|
||||||
} else
|
} else
|
||||||
list_remove_active_sym(syme);
|
list_remove_active_sym(syme);
|
||||||
|
@ -535,9 +538,9 @@ static void print_sym_table(void)
|
||||||
esamples_percent);
|
esamples_percent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nr_counters == 1 || !display_weighted) {
|
if (evsel_list->nr_entries == 1 || !display_weighted) {
|
||||||
struct perf_evsel *first;
|
struct perf_evsel *first;
|
||||||
first = list_entry(evsel_list.next, struct perf_evsel, node);
|
first = list_entry(evsel_list->entries.next, struct perf_evsel, node);
|
||||||
printf("%" PRIu64, (uint64_t)first->attr.sample_period);
|
printf("%" PRIu64, (uint64_t)first->attr.sample_period);
|
||||||
if (freq)
|
if (freq)
|
||||||
printf("Hz ");
|
printf("Hz ");
|
||||||
|
@ -547,7 +550,7 @@ static void print_sym_table(void)
|
||||||
|
|
||||||
if (!display_weighted)
|
if (!display_weighted)
|
||||||
printf("%s", event_name(sym_evsel));
|
printf("%s", event_name(sym_evsel));
|
||||||
else list_for_each_entry(counter, &evsel_list, node) {
|
else list_for_each_entry(counter, &evsel_list->entries, node) {
|
||||||
if (counter->idx)
|
if (counter->idx)
|
||||||
printf("/");
|
printf("/");
|
||||||
|
|
||||||
|
@ -606,7 +609,7 @@ static void print_sym_table(void)
|
||||||
sym_width = winsize.ws_col - dso_width - 29;
|
sym_width = winsize.ws_col - dso_width - 29;
|
||||||
}
|
}
|
||||||
putchar('\n');
|
putchar('\n');
|
||||||
if (nr_counters == 1)
|
if (evsel_list->nr_entries == 1)
|
||||||
printf(" samples pcnt");
|
printf(" samples pcnt");
|
||||||
else
|
else
|
||||||
printf(" weight samples pcnt");
|
printf(" weight samples pcnt");
|
||||||
|
@ -615,7 +618,7 @@ static void print_sym_table(void)
|
||||||
printf(" RIP ");
|
printf(" RIP ");
|
||||||
printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
|
printf(" %-*.*s DSO\n", sym_width, sym_width, "function");
|
||||||
printf(" %s _______ _____",
|
printf(" %s _______ _____",
|
||||||
nr_counters == 1 ? " " : "______");
|
evsel_list->nr_entries == 1 ? " " : "______");
|
||||||
if (verbose)
|
if (verbose)
|
||||||
printf(" ________________");
|
printf(" ________________");
|
||||||
printf(" %-*.*s", sym_width, sym_width, graph_line);
|
printf(" %-*.*s", sym_width, sym_width, graph_line);
|
||||||
|
@ -634,7 +637,7 @@ static void print_sym_table(void)
|
||||||
pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
|
pcnt = 100.0 - (100.0 * ((sum_ksamples - syme->snap_count) /
|
||||||
sum_ksamples));
|
sum_ksamples));
|
||||||
|
|
||||||
if (nr_counters == 1 || !display_weighted)
|
if (evsel_list->nr_entries == 1 || !display_weighted)
|
||||||
printf("%20.2f ", syme->weight);
|
printf("%20.2f ", syme->weight);
|
||||||
else
|
else
|
||||||
printf("%9.1f %10ld ", syme->weight, syme->snap_count);
|
printf("%9.1f %10ld ", syme->weight, syme->snap_count);
|
||||||
|
@ -744,7 +747,7 @@ static void print_mapped_keys(void)
|
||||||
fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs);
|
fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs);
|
||||||
fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries);
|
fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries);
|
||||||
|
|
||||||
if (nr_counters > 1)
|
if (evsel_list->nr_entries > 1)
|
||||||
fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel));
|
fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_evsel));
|
||||||
|
|
||||||
fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
|
fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter);
|
||||||
|
@ -753,7 +756,7 @@ static void print_mapped_keys(void)
|
||||||
fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
|
fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL");
|
||||||
fprintf(stdout, "\t[S] stop annotation.\n");
|
fprintf(stdout, "\t[S] stop annotation.\n");
|
||||||
|
|
||||||
if (nr_counters > 1)
|
if (evsel_list->nr_entries > 1)
|
||||||
fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
|
fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0);
|
||||||
|
|
||||||
fprintf(stdout,
|
fprintf(stdout,
|
||||||
|
@ -783,7 +786,7 @@ static int key_mapped(int c)
|
||||||
return 1;
|
return 1;
|
||||||
case 'E':
|
case 'E':
|
||||||
case 'w':
|
case 'w':
|
||||||
return nr_counters > 1 ? 1 : 0;
|
return evsel_list->nr_entries > 1 ? 1 : 0;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -831,22 +834,22 @@ static void handle_keypress(struct perf_session *session, int c)
|
||||||
signal(SIGWINCH, SIG_DFL);
|
signal(SIGWINCH, SIG_DFL);
|
||||||
break;
|
break;
|
||||||
case 'E':
|
case 'E':
|
||||||
if (nr_counters > 1) {
|
if (evsel_list->nr_entries > 1) {
|
||||||
fprintf(stderr, "\nAvailable events:");
|
fprintf(stderr, "\nAvailable events:");
|
||||||
|
|
||||||
list_for_each_entry(sym_evsel, &evsel_list, node)
|
list_for_each_entry(sym_evsel, &evsel_list->entries, node)
|
||||||
fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel));
|
fprintf(stderr, "\n\t%d %s", sym_evsel->idx, event_name(sym_evsel));
|
||||||
|
|
||||||
prompt_integer(&sym_counter, "Enter details event counter");
|
prompt_integer(&sym_counter, "Enter details event counter");
|
||||||
|
|
||||||
if (sym_counter >= nr_counters) {
|
if (sym_counter >= evsel_list->nr_entries) {
|
||||||
sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
|
sym_evsel = list_entry(evsel_list->entries.next, struct perf_evsel, node);
|
||||||
sym_counter = 0;
|
sym_counter = 0;
|
||||||
fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel));
|
fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(sym_evsel));
|
||||||
sleep(1);
|
sleep(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
list_for_each_entry(sym_evsel, &evsel_list, node)
|
list_for_each_entry(sym_evsel, &evsel_list->entries, node)
|
||||||
if (sym_evsel->idx == sym_counter)
|
if (sym_evsel->idx == sym_counter)
|
||||||
break;
|
break;
|
||||||
} else sym_counter = 0;
|
} else sym_counter = 0;
|
||||||
|
@ -1198,7 +1201,7 @@ static void perf_session__mmap_read(struct perf_session *self)
|
||||||
int i, thread_index;
|
int i, thread_index;
|
||||||
|
|
||||||
for (i = 0; i < cpus->nr; i++) {
|
for (i = 0; i < cpus->nr; i++) {
|
||||||
list_for_each_entry(counter, &evsel_list, node) {
|
list_for_each_entry(counter, &evsel_list->entries, node) {
|
||||||
for (thread_index = 0;
|
for (thread_index = 0;
|
||||||
thread_index < threads->nr;
|
thread_index < threads->nr;
|
||||||
thread_index++) {
|
thread_index++) {
|
||||||
|
@ -1312,7 +1315,7 @@ static int __cmd_top(void)
|
||||||
|
|
||||||
for (i = 0; i < cpus->nr; i++) {
|
for (i = 0; i < cpus->nr; i++) {
|
||||||
group_fd = -1;
|
group_fd = -1;
|
||||||
list_for_each_entry(counter, &evsel_list, node)
|
list_for_each_entry(counter, &evsel_list->entries, node)
|
||||||
start_counter(i, counter);
|
start_counter(i, counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1354,7 +1357,7 @@ static const char * const top_usage[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct option options[] = {
|
static const struct option options[] = {
|
||||||
OPT_CALLBACK('e', "event", NULL, "event",
|
OPT_CALLBACK('e', "event", &evsel_list, "event",
|
||||||
"event selector. use 'perf list' to list available events",
|
"event selector. use 'perf list' to list available events",
|
||||||
parse_events),
|
parse_events),
|
||||||
OPT_INTEGER('c', "count", &default_interval,
|
OPT_INTEGER('c', "count", &default_interval,
|
||||||
|
@ -1404,6 +1407,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
|
||||||
struct perf_evsel *pos;
|
struct perf_evsel *pos;
|
||||||
int status = -ENOMEM;
|
int status = -ENOMEM;
|
||||||
|
|
||||||
|
evsel_list = perf_evlist__new();
|
||||||
|
if (evsel_list == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
page_size = sysconf(_SC_PAGE_SIZE);
|
page_size = sysconf(_SC_PAGE_SIZE);
|
||||||
|
|
||||||
argc = parse_options(argc, argv, options, top_usage, 0);
|
argc = parse_options(argc, argv, options, top_usage, 0);
|
||||||
|
@ -1431,7 +1438,8 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
|
||||||
cpu_list = NULL;
|
cpu_list = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nr_counters && perf_evsel_list__create_default() < 0) {
|
if (!evsel_list->nr_entries &&
|
||||||
|
perf_evlist__add_default(evsel_list) < 0) {
|
||||||
pr_err("Not enough memory for event selector list\n");
|
pr_err("Not enough memory for event selector list\n");
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
@ -1459,7 +1467,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
|
||||||
if (cpus == NULL)
|
if (cpus == NULL)
|
||||||
usage_with_options(top_usage, options);
|
usage_with_options(top_usage, options);
|
||||||
|
|
||||||
list_for_each_entry(pos, &evsel_list, node) {
|
list_for_each_entry(pos, &evsel_list->entries, node) {
|
||||||
if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 ||
|
if (perf_evsel__alloc_mmap_per_thread(pos, cpus->nr, threads->nr) < 0 ||
|
||||||
perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
|
perf_evsel__alloc_fd(pos, cpus->nr, threads->nr) < 0)
|
||||||
goto out_free_fd;
|
goto out_free_fd;
|
||||||
|
@ -1472,10 +1480,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
|
||||||
pos->attr.sample_period = default_interval;
|
pos->attr.sample_period = default_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
sym_evsel = list_entry(evsel_list.next, struct perf_evsel, node);
|
sym_evsel = list_entry(evsel_list->entries.next, struct perf_evsel, node);
|
||||||
|
|
||||||
symbol_conf.priv_size = (sizeof(struct sym_entry) +
|
symbol_conf.priv_size = (sizeof(struct sym_entry) +
|
||||||
(nr_counters + 1) * sizeof(unsigned long));
|
(evsel_list->nr_entries + 1) * sizeof(unsigned long));
|
||||||
|
|
||||||
symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
|
symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
|
||||||
if (symbol__init() < 0)
|
if (symbol__init() < 0)
|
||||||
|
@ -1489,9 +1497,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
|
||||||
|
|
||||||
status = __cmd_top();
|
status = __cmd_top();
|
||||||
out_free_fd:
|
out_free_fd:
|
||||||
list_for_each_entry(pos, &evsel_list, node)
|
list_for_each_entry(pos, &evsel_list->entries, node)
|
||||||
perf_evsel__free_mmap(pos);
|
perf_evsel__free_mmap(pos);
|
||||||
perf_evsel_list__delete();
|
perf_evlist__delete(evsel_list);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include "evlist.h"
|
||||||
|
#include "evsel.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
struct perf_evlist *perf_evlist__new(void)
|
||||||
|
{
|
||||||
|
struct perf_evlist *evlist = zalloc(sizeof(*evlist));
|
||||||
|
|
||||||
|
if (evlist != NULL) {
|
||||||
|
INIT_LIST_HEAD(&evlist->entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
return evlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void perf_evlist__purge(struct perf_evlist *evlist)
|
||||||
|
{
|
||||||
|
struct perf_evsel *pos, *n;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(pos, n, &evlist->entries, node) {
|
||||||
|
list_del_init(&pos->node);
|
||||||
|
perf_evsel__delete(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
evlist->nr_entries = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void perf_evlist__delete(struct perf_evlist *evlist)
|
||||||
|
{
|
||||||
|
perf_evlist__purge(evlist);
|
||||||
|
free(evlist);
|
||||||
|
}
|
||||||
|
|
||||||
|
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
|
||||||
|
{
|
||||||
|
list_add_tail(&entry->node, &evlist->entries);
|
||||||
|
++evlist->nr_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
int perf_evlist__add_default(struct perf_evlist *evlist)
|
||||||
|
{
|
||||||
|
struct perf_event_attr attr = {
|
||||||
|
.type = PERF_TYPE_HARDWARE,
|
||||||
|
.config = PERF_COUNT_HW_CPU_CYCLES,
|
||||||
|
};
|
||||||
|
struct perf_evsel *evsel = perf_evsel__new(&attr, 0);
|
||||||
|
|
||||||
|
if (evsel == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
perf_evlist__add(evlist, evsel);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef __PERF_EVLIST_H
|
||||||
|
#define __PERF_EVLIST_H 1
|
||||||
|
|
||||||
|
#include <linux/list.h>
|
||||||
|
|
||||||
|
struct perf_evlist {
|
||||||
|
struct list_head entries;
|
||||||
|
int nr_entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct perf_evsel;
|
||||||
|
|
||||||
|
struct perf_evlist *perf_evlist__new(void);
|
||||||
|
void perf_evlist__delete(struct perf_evlist *evlist);
|
||||||
|
|
||||||
|
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry);
|
||||||
|
int perf_evlist__add_default(struct perf_evlist *evlist);
|
||||||
|
|
||||||
|
#endif /* __PERF_EVLIST_H */
|
|
@ -8,6 +8,7 @@
|
||||||
#include <linux/list.h>
|
#include <linux/list.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
|
||||||
|
#include "evlist.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "header.h"
|
#include "header.h"
|
||||||
#include "../perf.h"
|
#include "../perf.h"
|
||||||
|
@ -428,7 +429,8 @@ static bool perf_session__read_build_ids(struct perf_session *self, bool with_hi
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int perf_header__adds_write(struct perf_header *self, int fd)
|
static int perf_header__adds_write(struct perf_header *self,
|
||||||
|
struct perf_evlist *evlist, int fd)
|
||||||
{
|
{
|
||||||
int nr_sections;
|
int nr_sections;
|
||||||
struct perf_session *session;
|
struct perf_session *session;
|
||||||
|
@ -463,7 +465,7 @@ static int perf_header__adds_write(struct perf_header *self, int fd)
|
||||||
|
|
||||||
/* Write trace info */
|
/* Write trace info */
|
||||||
trace_sec->offset = lseek(fd, 0, SEEK_CUR);
|
trace_sec->offset = lseek(fd, 0, SEEK_CUR);
|
||||||
read_tracing_data(fd, &evsel_list);
|
read_tracing_data(fd, &evlist->entries);
|
||||||
trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
|
trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -513,7 +515,8 @@ int perf_header__write_pipe(int fd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int perf_header__write(struct perf_header *self, int fd, bool at_exit)
|
int perf_header__write(struct perf_header *self, struct perf_evlist *evlist,
|
||||||
|
int fd, bool at_exit)
|
||||||
{
|
{
|
||||||
struct perf_file_header f_header;
|
struct perf_file_header f_header;
|
||||||
struct perf_file_attr f_attr;
|
struct perf_file_attr f_attr;
|
||||||
|
@ -566,7 +569,7 @@ int perf_header__write(struct perf_header *self, int fd, bool at_exit)
|
||||||
self->data_offset = lseek(fd, 0, SEEK_CUR);
|
self->data_offset = lseek(fd, 0, SEEK_CUR);
|
||||||
|
|
||||||
if (at_exit) {
|
if (at_exit) {
|
||||||
err = perf_header__adds_write(self, fd);
|
err = perf_header__adds_write(self, evlist, fd);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -1133,7 +1136,7 @@ int event__process_event_type(event_t *self,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
|
int event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
|
||||||
event__handler_t process,
|
event__handler_t process,
|
||||||
struct perf_session *session __unused)
|
struct perf_session *session __unused)
|
||||||
{
|
{
|
||||||
|
@ -1144,7 +1147,7 @@ int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
|
||||||
memset(&ev, 0, sizeof(ev));
|
memset(&ev, 0, sizeof(ev));
|
||||||
|
|
||||||
ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
|
ev.tracing_data.header.type = PERF_RECORD_HEADER_TRACING_DATA;
|
||||||
size = read_tracing_data_size(fd, pattrs);
|
size = read_tracing_data_size(fd, &evlist->entries);
|
||||||
if (size <= 0)
|
if (size <= 0)
|
||||||
return size;
|
return size;
|
||||||
aligned_size = ALIGN(size, sizeof(u64));
|
aligned_size = ALIGN(size, sizeof(u64));
|
||||||
|
@ -1154,7 +1157,7 @@ int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
|
||||||
|
|
||||||
process(&ev, NULL, session);
|
process(&ev, NULL, session);
|
||||||
|
|
||||||
err = read_tracing_data(fd, pattrs);
|
err = read_tracing_data(fd, &evlist->entries);
|
||||||
write_padded(fd, NULL, 0, padding);
|
write_padded(fd, NULL, 0, padding);
|
||||||
|
|
||||||
return aligned_size;
|
return aligned_size;
|
||||||
|
|
|
@ -65,8 +65,11 @@ struct perf_header {
|
||||||
int perf_header__init(struct perf_header *self);
|
int perf_header__init(struct perf_header *self);
|
||||||
void perf_header__exit(struct perf_header *self);
|
void perf_header__exit(struct perf_header *self);
|
||||||
|
|
||||||
|
struct perf_evlist;
|
||||||
|
|
||||||
int perf_header__read(struct perf_session *session, int fd);
|
int perf_header__read(struct perf_session *session, int fd);
|
||||||
int perf_header__write(struct perf_header *self, int fd, bool at_exit);
|
int perf_header__write(struct perf_header *self, struct perf_evlist *evlist,
|
||||||
|
int fd, bool at_exit);
|
||||||
int perf_header__write_pipe(int fd);
|
int perf_header__write_pipe(int fd);
|
||||||
|
|
||||||
int perf_header__add_attr(struct perf_header *self,
|
int perf_header__add_attr(struct perf_header *self,
|
||||||
|
@ -113,7 +116,7 @@ int event__synthesize_event_types(event__handler_t process,
|
||||||
int event__process_event_type(event_t *self,
|
int event__process_event_type(event_t *self,
|
||||||
struct perf_session *session);
|
struct perf_session *session);
|
||||||
|
|
||||||
int event__synthesize_tracing_data(int fd, struct list_head *pattrs,
|
int event__synthesize_tracing_data(int fd, struct perf_evlist *evlist,
|
||||||
event__handler_t process,
|
event__handler_t process,
|
||||||
struct perf_session *session);
|
struct perf_session *session);
|
||||||
int event__process_tracing_data(event_t *self,
|
int event__process_tracing_data(event_t *self,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include <linux/kernel.h>
|
||||||
#include "../../../../include/linux/list.h"
|
#include "../../../../include/linux/list.h"
|
||||||
|
|
||||||
#ifndef PERF_LIST_H
|
#ifndef PERF_LIST_H
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "../../../include/linux/hw_breakpoint.h"
|
#include "../../../include/linux/hw_breakpoint.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "../perf.h"
|
#include "../perf.h"
|
||||||
|
#include "evlist.h"
|
||||||
#include "evsel.h"
|
#include "evsel.h"
|
||||||
#include "parse-options.h"
|
#include "parse-options.h"
|
||||||
#include "parse-events.h"
|
#include "parse-events.h"
|
||||||
|
@ -11,10 +12,6 @@
|
||||||
#include "header.h"
|
#include "header.h"
|
||||||
#include "debugfs.h"
|
#include "debugfs.h"
|
||||||
|
|
||||||
int nr_counters;
|
|
||||||
|
|
||||||
LIST_HEAD(evsel_list);
|
|
||||||
|
|
||||||
struct event_symbol {
|
struct event_symbol {
|
||||||
u8 type;
|
u8 type;
|
||||||
u64 config;
|
u64 config;
|
||||||
|
@ -778,8 +775,9 @@ modifier:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_events(const struct option *opt __used, const char *str, int unset __used)
|
int parse_events(const struct option *opt, const char *str, int unset __used)
|
||||||
{
|
{
|
||||||
|
struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
|
||||||
struct perf_event_attr attr;
|
struct perf_event_attr attr;
|
||||||
enum event_result ret;
|
enum event_result ret;
|
||||||
|
|
||||||
|
@ -794,12 +792,10 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
|
||||||
|
|
||||||
if (ret != EVT_HANDLED_ALL) {
|
if (ret != EVT_HANDLED_ALL) {
|
||||||
struct perf_evsel *evsel;
|
struct perf_evsel *evsel;
|
||||||
evsel = perf_evsel__new(&attr,
|
evsel = perf_evsel__new(&attr, evlist->nr_entries);
|
||||||
nr_counters);
|
|
||||||
if (evsel == NULL)
|
if (evsel == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
list_add_tail(&evsel->node, &evsel_list);
|
perf_evlist__add(evlist, evsel);
|
||||||
++nr_counters;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*str == 0)
|
if (*str == 0)
|
||||||
|
@ -813,13 +809,14 @@ int parse_events(const struct option *opt __used, const char *str, int unset __u
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_filter(const struct option *opt __used, const char *str,
|
int parse_filter(const struct option *opt, const char *str,
|
||||||
int unset __used)
|
int unset __used)
|
||||||
{
|
{
|
||||||
|
struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
|
||||||
struct perf_evsel *last = NULL;
|
struct perf_evsel *last = NULL;
|
||||||
|
|
||||||
if (!list_empty(&evsel_list))
|
if (evlist->nr_entries > 0)
|
||||||
last = list_entry(evsel_list.prev, struct perf_evsel, node);
|
last = list_entry(evlist->entries.prev, struct perf_evsel, node);
|
||||||
|
|
||||||
if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
|
if (last == NULL || last->attr.type != PERF_TYPE_TRACEPOINT) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
@ -981,33 +978,3 @@ void print_events(void)
|
||||||
|
|
||||||
exit(129);
|
exit(129);
|
||||||
}
|
}
|
||||||
|
|
||||||
int perf_evsel_list__create_default(void)
|
|
||||||
{
|
|
||||||
struct perf_evsel *evsel;
|
|
||||||
struct perf_event_attr attr;
|
|
||||||
|
|
||||||
memset(&attr, 0, sizeof(attr));
|
|
||||||
attr.type = PERF_TYPE_HARDWARE;
|
|
||||||
attr.config = PERF_COUNT_HW_CPU_CYCLES;
|
|
||||||
|
|
||||||
evsel = perf_evsel__new(&attr, 0);
|
|
||||||
|
|
||||||
if (evsel == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
list_add(&evsel->node, &evsel_list);
|
|
||||||
++nr_counters;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void perf_evsel_list__delete(void)
|
|
||||||
{
|
|
||||||
struct perf_evsel *pos, *n;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(pos, n, &evsel_list, node) {
|
|
||||||
list_del_init(&pos->node);
|
|
||||||
perf_evsel__delete(pos);
|
|
||||||
}
|
|
||||||
nr_counters = 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -9,11 +9,6 @@
|
||||||
struct list_head;
|
struct list_head;
|
||||||
struct perf_evsel;
|
struct perf_evsel;
|
||||||
|
|
||||||
extern struct list_head evsel_list;
|
|
||||||
|
|
||||||
int perf_evsel_list__create_default(void);
|
|
||||||
void perf_evsel_list__delete(void);
|
|
||||||
|
|
||||||
struct option;
|
struct option;
|
||||||
|
|
||||||
struct tracepoint_path {
|
struct tracepoint_path {
|
||||||
|
@ -25,8 +20,6 @@ struct tracepoint_path {
|
||||||
extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
|
extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
|
||||||
extern bool have_tracepoints(struct list_head *evlist);
|
extern bool have_tracepoints(struct list_head *evlist);
|
||||||
|
|
||||||
extern int nr_counters;
|
|
||||||
|
|
||||||
const char *event_name(struct perf_evsel *event);
|
const char *event_name(struct perf_evsel *event);
|
||||||
extern const char *__event_name(int type, u64 config);
|
extern const char *__event_name(int type, u64 config);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue