perf/core improvements and fixes
. Prep work for the DWARF CFI post unwinder, so that it doesn't uses perf_session in lots of places, just evlist/evsel is enough. . Make clean brace expansion fix for some shells, from Palmer Cox . Warn user just once per guest kernel when not finding kernel info, from David Ahern . perf test fix from Jiri Olsa . Fix error handling on event creation in perf top, from David Ahern . Fix check on perf_target__strnerror, from Namhyung Kim . Save the whole cmdline, from David Ahern Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iQIcBAABAgAGBQJQG9hnAAoJENZQFvNTUqpAw4kP/iqal/TGlSHZ8p9Uki+ZDLle 2Y7ekbGATn58ST0uNCzvrCcufE4ByBziQ23bMKZesEDFgOMvrS/BbY/eo7Psf1WR f7BoEQBoZloTBIOiw9wn5NGbDrncgRLn9Rg8mmLJaEEiIDuciUC+FQ6tdZtWTp5F fCAqMvGUZ+WPokmnsn23/hA3JyngU2Xz+QA0qrQ19wArxTQrInAUCYAHX6B7GdKi zpkpPJfxYPOkveQG5et+hhldvCtec1sVPelrGx0m3+Oq6Cj5GTW354uUu23P74oR Mcx6RAHBV/znJ38NYqFAb52SNNbc2VpWNKEPL8pu+j7iEDrM2z7qhvTwNvR8u1gb h6tYYs4RIMfNeYujabRusCGY3n5rSI1T5lqk6iBhbZ8wq7TCJe3hY2nB4C+Si0rY j0hogKo3LFhSXPpdwoODSR8MwJQ75vqA9ReTfLE9uJ+h4KtTvJ1T10ifviAmZYbl ykL/O56QvMvc5wvN7UtbvZYHo7ArKmG/V/Bv5eJ9vjeLic0VjKnxLQiWU8KDYidw ZPyQD5yvKQEu4t4vEplto9zmXSb9bTGa41HPfPkz3gFO0efimRvPMIViBJCHm3dG sCF9nD6FFV/W4k3WLA5iE2VxrvclPK6pmTI4rFO9LjsSQQMPiNZM4lC+axx+UXnb r0vms9HVaemjNX5/UHju =y8ib -----END PGP SIGNATURE----- Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent Pull perf/core fixes and some late updates from Arnaldo Carvalho de Melo: * Make clean brace expansion fix for some shells, from Palmer Cox * Warn user just once per guest kernel when not finding kernel info, from David Ahern * perf test fix from Jiri Olsa * Fix error handling on event creation in perf top, from David Ahern * Fix check on perf_target__strnerror, from Namhyung Kim * Save the whole cmdline, from David Ahern * Prep work for the DWARF CFI post unwinder, so that it doesn't uses perf_session in lots of places, just evlist/evsel is enough. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
8a06bf1400
@ -319,6 +319,8 @@ LIB_H += $(ARCH_INCLUDE)
|
|||||||
LIB_H += util/cgroup.h
|
LIB_H += util/cgroup.h
|
||||||
LIB_H += $(TRACE_EVENT_DIR)event-parse.h
|
LIB_H += $(TRACE_EVENT_DIR)event-parse.h
|
||||||
LIB_H += util/target.h
|
LIB_H += util/target.h
|
||||||
|
LIB_H += util/rblist.h
|
||||||
|
LIB_H += util/intlist.h
|
||||||
|
|
||||||
LIB_OBJS += $(OUTPUT)util/abspath.o
|
LIB_OBJS += $(OUTPUT)util/abspath.o
|
||||||
LIB_OBJS += $(OUTPUT)util/alias.o
|
LIB_OBJS += $(OUTPUT)util/alias.o
|
||||||
@ -383,6 +385,8 @@ LIB_OBJS += $(OUTPUT)util/xyarray.o
|
|||||||
LIB_OBJS += $(OUTPUT)util/cpumap.o
|
LIB_OBJS += $(OUTPUT)util/cpumap.o
|
||||||
LIB_OBJS += $(OUTPUT)util/cgroup.o
|
LIB_OBJS += $(OUTPUT)util/cgroup.o
|
||||||
LIB_OBJS += $(OUTPUT)util/target.o
|
LIB_OBJS += $(OUTPUT)util/target.o
|
||||||
|
LIB_OBJS += $(OUTPUT)util/rblist.o
|
||||||
|
LIB_OBJS += $(OUTPUT)util/intlist.o
|
||||||
|
|
||||||
BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
|
BUILTIN_OBJS += $(OUTPUT)builtin-annotate.o
|
||||||
|
|
||||||
@ -983,7 +987,8 @@ clean:
|
|||||||
$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
|
$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope*
|
||||||
$(MAKE) -C Documentation/ clean
|
$(MAKE) -C Documentation/ clean
|
||||||
$(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
|
$(RM) $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)PERF-CFLAGS
|
||||||
$(RM) $(OUTPUT)util/*-{bison,flex}*
|
$(RM) $(OUTPUT)util/*-bison*
|
||||||
|
$(RM) $(OUTPUT)util/*-flex*
|
||||||
$(python-clean)
|
$(python-clean)
|
||||||
|
|
||||||
.PHONY: all install clean strip $(LIBTRACEEVENT)
|
.PHONY: all install clean strip $(LIBTRACEEVENT)
|
||||||
|
@ -313,7 +313,7 @@ try_again:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
perf_session__update_sample_type(session);
|
perf_session__set_id_hdr_size(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_buildids(struct perf_record *rec)
|
static int process_buildids(struct perf_record *rec)
|
||||||
@ -844,8 +844,6 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
|
|||||||
struct perf_record *rec = &record;
|
struct perf_record *rec = &record;
|
||||||
char errbuf[BUFSIZ];
|
char errbuf[BUFSIZ];
|
||||||
|
|
||||||
perf_header__set_cmdline(argc, argv);
|
|
||||||
|
|
||||||
evsel_list = perf_evlist__new(NULL, NULL);
|
evsel_list = perf_evlist__new(NULL, NULL);
|
||||||
if (evsel_list == NULL)
|
if (evsel_list == NULL)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
@ -249,8 +249,9 @@ static int process_read_event(struct perf_tool *tool,
|
|||||||
static int perf_report__setup_sample_type(struct perf_report *rep)
|
static int perf_report__setup_sample_type(struct perf_report *rep)
|
||||||
{
|
{
|
||||||
struct perf_session *self = rep->session;
|
struct perf_session *self = rep->session;
|
||||||
|
u64 sample_type = perf_evlist__sample_type(self->evlist);
|
||||||
|
|
||||||
if (!self->fd_pipe && !(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
|
if (!self->fd_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
|
||||||
if (sort__has_parent) {
|
if (sort__has_parent) {
|
||||||
ui__error("Selected --sort parent, but no "
|
ui__error("Selected --sort parent, but no "
|
||||||
"callchain data. Did you call "
|
"callchain data. Did you call "
|
||||||
@ -274,7 +275,7 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
|
|||||||
|
|
||||||
if (sort__branch_mode == 1) {
|
if (sort__branch_mode == 1) {
|
||||||
if (!self->fd_pipe &&
|
if (!self->fd_pipe &&
|
||||||
!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
|
!(sample_type & PERF_SAMPLE_BRANCH_STACK)) {
|
||||||
ui__error("Selected -b but no branch data. "
|
ui__error("Selected -b but no branch data. "
|
||||||
"Did you call perf record without -b?\n");
|
"Did you call perf record without -b?\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -478,7 +478,6 @@ static int test__basic_mmap(void)
|
|||||||
unsigned int nr_events[nsyscalls],
|
unsigned int nr_events[nsyscalls],
|
||||||
expected_nr_events[nsyscalls], i, j;
|
expected_nr_events[nsyscalls], i, j;
|
||||||
struct perf_evsel *evsels[nsyscalls], *evsel;
|
struct perf_evsel *evsels[nsyscalls], *evsel;
|
||||||
int sample_size = __perf_evsel__sample_size(attr.sample_type);
|
|
||||||
|
|
||||||
for (i = 0; i < nsyscalls; ++i) {
|
for (i = 0; i < nsyscalls; ++i) {
|
||||||
char name[64];
|
char name[64];
|
||||||
@ -563,8 +562,7 @@ static int test__basic_mmap(void)
|
|||||||
goto out_munmap;
|
goto out_munmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = perf_event__parse_sample(event, attr.sample_type, sample_size,
|
err = perf_evlist__parse_sample(evlist, event, &sample, false);
|
||||||
false, &sample, false);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
pr_err("Can't parse sample, err = %d\n", err);
|
pr_err("Can't parse sample, err = %d\n", err);
|
||||||
goto out_munmap;
|
goto out_munmap;
|
||||||
@ -661,12 +659,12 @@ static int test__PERF_RECORD(void)
|
|||||||
const char *cmd = "sleep";
|
const char *cmd = "sleep";
|
||||||
const char *argv[] = { cmd, "1", NULL, };
|
const char *argv[] = { cmd, "1", NULL, };
|
||||||
char *bname;
|
char *bname;
|
||||||
u64 sample_type, prev_time = 0;
|
u64 prev_time = 0;
|
||||||
bool found_cmd_mmap = false,
|
bool found_cmd_mmap = false,
|
||||||
found_libc_mmap = false,
|
found_libc_mmap = false,
|
||||||
found_vdso_mmap = false,
|
found_vdso_mmap = false,
|
||||||
found_ld_mmap = false;
|
found_ld_mmap = false;
|
||||||
int err = -1, errs = 0, i, wakeups = 0, sample_size;
|
int err = -1, errs = 0, i, wakeups = 0;
|
||||||
u32 cpu;
|
u32 cpu;
|
||||||
int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
|
int total_events = 0, nr_events[PERF_RECORD_MAX] = { 0, };
|
||||||
|
|
||||||
@ -756,13 +754,6 @@ static int test__PERF_RECORD(void)
|
|||||||
goto out_delete_evlist;
|
goto out_delete_evlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* We'll need these two to parse the PERF_SAMPLE_* fields in each
|
|
||||||
* event.
|
|
||||||
*/
|
|
||||||
sample_type = perf_evlist__sample_type(evlist);
|
|
||||||
sample_size = __perf_evsel__sample_size(sample_type);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now that all is properly set up, enable the events, they will
|
* Now that all is properly set up, enable the events, they will
|
||||||
* count just on workload.pid, which will start...
|
* count just on workload.pid, which will start...
|
||||||
@ -788,9 +779,7 @@ static int test__PERF_RECORD(void)
|
|||||||
if (type < PERF_RECORD_MAX)
|
if (type < PERF_RECORD_MAX)
|
||||||
nr_events[type]++;
|
nr_events[type]++;
|
||||||
|
|
||||||
err = perf_event__parse_sample(event, sample_type,
|
err = perf_evlist__parse_sample(evlist, event, &sample, false);
|
||||||
sample_size, true,
|
|
||||||
&sample, false);
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
perf_event__fprintf(event, stderr);
|
perf_event__fprintf(event, stderr);
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include "util/cpumap.h"
|
#include "util/cpumap.h"
|
||||||
#include "util/xyarray.h"
|
#include "util/xyarray.h"
|
||||||
#include "util/sort.h"
|
#include "util/sort.h"
|
||||||
|
#include "util/intlist.h"
|
||||||
|
|
||||||
#include "util/debug.h"
|
#include "util/debug.h"
|
||||||
|
|
||||||
@ -706,8 +707,16 @@ static void perf_event__process_sample(struct perf_tool *tool,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!machine && perf_guest) {
|
if (!machine && perf_guest) {
|
||||||
pr_err("Can't find guest [%d]'s kernel information\n",
|
static struct intlist *seen;
|
||||||
event->ip.pid);
|
|
||||||
|
if (!seen)
|
||||||
|
seen = intlist__new();
|
||||||
|
|
||||||
|
if (!intlist__has_entry(seen, event->ip.pid)) {
|
||||||
|
pr_err("Can't find guest [%d]'s kernel information\n",
|
||||||
|
event->ip.pid);
|
||||||
|
intlist__add(seen, event->ip.pid);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,7 +820,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {
|
while ((event = perf_evlist__mmap_read(top->evlist, idx)) != NULL) {
|
||||||
ret = perf_session__parse_sample(session, event, &sample);
|
ret = perf_evlist__parse_sample(top->evlist, event, &sample, false);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_err("Can't parse sample, err = %d\n", ret);
|
pr_err("Can't parse sample, err = %d\n", ret);
|
||||||
continue;
|
continue;
|
||||||
@ -943,8 +952,10 @@ try_again:
|
|||||||
* based cpu-clock-tick sw counter, which
|
* based cpu-clock-tick sw counter, which
|
||||||
* is always available even if no PMU support:
|
* is always available even if no PMU support:
|
||||||
*/
|
*/
|
||||||
if (attr->type == PERF_TYPE_HARDWARE &&
|
if ((err == ENOENT || err == ENXIO) &&
|
||||||
attr->config == PERF_COUNT_HW_CPU_CYCLES) {
|
(attr->type == PERF_TYPE_HARDWARE) &&
|
||||||
|
(attr->config == PERF_COUNT_HW_CPU_CYCLES)) {
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
ui__warning("Cycles event not supported,\n"
|
ui__warning("Cycles event not supported,\n"
|
||||||
"trying to fall back to cpu-clock-ticks\n");
|
"trying to fall back to cpu-clock-ticks\n");
|
||||||
@ -1032,7 +1043,7 @@ static int __cmd_top(struct perf_top *top)
|
|||||||
&top->session->host_machine);
|
&top->session->host_machine);
|
||||||
perf_top__start_counters(top);
|
perf_top__start_counters(top);
|
||||||
top->session->evlist = top->evlist;
|
top->session->evlist = top->evlist;
|
||||||
perf_session__update_sample_type(top->session);
|
perf_session__set_id_hdr_size(top->session);
|
||||||
|
|
||||||
/* Wait for a minimal set of events before starting the snapshot */
|
/* Wait for a minimal set of events before starting the snapshot */
|
||||||
poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
|
poll(top->evlist->pollfd, top->evlist->nr_fds, 100);
|
||||||
|
@ -197,9 +197,6 @@ int perf_event__preprocess_sample(const union perf_event *self,
|
|||||||
|
|
||||||
const char *perf_event__name(unsigned int id);
|
const char *perf_event__name(unsigned int id);
|
||||||
|
|
||||||
int perf_event__parse_sample(const union perf_event *event, u64 type,
|
|
||||||
int sample_size, bool sample_id_all,
|
|
||||||
struct perf_sample *sample, bool swapped);
|
|
||||||
int perf_event__synthesize_sample(union perf_event *event, u64 type,
|
int perf_event__synthesize_sample(union perf_event *event, u64 type,
|
||||||
const struct perf_sample *sample,
|
const struct perf_sample *sample,
|
||||||
bool swapped);
|
bool swapped);
|
||||||
|
@ -881,3 +881,10 @@ int perf_evlist__start_workload(struct perf_evlist *evlist)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
|
||||||
|
struct perf_sample *sample, bool swapped)
|
||||||
|
{
|
||||||
|
struct perf_evsel *e = list_entry(evlist->entries.next, struct perf_evsel, node);
|
||||||
|
return perf_evsel__parse_sample(e, event, sample, swapped);
|
||||||
|
}
|
||||||
|
@ -122,6 +122,9 @@ u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
|
|||||||
bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
|
bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
|
||||||
u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
|
u16 perf_evlist__id_hdr_size(const struct perf_evlist *evlist);
|
||||||
|
|
||||||
|
int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event,
|
||||||
|
struct perf_sample *sample, bool swapped);
|
||||||
|
|
||||||
bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
|
bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
|
||||||
bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
|
bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
|
||||||
|
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
||||||
#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
|
#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
|
||||||
|
|
||||||
int __perf_evsel__sample_size(u64 sample_type)
|
static int __perf_evsel__sample_size(u64 sample_type)
|
||||||
{
|
{
|
||||||
u64 mask = sample_type & PERF_SAMPLE_MASK;
|
u64 mask = sample_type & PERF_SAMPLE_MASK;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
@ -53,6 +53,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
|
|||||||
evsel->attr = *attr;
|
evsel->attr = *attr;
|
||||||
INIT_LIST_HEAD(&evsel->node);
|
INIT_LIST_HEAD(&evsel->node);
|
||||||
hists__init(&evsel->hists);
|
hists__init(&evsel->hists);
|
||||||
|
evsel->sample_size = __perf_evsel__sample_size(attr->sample_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
|
struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
|
||||||
@ -728,10 +729,10 @@ static bool sample_overlap(const union perf_event *event,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int perf_event__parse_sample(const union perf_event *event, u64 type,
|
int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
|
||||||
int sample_size, bool sample_id_all,
|
|
||||||
struct perf_sample *data, bool swapped)
|
struct perf_sample *data, bool swapped)
|
||||||
{
|
{
|
||||||
|
u64 type = evsel->attr.sample_type;
|
||||||
const u64 *array;
|
const u64 *array;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -746,14 +747,14 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
|
|||||||
data->period = 1;
|
data->period = 1;
|
||||||
|
|
||||||
if (event->header.type != PERF_RECORD_SAMPLE) {
|
if (event->header.type != PERF_RECORD_SAMPLE) {
|
||||||
if (!sample_id_all)
|
if (!evsel->attr.sample_id_all)
|
||||||
return 0;
|
return 0;
|
||||||
return perf_event__parse_id_sample(event, type, data, swapped);
|
return perf_event__parse_id_sample(event, type, data, swapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
array = event->sample.array;
|
array = event->sample.array;
|
||||||
|
|
||||||
if (sample_size + sizeof(event->header) > event->header.size)
|
if (evsel->sample_size + sizeof(event->header) > event->header.size)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
if (type & PERF_SAMPLE_IP) {
|
if (type & PERF_SAMPLE_IP) {
|
||||||
@ -895,7 +896,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
|
|||||||
u.val32[1] = sample->tid;
|
u.val32[1] = sample->tid;
|
||||||
if (swapped) {
|
if (swapped) {
|
||||||
/*
|
/*
|
||||||
* Inverse of what is done in perf_event__parse_sample
|
* Inverse of what is done in perf_evsel__parse_sample
|
||||||
*/
|
*/
|
||||||
u.val32[0] = bswap_32(u.val32[0]);
|
u.val32[0] = bswap_32(u.val32[0]);
|
||||||
u.val32[1] = bswap_32(u.val32[1]);
|
u.val32[1] = bswap_32(u.val32[1]);
|
||||||
@ -930,7 +931,7 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type,
|
|||||||
u.val32[0] = sample->cpu;
|
u.val32[0] = sample->cpu;
|
||||||
if (swapped) {
|
if (swapped) {
|
||||||
/*
|
/*
|
||||||
* Inverse of what is done in perf_event__parse_sample
|
* Inverse of what is done in perf_evsel__parse_sample
|
||||||
*/
|
*/
|
||||||
u.val32[0] = bswap_32(u.val32[0]);
|
u.val32[0] = bswap_32(u.val32[0]);
|
||||||
u.val64 = bswap_64(u.val64);
|
u.val64 = bswap_64(u.val64);
|
||||||
|
@ -65,6 +65,7 @@ struct perf_evsel {
|
|||||||
void *func;
|
void *func;
|
||||||
void *data;
|
void *data;
|
||||||
} handler;
|
} handler;
|
||||||
|
unsigned int sample_size;
|
||||||
bool supported;
|
bool supported;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -177,13 +178,8 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
|
|||||||
return __perf_evsel__read(evsel, ncpus, nthreads, true);
|
return __perf_evsel__read(evsel, ncpus, nthreads, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int __perf_evsel__sample_size(u64 sample_type);
|
|
||||||
|
|
||||||
static inline int perf_evsel__sample_size(struct perf_evsel *evsel)
|
|
||||||
{
|
|
||||||
return __perf_evsel__sample_size(evsel->attr.sample_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hists__init(struct hists *hists);
|
void hists__init(struct hists *hists);
|
||||||
|
|
||||||
|
int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
|
||||||
|
struct perf_sample *sample, bool swapped);
|
||||||
#endif /* __PERF_EVSEL_H */
|
#endif /* __PERF_EVSEL_H */
|
||||||
|
@ -174,6 +174,15 @@ perf_header__set_cmdline(int argc, const char **argv)
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If header_argv has already been set, do not override it.
|
||||||
|
* This allows a command to set the cmdline, parse args and
|
||||||
|
* then call another builtin function that implements a
|
||||||
|
* command -- e.g, cmd_kvm calling cmd_record.
|
||||||
|
*/
|
||||||
|
if (header_argv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
header_argc = (u32)argc;
|
header_argc = (u32)argc;
|
||||||
|
|
||||||
/* do not include NULL termination */
|
/* do not include NULL termination */
|
||||||
|
101
tools/perf/util/intlist.c
Normal file
101
tools/perf/util/intlist.c
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
/*
|
||||||
|
* Based on intlist.c by:
|
||||||
|
* (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||||
|
*
|
||||||
|
* Licensed under the GPLv2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <linux/compiler.h>
|
||||||
|
|
||||||
|
#include "intlist.h"
|
||||||
|
|
||||||
|
static struct rb_node *intlist__node_new(struct rblist *rblist __used,
|
||||||
|
const void *entry)
|
||||||
|
{
|
||||||
|
int i = (int)((long)entry);
|
||||||
|
struct rb_node *rc = NULL;
|
||||||
|
struct int_node *node = malloc(sizeof(*node));
|
||||||
|
|
||||||
|
if (node != NULL) {
|
||||||
|
node->i = i;
|
||||||
|
rc = &node->rb_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void int_node__delete(struct int_node *ilist)
|
||||||
|
{
|
||||||
|
free(ilist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void intlist__node_delete(struct rblist *rblist __used,
|
||||||
|
struct rb_node *rb_node)
|
||||||
|
{
|
||||||
|
struct int_node *node = container_of(rb_node, struct int_node, rb_node);
|
||||||
|
|
||||||
|
int_node__delete(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int intlist__node_cmp(struct rb_node *rb_node, const void *entry)
|
||||||
|
{
|
||||||
|
int i = (int)((long)entry);
|
||||||
|
struct int_node *node = container_of(rb_node, struct int_node, rb_node);
|
||||||
|
|
||||||
|
return node->i - i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int intlist__add(struct intlist *ilist, int i)
|
||||||
|
{
|
||||||
|
return rblist__add_node(&ilist->rblist, (void *)((long)i));
|
||||||
|
}
|
||||||
|
|
||||||
|
void intlist__remove(struct intlist *ilist __used, struct int_node *node)
|
||||||
|
{
|
||||||
|
int_node__delete(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct int_node *intlist__find(struct intlist *ilist, int i)
|
||||||
|
{
|
||||||
|
struct int_node *node = NULL;
|
||||||
|
struct rb_node *rb_node = rblist__find(&ilist->rblist, (void *)((long)i));
|
||||||
|
|
||||||
|
if (rb_node)
|
||||||
|
node = container_of(rb_node, struct int_node, rb_node);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct intlist *intlist__new(void)
|
||||||
|
{
|
||||||
|
struct intlist *ilist = malloc(sizeof(*ilist));
|
||||||
|
|
||||||
|
if (ilist != NULL) {
|
||||||
|
rblist__init(&ilist->rblist);
|
||||||
|
ilist->rblist.node_cmp = intlist__node_cmp;
|
||||||
|
ilist->rblist.node_new = intlist__node_new;
|
||||||
|
ilist->rblist.node_delete = intlist__node_delete;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ilist;
|
||||||
|
}
|
||||||
|
|
||||||
|
void intlist__delete(struct intlist *ilist)
|
||||||
|
{
|
||||||
|
if (ilist != NULL)
|
||||||
|
rblist__delete(&ilist->rblist);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx)
|
||||||
|
{
|
||||||
|
struct int_node *node = NULL;
|
||||||
|
struct rb_node *rb_node;
|
||||||
|
|
||||||
|
rb_node = rblist__entry(&ilist->rblist, idx);
|
||||||
|
if (rb_node)
|
||||||
|
node = container_of(rb_node, struct int_node, rb_node);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
75
tools/perf/util/intlist.h
Normal file
75
tools/perf/util/intlist.h
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#ifndef __PERF_INTLIST_H
|
||||||
|
#define __PERF_INTLIST_H
|
||||||
|
|
||||||
|
#include <linux/rbtree.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "rblist.h"
|
||||||
|
|
||||||
|
struct int_node {
|
||||||
|
struct rb_node rb_node;
|
||||||
|
int i;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct intlist {
|
||||||
|
struct rblist rblist;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct intlist *intlist__new(void);
|
||||||
|
void intlist__delete(struct intlist *ilist);
|
||||||
|
|
||||||
|
void intlist__remove(struct intlist *ilist, struct int_node *in);
|
||||||
|
int intlist__add(struct intlist *ilist, int i);
|
||||||
|
|
||||||
|
struct int_node *intlist__entry(const struct intlist *ilist, unsigned int idx);
|
||||||
|
struct int_node *intlist__find(struct intlist *ilist, int i);
|
||||||
|
|
||||||
|
static inline bool intlist__has_entry(struct intlist *ilist, int i)
|
||||||
|
{
|
||||||
|
return intlist__find(ilist, i) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool intlist__empty(const struct intlist *ilist)
|
||||||
|
{
|
||||||
|
return rblist__empty(&ilist->rblist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int intlist__nr_entries(const struct intlist *ilist)
|
||||||
|
{
|
||||||
|
return rblist__nr_entries(&ilist->rblist);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* For intlist iteration */
|
||||||
|
static inline struct int_node *intlist__first(struct intlist *ilist)
|
||||||
|
{
|
||||||
|
struct rb_node *rn = rb_first(&ilist->rblist.entries);
|
||||||
|
return rn ? rb_entry(rn, struct int_node, rb_node) : NULL;
|
||||||
|
}
|
||||||
|
static inline struct int_node *intlist__next(struct int_node *in)
|
||||||
|
{
|
||||||
|
struct rb_node *rn;
|
||||||
|
if (!in)
|
||||||
|
return NULL;
|
||||||
|
rn = rb_next(&in->rb_node);
|
||||||
|
return rn ? rb_entry(rn, struct int_node, rb_node) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* intlist_for_each - iterate over a intlist
|
||||||
|
* @pos: the &struct int_node to use as a loop cursor.
|
||||||
|
* @ilist: the &struct intlist for loop.
|
||||||
|
*/
|
||||||
|
#define intlist__for_each(pos, ilist) \
|
||||||
|
for (pos = intlist__first(ilist); pos; pos = intlist__next(pos))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* intlist_for_each_safe - iterate over a intlist safe against removal of
|
||||||
|
* int_node
|
||||||
|
* @pos: the &struct int_node to use as a loop cursor.
|
||||||
|
* @n: another &struct int_node to use as temporary storage.
|
||||||
|
* @ilist: the &struct intlist for loop.
|
||||||
|
*/
|
||||||
|
#define intlist__for_each_safe(pos, n, ilist) \
|
||||||
|
for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\
|
||||||
|
pos = n, n = intlist__next(n))
|
||||||
|
#endif /* __PERF_INTLIST_H */
|
@ -13,6 +13,9 @@ do { \
|
|||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
#define PERF_TP_SAMPLE_TYPE (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | \
|
||||||
|
PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD)
|
||||||
|
|
||||||
static int test__checkevent_tracepoint(struct perf_evlist *evlist)
|
static int test__checkevent_tracepoint(struct perf_evlist *evlist)
|
||||||
{
|
{
|
||||||
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
struct perf_evsel *evsel = list_entry(evlist->entries.next,
|
||||||
@ -21,8 +24,7 @@ static int test__checkevent_tracepoint(struct perf_evlist *evlist)
|
|||||||
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
|
TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
|
||||||
TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
|
TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
|
||||||
TEST_ASSERT_VAL("wrong sample_type",
|
TEST_ASSERT_VAL("wrong sample_type",
|
||||||
(PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
|
PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
|
||||||
evsel->attr.sample_type);
|
|
||||||
TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
|
TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -37,8 +39,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
|
|||||||
TEST_ASSERT_VAL("wrong type",
|
TEST_ASSERT_VAL("wrong type",
|
||||||
PERF_TYPE_TRACEPOINT == evsel->attr.type);
|
PERF_TYPE_TRACEPOINT == evsel->attr.type);
|
||||||
TEST_ASSERT_VAL("wrong sample_type",
|
TEST_ASSERT_VAL("wrong sample_type",
|
||||||
(PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU)
|
PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
|
||||||
== evsel->attr.sample_type);
|
|
||||||
TEST_ASSERT_VAL("wrong sample_period",
|
TEST_ASSERT_VAL("wrong sample_period",
|
||||||
1 == evsel->attr.sample_period);
|
1 == evsel->attr.sample_period);
|
||||||
}
|
}
|
||||||
@ -428,8 +429,7 @@ static int test__checkevent_list(struct perf_evlist *evlist)
|
|||||||
evsel = list_entry(evsel->node.next, struct perf_evsel, node);
|
evsel = list_entry(evsel->node.next, struct perf_evsel, node);
|
||||||
TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
|
TEST_ASSERT_VAL("wrong type", PERF_TYPE_TRACEPOINT == evsel->attr.type);
|
||||||
TEST_ASSERT_VAL("wrong sample_type",
|
TEST_ASSERT_VAL("wrong sample_type",
|
||||||
(PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | PERF_SAMPLE_CPU) ==
|
PERF_TP_SAMPLE_TYPE == evsel->attr.sample_type);
|
||||||
evsel->attr.sample_type);
|
|
||||||
TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
|
TEST_ASSERT_VAL("wrong sample_period", 1 == evsel->attr.sample_period);
|
||||||
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
|
TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
|
||||||
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
|
TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "parse-options.h"
|
#include "parse-options.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
|
#include "header.h"
|
||||||
|
|
||||||
#define OPT_SHORT 1
|
#define OPT_SHORT 1
|
||||||
#define OPT_UNSET 2
|
#define OPT_UNSET 2
|
||||||
@ -413,6 +414,8 @@ int parse_options(int argc, const char **argv, const struct option *options,
|
|||||||
{
|
{
|
||||||
struct parse_opt_ctx_t ctx;
|
struct parse_opt_ctx_t ctx;
|
||||||
|
|
||||||
|
perf_header__set_cmdline(argc, argv);
|
||||||
|
|
||||||
parse_options_start(&ctx, argc, argv, flags);
|
parse_options_start(&ctx, argc, argv, flags);
|
||||||
switch (parse_options_step(&ctx, options, usagestr)) {
|
switch (parse_options_step(&ctx, options, usagestr)) {
|
||||||
case PARSE_OPT_HELP:
|
case PARSE_OPT_HELP:
|
||||||
|
@ -797,17 +797,13 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
|
|||||||
|
|
||||||
event = perf_evlist__mmap_read(evlist, cpu);
|
event = perf_evlist__mmap_read(evlist, cpu);
|
||||||
if (event != NULL) {
|
if (event != NULL) {
|
||||||
struct perf_evsel *first;
|
|
||||||
PyObject *pyevent = pyrf_event__new(event);
|
PyObject *pyevent = pyrf_event__new(event);
|
||||||
struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
|
struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
|
||||||
|
|
||||||
if (pyevent == NULL)
|
if (pyevent == NULL)
|
||||||
return PyErr_NoMemory();
|
return PyErr_NoMemory();
|
||||||
|
|
||||||
first = list_entry(evlist->entries.next, struct perf_evsel, node);
|
err = perf_evlist__parse_sample(evlist, event, &pevent->sample, false);
|
||||||
err = perf_event__parse_sample(event, first->attr.sample_type,
|
|
||||||
perf_evsel__sample_size(first),
|
|
||||||
sample_id_all, &pevent->sample, false);
|
|
||||||
if (err)
|
if (err)
|
||||||
return PyErr_Format(PyExc_OSError,
|
return PyErr_Format(PyExc_OSError,
|
||||||
"perf: can't parse sample, err=%d", err);
|
"perf: can't parse sample, err=%d", err);
|
||||||
|
107
tools/perf/util/rblist.c
Normal file
107
tools/perf/util/rblist.c
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Based on strlist.c by:
|
||||||
|
* (c) 2009 Arnaldo Carvalho de Melo <acme@redhat.com>
|
||||||
|
*
|
||||||
|
* Licensed under the GPLv2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "rblist.h"
|
||||||
|
|
||||||
|
int rblist__add_node(struct rblist *rblist, const void *new_entry)
|
||||||
|
{
|
||||||
|
struct rb_node **p = &rblist->entries.rb_node;
|
||||||
|
struct rb_node *parent = NULL, *new_node;
|
||||||
|
|
||||||
|
while (*p != NULL) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
parent = *p;
|
||||||
|
|
||||||
|
rc = rblist->node_cmp(parent, new_entry);
|
||||||
|
if (rc > 0)
|
||||||
|
p = &(*p)->rb_left;
|
||||||
|
else if (rc < 0)
|
||||||
|
p = &(*p)->rb_right;
|
||||||
|
else
|
||||||
|
return -EEXIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_node = rblist->node_new(rblist, new_entry);
|
||||||
|
if (new_node == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
rb_link_node(new_node, parent, p);
|
||||||
|
rb_insert_color(new_node, &rblist->entries);
|
||||||
|
++rblist->nr_entries;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node)
|
||||||
|
{
|
||||||
|
rb_erase(rb_node, &rblist->entries);
|
||||||
|
rblist->node_delete(rblist, rb_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rb_node *rblist__find(struct rblist *rblist, const void *entry)
|
||||||
|
{
|
||||||
|
struct rb_node **p = &rblist->entries.rb_node;
|
||||||
|
struct rb_node *parent = NULL;
|
||||||
|
|
||||||
|
while (*p != NULL) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
parent = *p;
|
||||||
|
|
||||||
|
rc = rblist->node_cmp(parent, entry);
|
||||||
|
if (rc > 0)
|
||||||
|
p = &(*p)->rb_left;
|
||||||
|
else if (rc < 0)
|
||||||
|
p = &(*p)->rb_right;
|
||||||
|
else
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rblist__init(struct rblist *rblist)
|
||||||
|
{
|
||||||
|
if (rblist != NULL) {
|
||||||
|
rblist->entries = RB_ROOT;
|
||||||
|
rblist->nr_entries = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rblist__delete(struct rblist *rblist)
|
||||||
|
{
|
||||||
|
if (rblist != NULL) {
|
||||||
|
struct rb_node *pos, *next = rb_first(&rblist->entries);
|
||||||
|
|
||||||
|
while (next) {
|
||||||
|
pos = next;
|
||||||
|
next = rb_next(pos);
|
||||||
|
rb_erase(pos, &rblist->entries);
|
||||||
|
rblist->node_delete(rblist, pos);
|
||||||
|
}
|
||||||
|
free(rblist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx)
|
||||||
|
{
|
||||||
|
struct rb_node *node;
|
||||||
|
|
||||||
|
for (node = rb_first(&rblist->entries); node; node = rb_next(node)) {
|
||||||
|
if (!idx--)
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
47
tools/perf/util/rblist.h
Normal file
47
tools/perf/util/rblist.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#ifndef __PERF_RBLIST_H
|
||||||
|
#define __PERF_RBLIST_H
|
||||||
|
|
||||||
|
#include <linux/rbtree.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* create node structs of the form:
|
||||||
|
* struct my_node {
|
||||||
|
* struct rb_node rb_node;
|
||||||
|
* ... my data ...
|
||||||
|
* };
|
||||||
|
*
|
||||||
|
* create list structs of the form:
|
||||||
|
* struct mylist {
|
||||||
|
* struct rblist rblist;
|
||||||
|
* ... my data ...
|
||||||
|
* };
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct rblist {
|
||||||
|
struct rb_root entries;
|
||||||
|
unsigned int nr_entries;
|
||||||
|
|
||||||
|
int (*node_cmp)(struct rb_node *rbn, const void *entry);
|
||||||
|
struct rb_node *(*node_new)(struct rblist *rlist, const void *new_entry);
|
||||||
|
void (*node_delete)(struct rblist *rblist, struct rb_node *rb_node);
|
||||||
|
};
|
||||||
|
|
||||||
|
void rblist__init(struct rblist *rblist);
|
||||||
|
void rblist__delete(struct rblist *rblist);
|
||||||
|
int rblist__add_node(struct rblist *rblist, const void *new_entry);
|
||||||
|
void rblist__remove_node(struct rblist *rblist, struct rb_node *rb_node);
|
||||||
|
struct rb_node *rblist__find(struct rblist *rblist, const void *entry);
|
||||||
|
struct rb_node *rblist__entry(const struct rblist *rblist, unsigned int idx);
|
||||||
|
|
||||||
|
static inline bool rblist__empty(const struct rblist *rblist)
|
||||||
|
{
|
||||||
|
return rblist->nr_entries == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline unsigned int rblist__nr_entries(const struct rblist *rblist)
|
||||||
|
{
|
||||||
|
return rblist->nr_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __PERF_RBLIST_H */
|
@ -80,14 +80,12 @@ out_close:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void perf_session__update_sample_type(struct perf_session *self)
|
void perf_session__set_id_hdr_size(struct perf_session *session)
|
||||||
{
|
{
|
||||||
self->sample_type = perf_evlist__sample_type(self->evlist);
|
u16 id_hdr_size = perf_evlist__id_hdr_size(session->evlist);
|
||||||
self->sample_size = __perf_evsel__sample_size(self->sample_type);
|
|
||||||
self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
|
session->host_machine.id_hdr_size = id_hdr_size;
|
||||||
self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
|
machines__set_id_hdr_size(&session->machines, id_hdr_size);
|
||||||
self->host_machine.id_hdr_size = self->id_hdr_size;
|
|
||||||
machines__set_id_hdr_size(&self->machines, self->id_hdr_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int perf_session__create_kernel_maps(struct perf_session *self)
|
int perf_session__create_kernel_maps(struct perf_session *self)
|
||||||
@ -147,7 +145,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,
|
|||||||
if (mode == O_RDONLY) {
|
if (mode == O_RDONLY) {
|
||||||
if (perf_session__open(self, force) < 0)
|
if (perf_session__open(self, force) < 0)
|
||||||
goto out_delete;
|
goto out_delete;
|
||||||
perf_session__update_sample_type(self);
|
perf_session__set_id_hdr_size(self);
|
||||||
} else if (mode == O_WRONLY) {
|
} else if (mode == O_WRONLY) {
|
||||||
/*
|
/*
|
||||||
* In O_RDONLY mode this will be performed when reading the
|
* In O_RDONLY mode this will be performed when reading the
|
||||||
@ -158,7 +156,7 @@ struct perf_session *perf_session__new(const char *filename, int mode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (tool && tool->ordering_requires_timestamps &&
|
if (tool && tool->ordering_requires_timestamps &&
|
||||||
tool->ordered_samples && !self->sample_id_all) {
|
tool->ordered_samples && !perf_evlist__sample_id_all(self->evlist)) {
|
||||||
dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
|
dump_printf("WARNING: No sample_id_all support, falling back to unordered processing\n");
|
||||||
tool->ordered_samples = false;
|
tool->ordered_samples = false;
|
||||||
}
|
}
|
||||||
@ -673,7 +671,8 @@ static void flush_sample_queue(struct perf_session *s,
|
|||||||
if (iter->timestamp > limit)
|
if (iter->timestamp > limit)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
ret = perf_session__parse_sample(s, iter->event, &sample);
|
ret = perf_evlist__parse_sample(s->evlist, iter->event, &sample,
|
||||||
|
s->header.needs_swap);
|
||||||
if (ret)
|
if (ret)
|
||||||
pr_err("Can't parse sample, err = %d\n", ret);
|
pr_err("Can't parse sample, err = %d\n", ret);
|
||||||
else
|
else
|
||||||
@ -865,16 +864,18 @@ static void perf_session__print_tstamp(struct perf_session *session,
|
|||||||
union perf_event *event,
|
union perf_event *event,
|
||||||
struct perf_sample *sample)
|
struct perf_sample *sample)
|
||||||
{
|
{
|
||||||
|
u64 sample_type = perf_evlist__sample_type(session->evlist);
|
||||||
|
|
||||||
if (event->header.type != PERF_RECORD_SAMPLE &&
|
if (event->header.type != PERF_RECORD_SAMPLE &&
|
||||||
!session->sample_id_all) {
|
!perf_evlist__sample_id_all(session->evlist)) {
|
||||||
fputs("-1 -1 ", stdout);
|
fputs("-1 -1 ", stdout);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((session->sample_type & PERF_SAMPLE_CPU))
|
if ((sample_type & PERF_SAMPLE_CPU))
|
||||||
printf("%u ", sample->cpu);
|
printf("%u ", sample->cpu);
|
||||||
|
|
||||||
if (session->sample_type & PERF_SAMPLE_TIME)
|
if (sample_type & PERF_SAMPLE_TIME)
|
||||||
printf("%" PRIu64 " ", sample->time);
|
printf("%" PRIu64 " ", sample->time);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -899,6 +900,8 @@ static void dump_event(struct perf_session *session, union perf_event *event,
|
|||||||
static void dump_sample(struct perf_session *session, union perf_event *event,
|
static void dump_sample(struct perf_session *session, union perf_event *event,
|
||||||
struct perf_sample *sample)
|
struct perf_sample *sample)
|
||||||
{
|
{
|
||||||
|
u64 sample_type;
|
||||||
|
|
||||||
if (!dump_trace)
|
if (!dump_trace)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -906,10 +909,12 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
|
|||||||
event->header.misc, sample->pid, sample->tid, sample->ip,
|
event->header.misc, sample->pid, sample->tid, sample->ip,
|
||||||
sample->period, sample->addr);
|
sample->period, sample->addr);
|
||||||
|
|
||||||
if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
|
sample_type = perf_evlist__sample_type(session->evlist);
|
||||||
|
|
||||||
|
if (sample_type & PERF_SAMPLE_CALLCHAIN)
|
||||||
callchain__printf(sample);
|
callchain__printf(sample);
|
||||||
|
|
||||||
if (session->sample_type & PERF_SAMPLE_BRANCH_STACK)
|
if (sample_type & PERF_SAMPLE_BRANCH_STACK)
|
||||||
branch_stack__printf(sample);
|
branch_stack__printf(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1006,7 +1011,7 @@ static int perf_session__preprocess_sample(struct perf_session *session,
|
|||||||
union perf_event *event, struct perf_sample *sample)
|
union perf_event *event, struct perf_sample *sample)
|
||||||
{
|
{
|
||||||
if (event->header.type != PERF_RECORD_SAMPLE ||
|
if (event->header.type != PERF_RECORD_SAMPLE ||
|
||||||
!(session->sample_type & PERF_SAMPLE_CALLCHAIN))
|
!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_CALLCHAIN))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!ip_callchain__valid(sample->callchain, event)) {
|
if (!ip_callchain__valid(sample->callchain, event)) {
|
||||||
@ -1030,7 +1035,7 @@ static int perf_session__process_user_event(struct perf_session *session, union
|
|||||||
case PERF_RECORD_HEADER_ATTR:
|
case PERF_RECORD_HEADER_ATTR:
|
||||||
err = tool->attr(event, &session->evlist);
|
err = tool->attr(event, &session->evlist);
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
perf_session__update_sample_type(session);
|
perf_session__set_id_hdr_size(session);
|
||||||
return err;
|
return err;
|
||||||
case PERF_RECORD_HEADER_EVENT_TYPE:
|
case PERF_RECORD_HEADER_EVENT_TYPE:
|
||||||
return tool->event_type(tool, event);
|
return tool->event_type(tool, event);
|
||||||
@ -1065,7 +1070,7 @@ static int perf_session__process_event(struct perf_session *session,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (session->header.needs_swap)
|
if (session->header.needs_swap)
|
||||||
event_swap(event, session->sample_id_all);
|
event_swap(event, perf_evlist__sample_id_all(session->evlist));
|
||||||
|
|
||||||
if (event->header.type >= PERF_RECORD_HEADER_MAX)
|
if (event->header.type >= PERF_RECORD_HEADER_MAX)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -1078,7 +1083,8 @@ static int perf_session__process_event(struct perf_session *session,
|
|||||||
/*
|
/*
|
||||||
* For all kernel events we get the sample data
|
* For all kernel events we get the sample data
|
||||||
*/
|
*/
|
||||||
ret = perf_session__parse_sample(session, event, &sample);
|
ret = perf_evlist__parse_sample(session->evlist, event, &sample,
|
||||||
|
session->header.needs_swap);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1389,9 +1395,9 @@ int perf_session__process_events(struct perf_session *self,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool perf_session__has_traces(struct perf_session *self, const char *msg)
|
bool perf_session__has_traces(struct perf_session *session, const char *msg)
|
||||||
{
|
{
|
||||||
if (!(self->sample_type & PERF_SAMPLE_RAW)) {
|
if (!(perf_evlist__sample_type(session->evlist) & PERF_SAMPLE_RAW)) {
|
||||||
pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);
|
pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -41,13 +41,9 @@ struct perf_session {
|
|||||||
* perf.data file.
|
* perf.data file.
|
||||||
*/
|
*/
|
||||||
struct hists hists;
|
struct hists hists;
|
||||||
u64 sample_type;
|
|
||||||
int sample_size;
|
|
||||||
int fd;
|
int fd;
|
||||||
bool fd_pipe;
|
bool fd_pipe;
|
||||||
bool repipe;
|
bool repipe;
|
||||||
bool sample_id_all;
|
|
||||||
u16 id_hdr_size;
|
|
||||||
int cwdlen;
|
int cwdlen;
|
||||||
char *cwd;
|
char *cwd;
|
||||||
struct ordered_samples ordered_samples;
|
struct ordered_samples ordered_samples;
|
||||||
@ -86,7 +82,7 @@ void perf_event__attr_swap(struct perf_event_attr *attr);
|
|||||||
|
|
||||||
int perf_session__create_kernel_maps(struct perf_session *self);
|
int perf_session__create_kernel_maps(struct perf_session *self);
|
||||||
|
|
||||||
void perf_session__update_sample_type(struct perf_session *self);
|
void perf_session__set_id_hdr_size(struct perf_session *session);
|
||||||
void perf_session__remove_thread(struct perf_session *self, struct thread *th);
|
void perf_session__remove_thread(struct perf_session *self, struct thread *th);
|
||||||
|
|
||||||
static inline
|
static inline
|
||||||
@ -130,24 +126,6 @@ size_t perf_session__fprintf_dsos_buildid(struct perf_session *self,
|
|||||||
|
|
||||||
size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
|
size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp);
|
||||||
|
|
||||||
static inline int perf_session__parse_sample(struct perf_session *session,
|
|
||||||
const union perf_event *event,
|
|
||||||
struct perf_sample *sample)
|
|
||||||
{
|
|
||||||
return perf_event__parse_sample(event, session->sample_type,
|
|
||||||
session->sample_size,
|
|
||||||
session->sample_id_all, sample,
|
|
||||||
session->header.needs_swap);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int perf_session__synthesize_sample(struct perf_session *session,
|
|
||||||
union perf_event *event,
|
|
||||||
const struct perf_sample *sample)
|
|
||||||
{
|
|
||||||
return perf_event__synthesize_sample(event, session->sample_type,
|
|
||||||
sample, session->header.needs_swap);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
|
struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
|
||||||
unsigned int type);
|
unsigned int type);
|
||||||
|
|
||||||
|
@ -10,23 +10,28 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static struct str_node *str_node__new(const char *s, bool dupstr)
|
static
|
||||||
|
struct rb_node *strlist__node_new(struct rblist *rblist, const void *entry)
|
||||||
{
|
{
|
||||||
struct str_node *self = malloc(sizeof(*self));
|
const char *s = entry;
|
||||||
|
struct rb_node *rc = NULL;
|
||||||
|
struct strlist *strlist = container_of(rblist, struct strlist, rblist);
|
||||||
|
struct str_node *snode = malloc(sizeof(*snode));
|
||||||
|
|
||||||
if (self != NULL) {
|
if (snode != NULL) {
|
||||||
if (dupstr) {
|
if (strlist->dupstr) {
|
||||||
s = strdup(s);
|
s = strdup(s);
|
||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
goto out_delete;
|
goto out_delete;
|
||||||
}
|
}
|
||||||
self->s = s;
|
snode->s = s;
|
||||||
|
rc = &snode->rb_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self;
|
return rc;
|
||||||
|
|
||||||
out_delete:
|
out_delete:
|
||||||
free(self);
|
free(snode);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,36 +42,26 @@ static void str_node__delete(struct str_node *self, bool dupstr)
|
|||||||
free(self);
|
free(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
void strlist__node_delete(struct rblist *rblist, struct rb_node *rb_node)
|
||||||
|
{
|
||||||
|
struct strlist *slist = container_of(rblist, struct strlist, rblist);
|
||||||
|
struct str_node *snode = container_of(rb_node, struct str_node, rb_node);
|
||||||
|
|
||||||
|
str_node__delete(snode, slist->dupstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int strlist__node_cmp(struct rb_node *rb_node, const void *entry)
|
||||||
|
{
|
||||||
|
const char *str = entry;
|
||||||
|
struct str_node *snode = container_of(rb_node, struct str_node, rb_node);
|
||||||
|
|
||||||
|
return strcmp(snode->s, str);
|
||||||
|
}
|
||||||
|
|
||||||
int strlist__add(struct strlist *self, const char *new_entry)
|
int strlist__add(struct strlist *self, const char *new_entry)
|
||||||
{
|
{
|
||||||
struct rb_node **p = &self->entries.rb_node;
|
return rblist__add_node(&self->rblist, new_entry);
|
||||||
struct rb_node *parent = NULL;
|
|
||||||
struct str_node *sn;
|
|
||||||
|
|
||||||
while (*p != NULL) {
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
parent = *p;
|
|
||||||
sn = rb_entry(parent, struct str_node, rb_node);
|
|
||||||
rc = strcmp(sn->s, new_entry);
|
|
||||||
|
|
||||||
if (rc > 0)
|
|
||||||
p = &(*p)->rb_left;
|
|
||||||
else if (rc < 0)
|
|
||||||
p = &(*p)->rb_right;
|
|
||||||
else
|
|
||||||
return -EEXIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
sn = str_node__new(new_entry, self->dupstr);
|
|
||||||
if (sn == NULL)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
rb_link_node(&sn->rb_node, parent, p);
|
|
||||||
rb_insert_color(&sn->rb_node, &self->entries);
|
|
||||||
++self->nr_entries;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int strlist__load(struct strlist *self, const char *filename)
|
int strlist__load(struct strlist *self, const char *filename)
|
||||||
@ -96,34 +91,20 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strlist__remove(struct strlist *self, struct str_node *sn)
|
void strlist__remove(struct strlist *slist, struct str_node *snode)
|
||||||
{
|
{
|
||||||
rb_erase(&sn->rb_node, &self->entries);
|
str_node__delete(snode, slist->dupstr);
|
||||||
str_node__delete(sn, self->dupstr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct str_node *strlist__find(struct strlist *self, const char *entry)
|
struct str_node *strlist__find(struct strlist *slist, const char *entry)
|
||||||
{
|
{
|
||||||
struct rb_node **p = &self->entries.rb_node;
|
struct str_node *snode = NULL;
|
||||||
struct rb_node *parent = NULL;
|
struct rb_node *rb_node = rblist__find(&slist->rblist, entry);
|
||||||
|
|
||||||
while (*p != NULL) {
|
if (rb_node)
|
||||||
struct str_node *sn;
|
snode = container_of(rb_node, struct str_node, rb_node);
|
||||||
int rc;
|
|
||||||
|
|
||||||
parent = *p;
|
return snode;
|
||||||
sn = rb_entry(parent, struct str_node, rb_node);
|
|
||||||
rc = strcmp(sn->s, entry);
|
|
||||||
|
|
||||||
if (rc > 0)
|
|
||||||
p = &(*p)->rb_left;
|
|
||||||
else if (rc < 0)
|
|
||||||
p = &(*p)->rb_right;
|
|
||||||
else
|
|
||||||
return sn;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int strlist__parse_list_entry(struct strlist *self, const char *s)
|
static int strlist__parse_list_entry(struct strlist *self, const char *s)
|
||||||
@ -156,9 +137,12 @@ struct strlist *strlist__new(bool dupstr, const char *slist)
|
|||||||
struct strlist *self = malloc(sizeof(*self));
|
struct strlist *self = malloc(sizeof(*self));
|
||||||
|
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
self->entries = RB_ROOT;
|
rblist__init(&self->rblist);
|
||||||
|
self->rblist.node_cmp = strlist__node_cmp;
|
||||||
|
self->rblist.node_new = strlist__node_new;
|
||||||
|
self->rblist.node_delete = strlist__node_delete;
|
||||||
|
|
||||||
self->dupstr = dupstr;
|
self->dupstr = dupstr;
|
||||||
self->nr_entries = 0;
|
|
||||||
if (slist && strlist__parse_list(self, slist) != 0)
|
if (slist && strlist__parse_list(self, slist) != 0)
|
||||||
goto out_error;
|
goto out_error;
|
||||||
}
|
}
|
||||||
@ -171,30 +155,18 @@ out_error:
|
|||||||
|
|
||||||
void strlist__delete(struct strlist *self)
|
void strlist__delete(struct strlist *self)
|
||||||
{
|
{
|
||||||
if (self != NULL) {
|
if (self != NULL)
|
||||||
struct str_node *pos;
|
rblist__delete(&self->rblist);
|
||||||
struct rb_node *next = rb_first(&self->entries);
|
|
||||||
|
|
||||||
while (next) {
|
|
||||||
pos = rb_entry(next, struct str_node, rb_node);
|
|
||||||
next = rb_next(&pos->rb_node);
|
|
||||||
strlist__remove(self, pos);
|
|
||||||
}
|
|
||||||
self->entries = RB_ROOT;
|
|
||||||
free(self);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct str_node *strlist__entry(const struct strlist *self, unsigned int idx)
|
struct str_node *strlist__entry(const struct strlist *slist, unsigned int idx)
|
||||||
{
|
{
|
||||||
struct rb_node *nd;
|
struct str_node *snode = NULL;
|
||||||
|
struct rb_node *rb_node;
|
||||||
|
|
||||||
for (nd = rb_first(&self->entries); nd; nd = rb_next(nd)) {
|
rb_node = rblist__entry(&slist->rblist, idx);
|
||||||
struct str_node *pos = rb_entry(nd, struct str_node, rb_node);
|
if (rb_node)
|
||||||
|
snode = container_of(rb_node, struct str_node, rb_node);
|
||||||
|
|
||||||
if (!idx--)
|
return snode;
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,15 @@
|
|||||||
#include <linux/rbtree.h>
|
#include <linux/rbtree.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "rblist.h"
|
||||||
|
|
||||||
struct str_node {
|
struct str_node {
|
||||||
struct rb_node rb_node;
|
struct rb_node rb_node;
|
||||||
const char *s;
|
const char *s;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct strlist {
|
struct strlist {
|
||||||
struct rb_root entries;
|
struct rblist rblist;
|
||||||
unsigned int nr_entries;
|
|
||||||
bool dupstr;
|
bool dupstr;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,18 +33,18 @@ static inline bool strlist__has_entry(struct strlist *self, const char *entry)
|
|||||||
|
|
||||||
static inline bool strlist__empty(const struct strlist *self)
|
static inline bool strlist__empty(const struct strlist *self)
|
||||||
{
|
{
|
||||||
return self->nr_entries == 0;
|
return rblist__empty(&self->rblist);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned int strlist__nr_entries(const struct strlist *self)
|
static inline unsigned int strlist__nr_entries(const struct strlist *self)
|
||||||
{
|
{
|
||||||
return self->nr_entries;
|
return rblist__nr_entries(&self->rblist);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* For strlist iteration */
|
/* For strlist iteration */
|
||||||
static inline struct str_node *strlist__first(struct strlist *self)
|
static inline struct str_node *strlist__first(struct strlist *self)
|
||||||
{
|
{
|
||||||
struct rb_node *rn = rb_first(&self->entries);
|
struct rb_node *rn = rb_first(&self->rblist.entries);
|
||||||
return rn ? rb_entry(rn, struct str_node, rb_node) : NULL;
|
return rn ? rb_entry(rn, struct str_node, rb_node) : NULL;
|
||||||
}
|
}
|
||||||
static inline struct str_node *strlist__next(struct str_node *sn)
|
static inline struct str_node *strlist__next(struct str_node *sn)
|
||||||
|
@ -64,7 +64,7 @@ static enum dso_binary_type binary_type_symtab[] = {
|
|||||||
DSO_BINARY_TYPE__NOT_FOUND,
|
DSO_BINARY_TYPE__NOT_FOUND,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab)
|
#define DSO_BINARY_TYPE__SYMTAB_CNT ARRAY_SIZE(binary_type_symtab)
|
||||||
|
|
||||||
static enum dso_binary_type binary_type_data[] = {
|
static enum dso_binary_type binary_type_data[] = {
|
||||||
DSO_BINARY_TYPE__BUILD_ID_CACHE,
|
DSO_BINARY_TYPE__BUILD_ID_CACHE,
|
||||||
@ -72,7 +72,7 @@ static enum dso_binary_type binary_type_data[] = {
|
|||||||
DSO_BINARY_TYPE__NOT_FOUND,
|
DSO_BINARY_TYPE__NOT_FOUND,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data)
|
#define DSO_BINARY_TYPE__DATA_CNT ARRAY_SIZE(binary_type_data)
|
||||||
|
|
||||||
int dso__name_len(const struct dso *dso)
|
int dso__name_len(const struct dso *dso)
|
||||||
{
|
{
|
||||||
@ -2875,6 +2875,7 @@ int machines__create_guest_kernel_maps(struct rb_root *machines)
|
|||||||
int i, items = 0;
|
int i, items = 0;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
|
char *endp;
|
||||||
|
|
||||||
if (symbol_conf.default_guest_vmlinux_name ||
|
if (symbol_conf.default_guest_vmlinux_name ||
|
||||||
symbol_conf.default_guest_modules ||
|
symbol_conf.default_guest_modules ||
|
||||||
@ -2891,7 +2892,14 @@ int machines__create_guest_kernel_maps(struct rb_root *machines)
|
|||||||
/* Filter out . and .. */
|
/* Filter out . and .. */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
pid = atoi(namelist[i]->d_name);
|
pid = (pid_t)strtol(namelist[i]->d_name, &endp, 10);
|
||||||
|
if ((*endp != '\0') ||
|
||||||
|
(endp == namelist[i]->d_name) ||
|
||||||
|
(errno == ERANGE)) {
|
||||||
|
pr_debug("invalid directory (%s). Skipping.\n",
|
||||||
|
namelist[i]->d_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
sprintf(path, "%s/%s/proc/kallsyms",
|
sprintf(path, "%s/%s/proc/kallsyms",
|
||||||
symbol_conf.guestmount,
|
symbol_conf.guestmount,
|
||||||
namelist[i]->d_name);
|
namelist[i]->d_name);
|
||||||
|
@ -110,7 +110,7 @@ int perf_target__strerror(struct perf_target *target, int errnum,
|
|||||||
int idx;
|
int idx;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
|
|
||||||
BUG_ON(buflen > 0);
|
BUG_ON(buflen == 0);
|
||||||
|
|
||||||
if (errnum >= 0) {
|
if (errnum >= 0) {
|
||||||
const char *err = strerror_r(errnum, buf, buflen);
|
const char *err = strerror_r(errnum, buf, buflen);
|
||||||
|
Loading…
Reference in New Issue
Block a user