Commit 479d8758 authored by Ingo Molnar's avatar Ingo Molnar

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

 - Rename libtraceevent 'private' struct member to 'priv' so that it works
   in C++, from Steven Rostedt

 - Remove lots of exit()/die() calls from tools so that the main perf exit
   routine can take place, from David Ahern

 - Fix x86 build on x86-64, from David Ahern.

 - Remove some headers that prevented perf from building on Android,
   from David Ahern

 - {int,str,rb}list fixes from Suzuki K Poulose

 - perf.data header fixes from Namhyung Kim

 - Replace needless mempcpy with memcpy, to allow build on Android, from Irina Tirdea

 - Allow user to indicate objdump path, needed in cross environments, from
   Maciek Borzecki

 - Fix hardware cache event name generation, fix from Jiri Olsa

 - Add round trip test for sw, hw and cache event names, catching the
   problem Jiri fixed, after Jiri's patch, the test passes successfully.

 - Clean target should do clean for lib/traceevent too, fix from David Ahern

 - Check the right variable for allocation failure, fix from Namhyung Kim

 - Set up evsel->tp_format regardless of evsel->name being set already,
   fix from Namhyung Kim
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents bab57e99 275ef387
...@@ -49,7 +49,7 @@ struct pevent_record { ...@@ -49,7 +49,7 @@ struct pevent_record {
int cpu; int cpu;
int ref_count; int ref_count;
int locked; /* Do not free, even if ref_count is zero */ int locked; /* Do not free, even if ref_count is zero */
void *private; void *priv;
#if DEBUG_RECORD #if DEBUG_RECORD
struct pevent_record *prev; struct pevent_record *prev;
struct pevent_record *next; struct pevent_record *next;
...@@ -106,7 +106,7 @@ struct plugin_option { ...@@ -106,7 +106,7 @@ struct plugin_option {
char *plugin_alias; char *plugin_alias;
char *description; char *description;
char *value; char *value;
void *private; void *priv;
int set; int set;
}; };
......
...@@ -85,6 +85,9 @@ OPTIONS ...@@ -85,6 +85,9 @@ OPTIONS
-M:: -M::
--disassembler-style=:: Set disassembler style for objdump. --disassembler-style=:: Set disassembler style for objdump.
--objdump=<path>::
Path to objdump binary.
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-record[1], linkperf:perf-report[1] linkperf:perf-record[1], linkperf:perf-report[1]
...@@ -168,6 +168,9 @@ OPTIONS ...@@ -168,6 +168,9 @@ OPTIONS
branch stacks and it will automatically switch to the branch view mode, branch stacks and it will automatically switch to the branch view mode,
unless --no-branch-stack is used. unless --no-branch-stack is used.
--objdump=<path>::
Path to objdump binary.
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-stat[1], linkperf:perf-annotate[1] linkperf:perf-stat[1], linkperf:perf-annotate[1]
...@@ -64,12 +64,12 @@ AR = $(CROSS_COMPILE)ar ...@@ -64,12 +64,12 @@ AR = $(CROSS_COMPILE)ar
# Additional ARCH settings for x86 # Additional ARCH settings for x86
ifeq ($(ARCH),i386) ifeq ($(ARCH),i386)
ARCH := x86 override ARCH := x86
NO_PERF_REGS := 0 NO_PERF_REGS := 0
LIBUNWIND_LIBS = -lunwind -lunwind-x86 LIBUNWIND_LIBS = -lunwind -lunwind-x86
endif endif
ifeq ($(ARCH),x86_64) ifeq ($(ARCH),x86_64)
ARCH := x86 override ARCH := x86
IS_X86_64 := 0 IS_X86_64 := 0
ifeq (, $(findstring m32,$(EXTRA_CFLAGS))) ifeq (, $(findstring m32,$(EXTRA_CFLAGS)))
IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1) IS_X86_64 := $(shell echo __x86_64__ | ${CC} -E -xc - | tail -n 1)
...@@ -917,6 +917,9 @@ $(LIB_FILE): $(LIB_OBJS) ...@@ -917,6 +917,9 @@ $(LIB_FILE): $(LIB_OBJS)
$(LIBTRACEEVENT): $(LIBTRACEEVENT):
$(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libtraceevent.a $(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) libtraceevent.a
$(LIBTRACEEVENT)-clean:
$(QUIET_SUBDIR0)$(TRACE_EVENT_DIR) $(QUIET_SUBDIR1) O=$(OUTPUT) clean
help: help:
@echo 'Perf make targets:' @echo 'Perf make targets:'
@echo ' doc - make *all* documentation (see below)' @echo ' doc - make *all* documentation (see below)'
...@@ -1056,7 +1059,7 @@ quick-install-html: ...@@ -1056,7 +1059,7 @@ quick-install-html:
### Cleaning rules ### Cleaning rules
clean: clean: $(LIBTRACEEVENT)-clean
$(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS) $(RM) $(LIB_OBJS) $(BUILTIN_OBJS) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf.o $(LANG_BINDINGS)
$(RM) $(ALL_PROGRAMS) perf $(RM) $(ALL_PROGRAMS) perf
$(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*
......
...@@ -282,6 +282,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used) ...@@ -282,6 +282,8 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __used)
"Display raw encoding of assembly instructions (default)"), "Display raw encoding of assembly instructions (default)"),
OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style", OPT_STRING('M', "disassembler-style", &disassembler_style, "disassembler style",
"Specify disassembler style (e.g. -M intel for intel syntax)"), "Specify disassembler style (e.g. -M intel for intel syntax)"),
OPT_STRING(0, "objdump", &objdump_path, "path",
"objdump binary to use for disassembly and annotations"),
OPT_END() OPT_END()
}; };
......
...@@ -24,13 +24,14 @@ static struct man_viewer_info_list { ...@@ -24,13 +24,14 @@ static struct man_viewer_info_list {
} *man_viewer_info_list; } *man_viewer_info_list;
enum help_format { enum help_format {
HELP_FORMAT_NONE,
HELP_FORMAT_MAN, HELP_FORMAT_MAN,
HELP_FORMAT_INFO, HELP_FORMAT_INFO,
HELP_FORMAT_WEB, HELP_FORMAT_WEB,
}; };
static bool show_all = false; static bool show_all = false;
static enum help_format help_format = HELP_FORMAT_MAN; static enum help_format help_format = HELP_FORMAT_NONE;
static struct option builtin_help_options[] = { static struct option builtin_help_options[] = {
OPT_BOOLEAN('a', "all", &show_all, "print all available commands"), OPT_BOOLEAN('a', "all", &show_all, "print all available commands"),
OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), OPT_SET_UINT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN),
...@@ -54,7 +55,9 @@ static enum help_format parse_help_format(const char *format) ...@@ -54,7 +55,9 @@ static enum help_format parse_help_format(const char *format)
return HELP_FORMAT_INFO; return HELP_FORMAT_INFO;
if (!strcmp(format, "web") || !strcmp(format, "html")) if (!strcmp(format, "web") || !strcmp(format, "html"))
return HELP_FORMAT_WEB; return HELP_FORMAT_WEB;
die("unrecognized help format '%s'", format);
pr_err("unrecognized help format '%s'", format);
return HELP_FORMAT_NONE;
} }
static const char *get_man_viewer_info(const char *name) static const char *get_man_viewer_info(const char *name)
...@@ -259,6 +262,8 @@ static int perf_help_config(const char *var, const char *value, void *cb) ...@@ -259,6 +262,8 @@ static int perf_help_config(const char *var, const char *value, void *cb)
if (!value) if (!value)
return config_error_nonbool(var); return config_error_nonbool(var);
help_format = parse_help_format(value); help_format = parse_help_format(value);
if (help_format == HELP_FORMAT_NONE)
return -1;
return 0; return 0;
} }
if (!strcmp(var, "man.viewer")) { if (!strcmp(var, "man.viewer")) {
...@@ -352,7 +357,7 @@ static void exec_viewer(const char *name, const char *page) ...@@ -352,7 +357,7 @@ static void exec_viewer(const char *name, const char *page)
warning("'%s': unknown man viewer.", name); warning("'%s': unknown man viewer.", name);
} }
static void show_man_page(const char *perf_cmd) static int show_man_page(const char *perf_cmd)
{ {
struct man_viewer_list *viewer; struct man_viewer_list *viewer;
const char *page = cmd_to_page(perf_cmd); const char *page = cmd_to_page(perf_cmd);
...@@ -365,28 +370,35 @@ static void show_man_page(const char *perf_cmd) ...@@ -365,28 +370,35 @@ static void show_man_page(const char *perf_cmd)
if (fallback) if (fallback)
exec_viewer(fallback, page); exec_viewer(fallback, page);
exec_viewer("man", page); exec_viewer("man", page);
die("no man viewer handled the request");
pr_err("no man viewer handled the request");
return -1;
} }
static void show_info_page(const char *perf_cmd) static int show_info_page(const char *perf_cmd)
{ {
const char *page = cmd_to_page(perf_cmd); const char *page = cmd_to_page(perf_cmd);
setenv("INFOPATH", system_path(PERF_INFO_PATH), 1); setenv("INFOPATH", system_path(PERF_INFO_PATH), 1);
execlp("info", "info", "perfman", page, NULL); execlp("info", "info", "perfman", page, NULL);
return -1;
} }
static void get_html_page_path(struct strbuf *page_path, const char *page) static int get_html_page_path(struct strbuf *page_path, const char *page)
{ {
struct stat st; struct stat st;
const char *html_path = system_path(PERF_HTML_PATH); const char *html_path = system_path(PERF_HTML_PATH);
/* Check that we have a perf documentation directory. */ /* Check that we have a perf documentation directory. */
if (stat(mkpath("%s/perf.html", html_path), &st) if (stat(mkpath("%s/perf.html", html_path), &st)
|| !S_ISREG(st.st_mode)) || !S_ISREG(st.st_mode)) {
die("'%s': not a documentation directory.", html_path); pr_err("'%s': not a documentation directory.", html_path);
return -1;
}
strbuf_init(page_path, 0); strbuf_init(page_path, 0);
strbuf_addf(page_path, "%s/%s.html", html_path, page); strbuf_addf(page_path, "%s/%s.html", html_path, page);
return 0;
} }
/* /*
...@@ -401,19 +413,23 @@ static void open_html(const char *path) ...@@ -401,19 +413,23 @@ static void open_html(const char *path)
} }
#endif #endif
static void show_html_page(const char *perf_cmd) static int show_html_page(const char *perf_cmd)
{ {
const char *page = cmd_to_page(perf_cmd); const char *page = cmd_to_page(perf_cmd);
struct strbuf page_path; /* it leaks but we exec bellow */ struct strbuf page_path; /* it leaks but we exec bellow */
get_html_page_path(&page_path, page); if (get_html_page_path(&page_path, page) != 0)
return -1;
open_html(page_path.buf); open_html(page_path.buf);
return 0;
} }
int cmd_help(int argc, const char **argv, const char *prefix __used) int cmd_help(int argc, const char **argv, const char *prefix __used)
{ {
const char *alias; const char *alias;
int rc = 0;
load_command_list("perf-", &main_cmds, &other_cmds); load_command_list("perf-", &main_cmds, &other_cmds);
...@@ -444,16 +460,20 @@ int cmd_help(int argc, const char **argv, const char *prefix __used) ...@@ -444,16 +460,20 @@ int cmd_help(int argc, const char **argv, const char *prefix __used)
switch (help_format) { switch (help_format) {
case HELP_FORMAT_MAN: case HELP_FORMAT_MAN:
show_man_page(argv[0]); rc = show_man_page(argv[0]);
break; break;
case HELP_FORMAT_INFO: case HELP_FORMAT_INFO:
show_info_page(argv[0]); rc = show_info_page(argv[0]);
break; break;
case HELP_FORMAT_WEB: case HELP_FORMAT_WEB:
show_html_page(argv[0]); rc = show_html_page(argv[0]);
break;
case HELP_FORMAT_NONE:
/* fall-through */
default: default:
rc = -1;
break; break;
} }
return 0; return rc;
} }
...@@ -161,8 +161,10 @@ static struct thread_stat *thread_stat_findnew_after_first(u32 tid) ...@@ -161,8 +161,10 @@ static struct thread_stat *thread_stat_findnew_after_first(u32 tid)
return st; return st;
st = zalloc(sizeof(struct thread_stat)); st = zalloc(sizeof(struct thread_stat));
if (!st) if (!st) {
die("memory allocation failed\n"); pr_err("memory allocation failed\n");
return NULL;
}
st->tid = tid; st->tid = tid;
INIT_LIST_HEAD(&st->seq_list); INIT_LIST_HEAD(&st->seq_list);
...@@ -181,8 +183,10 @@ static struct thread_stat *thread_stat_findnew_first(u32 tid) ...@@ -181,8 +183,10 @@ static struct thread_stat *thread_stat_findnew_first(u32 tid)
struct thread_stat *st; struct thread_stat *st;
st = zalloc(sizeof(struct thread_stat)); st = zalloc(sizeof(struct thread_stat));
if (!st) if (!st) {
die("memory allocation failed\n"); pr_err("memory allocation failed\n");
return NULL;
}
st->tid = tid; st->tid = tid;
INIT_LIST_HEAD(&st->seq_list); INIT_LIST_HEAD(&st->seq_list);
...@@ -248,18 +252,20 @@ struct lock_key keys[] = { ...@@ -248,18 +252,20 @@ struct lock_key keys[] = {
{ NULL, NULL } { NULL, NULL }
}; };
static void select_key(void) static int select_key(void)
{ {
int i; int i;
for (i = 0; keys[i].name; i++) { for (i = 0; keys[i].name; i++) {
if (!strcmp(keys[i].name, sort_key)) { if (!strcmp(keys[i].name, sort_key)) {
compare = keys[i].key; compare = keys[i].key;
return; return 0;
} }
} }
die("Unknown compare key:%s\n", sort_key); pr_err("Unknown compare key: %s\n", sort_key);
return -1;
} }
static void insert_to_result(struct lock_stat *st, static void insert_to_result(struct lock_stat *st,
...@@ -324,7 +330,8 @@ static struct lock_stat *lock_stat_findnew(void *addr, const char *name) ...@@ -324,7 +330,8 @@ static struct lock_stat *lock_stat_findnew(void *addr, const char *name)
return new; return new;
alloc_failed: alloc_failed:
die("memory allocation failed\n"); pr_err("memory allocation failed\n");
return NULL;
} }
static const char *input_name; static const char *input_name;
...@@ -356,16 +363,16 @@ struct trace_release_event { ...@@ -356,16 +363,16 @@ struct trace_release_event {
}; };
struct trace_lock_handler { struct trace_lock_handler {
void (*acquire_event)(struct trace_acquire_event *, int (*acquire_event)(struct trace_acquire_event *,
const struct perf_sample *sample); const struct perf_sample *sample);
void (*acquired_event)(struct trace_acquired_event *, int (*acquired_event)(struct trace_acquired_event *,
const struct perf_sample *sample); const struct perf_sample *sample);
void (*contended_event)(struct trace_contended_event *, int (*contended_event)(struct trace_contended_event *,
const struct perf_sample *sample); const struct perf_sample *sample);
void (*release_event)(struct trace_release_event *, int (*release_event)(struct trace_release_event *,
const struct perf_sample *sample); const struct perf_sample *sample);
}; };
...@@ -379,8 +386,10 @@ static struct lock_seq_stat *get_seq(struct thread_stat *ts, void *addr) ...@@ -379,8 +386,10 @@ static struct lock_seq_stat *get_seq(struct thread_stat *ts, void *addr)
} }
seq = zalloc(sizeof(struct lock_seq_stat)); seq = zalloc(sizeof(struct lock_seq_stat));
if (!seq) if (!seq) {
die("Not enough memory\n"); pr_err("memory allocation failed\n");
return NULL;
}
seq->state = SEQ_STATE_UNINITIALIZED; seq->state = SEQ_STATE_UNINITIALIZED;
seq->addr = addr; seq->addr = addr;
...@@ -403,7 +412,7 @@ enum acquire_flags { ...@@ -403,7 +412,7 @@ enum acquire_flags {
READ_LOCK = 2, READ_LOCK = 2,
}; };
static void static int
report_lock_acquire_event(struct trace_acquire_event *acquire_event, report_lock_acquire_event(struct trace_acquire_event *acquire_event,
const struct perf_sample *sample) const struct perf_sample *sample)
{ {
...@@ -412,11 +421,18 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event, ...@@ -412,11 +421,18 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event,
struct lock_seq_stat *seq; struct lock_seq_stat *seq;
ls = lock_stat_findnew(acquire_event->addr, acquire_event->name); ls = lock_stat_findnew(acquire_event->addr, acquire_event->name);
if (!ls)
return -1;
if (ls->discard) if (ls->discard)
return; return 0;
ts = thread_stat_findnew(sample->tid); ts = thread_stat_findnew(sample->tid);
if (!ts)
return -1;
seq = get_seq(ts, acquire_event->addr); seq = get_seq(ts, acquire_event->addr);
if (!seq)
return -1;
switch (seq->state) { switch (seq->state) {
case SEQ_STATE_UNINITIALIZED: case SEQ_STATE_UNINITIALIZED:
...@@ -461,10 +477,10 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event, ...@@ -461,10 +477,10 @@ report_lock_acquire_event(struct trace_acquire_event *acquire_event,
ls->nr_acquire++; ls->nr_acquire++;
seq->prev_event_time = sample->time; seq->prev_event_time = sample->time;
end: end:
return; return 0;
} }
static void static int
report_lock_acquired_event(struct trace_acquired_event *acquired_event, report_lock_acquired_event(struct trace_acquired_event *acquired_event,
const struct perf_sample *sample) const struct perf_sample *sample)
{ {
...@@ -475,16 +491,23 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event, ...@@ -475,16 +491,23 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event,
u64 contended_term; u64 contended_term;
ls = lock_stat_findnew(acquired_event->addr, acquired_event->name); ls = lock_stat_findnew(acquired_event->addr, acquired_event->name);
if (!ls)
return -1;
if (ls->discard) if (ls->discard)
return; return 0;
ts = thread_stat_findnew(sample->tid); ts = thread_stat_findnew(sample->tid);
if (!ts)
return -1;
seq = get_seq(ts, acquired_event->addr); seq = get_seq(ts, acquired_event->addr);
if (!seq)
return -1;
switch (seq->state) { switch (seq->state) {
case SEQ_STATE_UNINITIALIZED: case SEQ_STATE_UNINITIALIZED:
/* orphan event, do nothing */ /* orphan event, do nothing */
return; return 0;
case SEQ_STATE_ACQUIRING: case SEQ_STATE_ACQUIRING:
break; break;
case SEQ_STATE_CONTENDED: case SEQ_STATE_CONTENDED:
...@@ -515,10 +538,10 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event, ...@@ -515,10 +538,10 @@ report_lock_acquired_event(struct trace_acquired_event *acquired_event,
ls->nr_acquired++; ls->nr_acquired++;
seq->prev_event_time = timestamp; seq->prev_event_time = timestamp;
end: end:
return; return 0;
} }
static void static int
report_lock_contended_event(struct trace_contended_event *contended_event, report_lock_contended_event(struct trace_contended_event *contended_event,
const struct perf_sample *sample) const struct perf_sample *sample)
{ {
...@@ -527,16 +550,23 @@ report_lock_contended_event(struct trace_contended_event *contended_event, ...@@ -527,16 +550,23 @@ report_lock_contended_event(struct trace_contended_event *contended_event,
struct lock_seq_stat *seq; struct lock_seq_stat *seq;
ls = lock_stat_findnew(contended_event->addr, contended_event->name); ls = lock_stat_findnew(contended_event->addr, contended_event->name);
if (!ls)
return -1;
if (ls->discard) if (ls->discard)
return; return 0;
ts = thread_stat_findnew(sample->tid); ts = thread_stat_findnew(sample->tid);
if (!ts)
return -1;
seq = get_seq(ts, contended_event->addr); seq = get_seq(ts, contended_event->addr);
if (!seq)
return -1;
switch (seq->state) { switch (seq->state) {
case SEQ_STATE_UNINITIALIZED: case SEQ_STATE_UNINITIALIZED:
/* orphan event, do nothing */ /* orphan event, do nothing */
return; return 0;
case SEQ_STATE_ACQUIRING: case SEQ_STATE_ACQUIRING:
break; break;
case SEQ_STATE_RELEASED: case SEQ_STATE_RELEASED:
...@@ -559,10 +589,10 @@ report_lock_contended_event(struct trace_contended_event *contended_event, ...@@ -559,10 +589,10 @@ report_lock_contended_event(struct trace_contended_event *contended_event,
ls->nr_contended++; ls->nr_contended++;
seq->prev_event_time = sample->time; seq->prev_event_time = sample->time;
end: end:
return; return 0;
} }
static void static int
report_lock_release_event(struct trace_release_event *release_event, report_lock_release_event(struct trace_release_event *release_event,
const struct perf_sample *sample) const struct perf_sample *sample)
{ {
...@@ -571,11 +601,18 @@ report_lock_release_event(struct trace_release_event *release_event, ...@@ -571,11 +601,18 @@ report_lock_release_event(struct trace_release_event *release_event,
struct lock_seq_stat *seq; struct lock_seq_stat *seq;
ls = lock_stat_findnew(release_event->addr, release_event->name); ls = lock_stat_findnew(release_event->addr, release_event->name);
if (!ls)
return -1;
if (ls->discard) if (ls->discard)
return; return 0;
ts = thread_stat_findnew(sample->tid); ts = thread_stat_findnew(sample->tid);
if (!ts)
return -1;
seq = get_seq(ts, release_event->addr); seq = get_seq(ts, release_event->addr);
if (!seq)
return -1;
switch (seq->state) { switch (seq->state) {
case SEQ_STATE_UNINITIALIZED: case SEQ_STATE_UNINITIALIZED:
...@@ -609,7 +646,7 @@ report_lock_release_event(struct trace_release_event *release_event, ...@@ -609,7 +646,7 @@ report_lock_release_event(struct trace_release_event *release_event,
list_del(&seq->list); list_del(&seq->list);
free(seq); free(seq);
end: end:
return; return 0;
} }
/* lock oriented handlers */ /* lock oriented handlers */
...@@ -623,13 +660,14 @@ static struct trace_lock_handler report_lock_ops = { ...@@ -623,13 +660,14 @@ static struct trace_lock_handler report_lock_ops = {
static struct trace_lock_handler *trace_handler; static struct trace_lock_handler *trace_handler;
static void perf_evsel__process_lock_acquire(struct perf_evsel *evsel, static int perf_evsel__process_lock_acquire(struct perf_evsel *evsel,
struct perf_sample *sample) struct perf_sample *sample)
{ {
struct trace_acquire_event acquire_event; struct trace_acquire_event acquire_event;
struct event_format *event = evsel->tp_format; struct event_format *event = evsel->tp_format;
void *data = sample->raw_data; void *data = sample->raw_data;
u64 tmp; /* this is required for casting... */ u64 tmp; /* this is required for casting... */
int rc = 0;
tmp = raw_field_value(event, "lockdep_addr", data); tmp = raw_field_value(event, "lockdep_addr", data);
memcpy(&acquire_event.addr, &tmp, sizeof(void *)); memcpy(&acquire_event.addr, &tmp, sizeof(void *));
...@@ -637,70 +675,84 @@ static void perf_evsel__process_lock_acquire(struct perf_evsel *evsel, ...@@ -637,70 +675,84 @@ static void perf_evsel__process_lock_acquire(struct perf_evsel *evsel,
acquire_event.flag = (int)raw_field_value(event, "flag", data); acquire_event.flag = (int)raw_field_value(event, "flag", data);
if (trace_handler->acquire_event) if (trace_handler->acquire_event)
trace_handler->acquire_event(&acquire_event, sample); rc = trace_handler->acquire_event(&acquire_event, sample);
return rc;
} }
static void perf_evsel__process_lock_acquired(struct perf_evsel *evsel, static int perf_evsel__process_lock_acquired(struct perf_evsel *evsel,
struct perf_sample *sample) struct perf_sample *sample)
{ {
struct trace_acquired_event acquired_event; struct trace_acquired_event acquired_event;
struct event_format *event = evsel->tp_format; struct event_format *event = evsel->tp_format;
void *data = sample->raw_data; void *data = sample->raw_data;
u64 tmp; /* this is required for casting... */ u64 tmp; /* this is required for casting... */
int rc = 0;
tmp = raw_field_value(event, "lockdep_addr", data); tmp = raw_field_value(event, "lockdep_addr", data);
memcpy(&acquired_event.addr, &tmp, sizeof(void *)); memcpy(&acquired_event.addr, &tmp, sizeof(void *));
acquired_event.name = (char *)raw_field_ptr(event, "name", data); acquired_event.name = (char *)raw_field_ptr(event, "name", data);
if (trace_handler->acquire_event) if (trace_handler->acquired_event)
trace_handler->acquired_event(&acquired_event, sample); rc = trace_handler->acquired_event(&acquired_event, sample);
return rc;
} }
static void perf_evsel__process_lock_contended(struct perf_evsel *evsel, static int perf_evsel__process_lock_contended(struct perf_evsel *evsel,
struct perf_sample *sample) struct perf_sample *sample)
{ {
struct trace_contended_event contended_event; struct trace_contended_event contended_event;
struct event_format *event = evsel->tp_format; struct event_format *event = evsel->tp_format;
void *data = sample->raw_data; void *data = sample->raw_data;
u64 tmp; /* this is required for casting... */ u64 tmp; /* this is required for casting... */
int rc = 0;
tmp = raw_field_value(event, "lockdep_addr", data); tmp = raw_field_value(event, "lockdep_addr", data);
memcpy(&contended_event.addr, &tmp, sizeof(void *)); memcpy(&contended_event.addr, &tmp, sizeof(void *));
contended_event.name = (char *)raw_field_ptr(event, "name", data); contended_event.name = (char *)raw_field_ptr(event, "name", data);
if (trace_handler->acquire_event) if (trace_handler->contended_event)
trace_handler->contended_event(&contended_event, sample); rc = trace_handler->contended_event(&contended_event, sample);
return rc;
} }
static void perf_evsel__process_lock_release(struct perf_evsel *evsel, static int perf_evsel__process_lock_release(struct perf_evsel *evsel,
struct perf_sample *sample) struct perf_sample *sample)
{ {
struct trace_release_event release_event; struct trace_release_event release_event;
struct event_format *event = evsel->tp_format; struct event_format *event = evsel->tp_format;
void *data = sample->raw_data; void *data = sample->raw_data;
u64 tmp; /* this is required for casting... */ u64 tmp; /* this is required for casting... */
int rc = 0;
tmp = raw_field_value(event, "lockdep_addr", data); tmp = raw_field_value(event, "lockdep_addr", data);
memcpy(&release_event.addr, &tmp, sizeof(void *)); memcpy(&release_event.addr, &tmp, sizeof(void *));
release_event.name = (char *)raw_field_ptr(event, "name", data); release_event.name = (char *)raw_field_ptr(event, "name", data);
if (trace_handler->acquire_event) if (trace_handler->release_event)
trace_handler->release_event(&release_event, sample); rc = trace_handler->release_event(&release_event, sample);
return rc;
} }
static void perf_evsel__process_lock_event(struct perf_evsel *evsel, static int perf_evsel__process_lock_event(struct perf_evsel *evsel,
struct perf_sample *sample) struct perf_sample *sample)
{ {
struct event_format *event = evsel->tp_format; struct event_format *event = evsel->tp_format;
int rc = 0;
if (!strcmp(event->name, "lock_acquire")) if (!strcmp(event->name, "lock_acquire"))
perf_evsel__process_lock_acquire(evsel, sample); rc = perf_evsel__process_lock_acquire(evsel, sample);
if (!strcmp(event->name, "lock_acquired")) if (!strcmp(event->name, "lock_acquired"))
perf_evsel__process_lock_acquired(evsel, sample); rc = perf_evsel__process_lock_acquired(evsel, sample);
if (!strcmp(event->name, "lock_contended")) if (!strcmp(event->name, "lock_contended"))
perf_evsel__process_lock_contended(evsel, sample); rc = perf_evsel__process_lock_contended(evsel, sample);
if (!strcmp(event->name, "lock_release")) if (!strcmp(event->name, "lock_release"))
perf_evsel__process_lock_release(evsel, sample); rc = perf_evsel__process_lock_release(evsel, sample);
return rc;
} }
static void print_bad_events(int bad, int total) static void print_bad_events(int bad, int total)
...@@ -802,14 +854,20 @@ static void dump_map(void) ...@@ -802,14 +854,20 @@ static void dump_map(void)
} }
} }
static void dump_info(void) static int dump_info(void)
{ {
int rc = 0;
if (info_threads) if (info_threads)
dump_threads(); dump_threads();
else if (info_map) else if (info_map)
dump_map(); dump_map();
else else {
die("Unknown type of information\n"); rc = -1;
pr_err("Unknown type of information\n");
}
return rc;
} }
static int process_sample_event(struct perf_tool *tool __used, static int process_sample_event(struct perf_tool *tool __used,
...@@ -826,8 +884,7 @@ static int process_sample_event(struct perf_tool *tool __used, ...@@ -826,8 +884,7 @@ static int process_sample_event(struct perf_tool *tool __used,
return -1; return -1;
} }
perf_evsel__process_lock_event(evsel, sample); return perf_evsel__process_lock_event(evsel, sample);
return 0;
} }
static struct perf_tool eops = { static struct perf_tool eops = {
...@@ -839,8 +896,10 @@ static struct perf_tool eops = { ...@@ -839,8 +896,10 @@ static struct perf_tool eops = {
static int read_events(void) static int read_events(void)
{ {
session = perf_session__new(input_name, O_RDONLY, 0, false, &eops); session = perf_session__new(input_name, O_RDONLY, 0, false, &eops);
if (!session) if (!session) {
die("Initializing perf session failed\n"); pr_err("Initializing perf session failed\n");
return -1;
}
return perf_session__process_events(session, &eops); return perf_session__process_events(session, &eops);
} }
...@@ -857,13 +916,18 @@ static void sort_result(void) ...@@ -857,13 +916,18 @@ static void sort_result(void)
} }
} }
static void __cmd_report(void) static int __cmd_report(void)
{ {
setup_pager(); setup_pager();
select_key();
read_events(); if ((select_key() != 0) ||
(read_events() != 0))
return -1;
sort_result(); sort_result();
print_result(); print_result();
return 0;
} }
static const char * const report_usage[] = { static const char * const report_usage[] = {
...@@ -959,6 +1023,7 @@ static int __cmd_record(int argc, const char **argv) ...@@ -959,6 +1023,7 @@ static int __cmd_record(int argc, const char **argv)
int cmd_lock(int argc, const char **argv, const char *prefix __used) int cmd_lock(int argc, const char **argv, const char *prefix __used)
{ {
unsigned int i; unsigned int i;
int rc = 0;
symbol__init(); symbol__init();
for (i = 0; i < LOCKHASH_SIZE; i++) for (i = 0; i < LOCKHASH_SIZE; i++)
...@@ -993,11 +1058,13 @@ int cmd_lock(int argc, const char **argv, const char *prefix __used) ...@@ -993,11 +1058,13 @@ int cmd_lock(int argc, const char **argv, const char *prefix __used)
/* recycling report_lock_ops */ /* recycling report_lock_ops */
trace_handler = &report_lock_ops; trace_handler = &report_lock_ops;
setup_pager(); setup_pager();
read_events(); if (read_events() != 0)
dump_info(); rc = -1;
else
rc = dump_info();
} else { } else {
usage_with_options(lock_usage, lock_options); usage_with_options(lock_usage, lock_options);
} }
return 0; return rc;
} }
...@@ -71,19 +71,23 @@ static void advance_output(struct perf_record *rec, size_t size) ...@@ -71,19 +71,23 @@ static void advance_output(struct perf_record *rec, size_t size)
rec->bytes_written += size; rec->bytes_written += size;
} }
static void write_output(struct perf_record *rec, void *buf, size_t size) static int write_output(struct perf_record *rec, void *buf, size_t size)
{ {
while (size) { while (size) {
int ret = write(rec->output, buf, size); int ret = write(rec->output, buf, size);
if (ret < 0) if (ret < 0) {
die("failed to write"); pr_err("failed to write\n");
return -1;
}
size -= ret; size -= ret;
buf += ret; buf += ret;
rec->bytes_written += ret; rec->bytes_written += ret;
} }
return 0;
} }
static int process_synthesized_event(struct perf_tool *tool, static int process_synthesized_event(struct perf_tool *tool,
...@@ -92,11 +96,13 @@ static int process_synthesized_event(struct perf_tool *tool, ...@@ -92,11 +96,13 @@ static int process_synthesized_event(struct perf_tool *tool,
struct machine *machine __used) struct machine *machine __used)
{ {
struct perf_record *rec = container_of(tool, struct perf_record, tool); struct perf_record *rec = container_of(tool, struct perf_record, tool);
write_output(rec, event, event->header.size); if (write_output(rec, event, event->header.size) < 0)
return -1;
return 0; return 0;
} }
static void perf_record__mmap_read(struct perf_record *rec, static int perf_record__mmap_read(struct perf_record *rec,
struct perf_mmap *md) struct perf_mmap *md)
{ {
unsigned int head = perf_mmap__read_head(md); unsigned int head = perf_mmap__read_head(md);
...@@ -104,9 +110,10 @@ static void perf_record__mmap_read(struct perf_record *rec, ...@@ -104,9 +110,10 @@ static void perf_record__mmap_read(struct perf_record *rec,
unsigned char *data = md->base + rec->page_size; unsigned char *data = md->base + rec->page_size;
unsigned long size; unsigned long size;
void *buf; void *buf;
int rc = 0;
if (old == head) if (old == head)
return; return 0;
rec->samples++; rec->samples++;
...@@ -117,17 +124,26 @@ static void perf_record__mmap_read(struct perf_record *rec, ...@@ -117,17 +124,26 @@ static void perf_record__mmap_read(struct perf_record *rec,
size = md->mask + 1 - (old & md->mask); size = md->mask + 1 - (old & md->mask);
old += size; old += size;
write_output(rec, buf, size); if (write_output(rec, buf, size) < 0) {
rc = -1;
goto out;
}
} }
buf = &data[old & md->mask]; buf = &data[old & md->mask];
size = head - old; size = head - old;
old += size; old += size;
write_output(rec, buf, size); if (write_output(rec, buf, size) < 0) {
rc = -1;
goto out;
}
md->prev = old; md->prev = old;
perf_mmap__write_tail(md, old); perf_mmap__write_tail(md, old);
out:
return rc;
} }
static volatile int done = 0; static volatile int done = 0;
...@@ -183,12 +199,13 @@ static bool perf_evlist__equal(struct perf_evlist *evlist, ...@@ -183,12 +199,13 @@ static bool perf_evlist__equal(struct perf_evlist *evlist,
return true; return true;
} }
static void perf_record__open(struct perf_record *rec) static int perf_record__open(struct perf_record *rec)
{ {
struct perf_evsel *pos; struct perf_evsel *pos;
struct perf_evlist *evlist = rec->evlist; struct perf_evlist *evlist = rec->evlist;
struct perf_session *session = rec->session; struct perf_session *session = rec->session;
struct perf_record_opts *opts = &rec->opts; struct perf_record_opts *opts = &rec->opts;
int rc = 0;
perf_evlist__config_attrs(evlist, opts); perf_evlist__config_attrs(evlist, opts);
...@@ -222,10 +239,13 @@ static void perf_record__open(struct perf_record *rec) ...@@ -222,10 +239,13 @@ static void perf_record__open(struct perf_record *rec)
if (err == EPERM || err == EACCES) { if (err == EPERM || err == EACCES) {
ui__error_paranoid(); ui__error_paranoid();
exit(EXIT_FAILURE); rc = -err;
goto out;
} else if (err == ENODEV && opts->target.cpu_list) { } else if (err == ENODEV && opts->target.cpu_list) {
die("No such device - did you specify" pr_err("No such device - did you specify"
" an out-of-range profile CPU?\n"); " an out-of-range profile CPU?\n");
rc = -err;
goto out;
} else if (err == EINVAL) { } else if (err == EINVAL) {
if (!opts->exclude_guest_missing && if (!opts->exclude_guest_missing &&
(attr->exclude_guest || attr->exclude_host)) { (attr->exclude_guest || attr->exclude_host)) {
...@@ -272,7 +292,8 @@ static void perf_record__open(struct perf_record *rec) ...@@ -272,7 +292,8 @@ static void perf_record__open(struct perf_record *rec)
if (err == ENOENT) { if (err == ENOENT) {
ui__error("The %s event is not supported.\n", ui__error("The %s event is not supported.\n",
perf_evsel__name(pos)); perf_evsel__name(pos));
exit(EXIT_FAILURE); rc = -err;
goto out;
} }
printf("\n"); printf("\n");
...@@ -280,34 +301,46 @@ static void perf_record__open(struct perf_record *rec) ...@@ -280,34 +301,46 @@ static void perf_record__open(struct perf_record *rec)
err, strerror(err)); err, strerror(err));
#if defined(__i386__) || defined(__x86_64__) #if defined(__i386__) || defined(__x86_64__)
if (attr->type == PERF_TYPE_HARDWARE && err == EOPNOTSUPP) if (attr->type == PERF_TYPE_HARDWARE &&
die("No hardware sampling interrupt available." err == EOPNOTSUPP) {
pr_err("No hardware sampling interrupt available."
" No APIC? If so then you can boot the kernel" " No APIC? If so then you can boot the kernel"
" with the \"lapic\" boot parameter to" " with the \"lapic\" boot parameter to"
" force-enable it.\n"); " force-enable it.\n");
rc = -err;
goto out;
}
#endif #endif
die("No CONFIG_PERF_EVENTS=y kernel support configured?\n"); pr_err("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
rc = -err;
goto out;
} }
} }
if (perf_evlist__set_filters(evlist)) { if (perf_evlist__set_filters(evlist)) {
error("failed to set filter with %d (%s)\n", errno, error("failed to set filter with %d (%s)\n", errno,
strerror(errno)); strerror(errno));
exit(-1); rc = -1;
goto out;
} }
if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
if (errno == EPERM) if (errno == EPERM) {
die("Permission error mapping pages.\n" pr_err("Permission error mapping pages.\n"
"Consider increasing " "Consider increasing "
"/proc/sys/kernel/perf_event_mlock_kb,\n" "/proc/sys/kernel/perf_event_mlock_kb,\n"
"or try again with a smaller value of -m/--mmap_pages.\n" "or try again with a smaller value of -m/--mmap_pages.\n"
"(current value: %d)\n", opts->mmap_pages); "(current value: %d)\n", opts->mmap_pages);
else if (!is_power_of_2(opts->mmap_pages)) rc = -errno;
die("--mmap_pages/-m value must be a power of two."); } else if (!is_power_of_2(opts->mmap_pages)) {
pr_err("--mmap_pages/-m value must be a power of two.");
die("failed to mmap with %d (%s)\n", errno, strerror(errno)); rc = -EINVAL;
} else {
pr_err("failed to mmap with %d (%s)\n", errno, strerror(errno));
rc = -errno;
}
goto out;
} }
if (rec->file_new) if (rec->file_new)
...@@ -315,11 +348,14 @@ static void perf_record__open(struct perf_record *rec) ...@@ -315,11 +348,14 @@ static void perf_record__open(struct perf_record *rec)
else { else {
if (!perf_evlist__equal(session->evlist, evlist)) { if (!perf_evlist__equal(session->evlist, evlist)) {
fprintf(stderr, "incompatible append\n"); fprintf(stderr, "incompatible append\n");
exit(-1); rc = -1;
goto out;
} }
} }
perf_session__set_id_hdr_size(session); perf_session__set_id_hdr_size(session);
out:
return rc;
} }
static int process_buildids(struct perf_record *rec) static int process_buildids(struct perf_record *rec)
...@@ -335,10 +371,13 @@ static int process_buildids(struct perf_record *rec) ...@@ -335,10 +371,13 @@ static int process_buildids(struct perf_record *rec)
size, &build_id__mark_dso_hit_ops); size, &build_id__mark_dso_hit_ops);
} }
static void perf_record__exit(int status __used, void *arg) static void perf_record__exit(int status, void *arg)
{ {
struct perf_record *rec = arg; struct perf_record *rec = arg;
if (status != 0)
return;
if (!rec->opts.pipe_output) { if (!rec->opts.pipe_output) {
rec->session->header.data_size += rec->bytes_written; rec->session->header.data_size += rec->bytes_written;
...@@ -393,17 +432,26 @@ static struct perf_event_header finished_round_event = { ...@@ -393,17 +432,26 @@ static struct perf_event_header finished_round_event = {
.type = PERF_RECORD_FINISHED_ROUND, .type = PERF_RECORD_FINISHED_ROUND,
}; };
static void perf_record__mmap_read_all(struct perf_record *rec) static int perf_record__mmap_read_all(struct perf_record *rec)
{ {
int i; int i;
int rc = 0;
for (i = 0; i < rec->evlist->nr_mmaps; i++) { for (i = 0; i < rec->evlist->nr_mmaps; i++) {
if (rec->evlist->mmap[i].base) if (rec->evlist->mmap[i].base) {
perf_record__mmap_read(rec, &rec->evlist->mmap[i]); if (perf_record__mmap_read(rec, &rec->evlist->mmap[i]) != 0) {
rc = -1;
goto out;
}
}
} }
if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA))
write_output(rec, &finished_round_event, sizeof(finished_round_event)); rc = write_output(rec, &finished_round_event,
sizeof(finished_round_event));
out:
return rc;
} }
static int __cmd_record(struct perf_record *rec, int argc, const char **argv) static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
...@@ -463,7 +511,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -463,7 +511,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
output = open(output_name, flags, S_IRUSR | S_IWUSR); output = open(output_name, flags, S_IRUSR | S_IWUSR);
if (output < 0) { if (output < 0) {
perror("failed to create output file"); perror("failed to create output file");
exit(-1); return -1;
} }
rec->output = output; rec->output = output;
...@@ -503,7 +551,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -503,7 +551,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
} }
} }
perf_record__open(rec); if (perf_record__open(rec) != 0) {
err = -1;
goto out_delete_session;
}
/* /*
* perf_session__delete(session) will be called at perf_record__exit() * perf_session__delete(session) will be called at perf_record__exit()
...@@ -513,19 +564,20 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -513,19 +564,20 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
if (opts->pipe_output) { if (opts->pipe_output) {
err = perf_header__write_pipe(output); err = perf_header__write_pipe(output);
if (err < 0) if (err < 0)
return err; goto out_delete_session;
} else if (rec->file_new) { } else if (rec->file_new) {
err = perf_session__write_header(session, evsel_list, err = perf_session__write_header(session, evsel_list,
output, false); output, false);
if (err < 0) if (err < 0)
return err; goto out_delete_session;
} }
if (!rec->no_buildid if (!rec->no_buildid
&& !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) { && !perf_header__has_feat(&session->header, HEADER_BUILD_ID)) {
pr_err("Couldn't generate buildids. " pr_err("Couldn't generate buildids. "
"Use --no-buildid to profile anyway.\n"); "Use --no-buildid to profile anyway.\n");
return -1; err = -1;
goto out_delete_session;
} }
rec->post_processing_offset = lseek(output, 0, SEEK_CUR); rec->post_processing_offset = lseek(output, 0, SEEK_CUR);
...@@ -533,7 +585,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -533,7 +585,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
machine = perf_session__find_host_machine(session); machine = perf_session__find_host_machine(session);
if (!machine) { if (!machine) {
pr_err("Couldn't find native kernel information.\n"); pr_err("Couldn't find native kernel information.\n");
return -1; err = -1;
goto out_delete_session;
} }
if (opts->pipe_output) { if (opts->pipe_output) {
...@@ -541,14 +594,14 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -541,14 +594,14 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
process_synthesized_event); process_synthesized_event);
if (err < 0) { if (err < 0) {
pr_err("Couldn't synthesize attrs.\n"); pr_err("Couldn't synthesize attrs.\n");
return err; goto out_delete_session;
} }
err = perf_event__synthesize_event_types(tool, process_synthesized_event, err = perf_event__synthesize_event_types(tool, process_synthesized_event,
machine); machine);
if (err < 0) { if (err < 0) {
pr_err("Couldn't synthesize event_types.\n"); pr_err("Couldn't synthesize event_types.\n");
return err; goto out_delete_session;
} }
if (have_tracepoints(&evsel_list->entries)) { if (have_tracepoints(&evsel_list->entries)) {
...@@ -564,7 +617,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -564,7 +617,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
process_synthesized_event); process_synthesized_event);
if (err <= 0) { if (err <= 0) {
pr_err("Couldn't record tracing data.\n"); pr_err("Couldn't record tracing data.\n");
return err; goto out_delete_session;
} }
advance_output(rec, err); advance_output(rec, err);
} }
...@@ -592,20 +645,24 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -592,20 +645,24 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
perf_event__synthesize_guest_os); perf_event__synthesize_guest_os);
if (!opts->target.system_wide) if (!opts->target.system_wide)
perf_event__synthesize_thread_map(tool, evsel_list->threads, err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
process_synthesized_event, process_synthesized_event,
machine); machine);
else else
perf_event__synthesize_threads(tool, process_synthesized_event, err = perf_event__synthesize_threads(tool, process_synthesized_event,
machine); machine);
if (err != 0)
goto out_delete_session;
if (rec->realtime_prio) { if (rec->realtime_prio) {
struct sched_param param; struct sched_param param;
param.sched_priority = rec->realtime_prio; param.sched_priority = rec->realtime_prio;
if (sched_setscheduler(0, SCHED_FIFO, &param)) { if (sched_setscheduler(0, SCHED_FIFO, &param)) {
pr_err("Could not set realtime priority.\n"); pr_err("Could not set realtime priority.\n");
exit(-1); err = -1;
goto out_delete_session;
} }
} }
...@@ -620,7 +677,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -620,7 +677,10 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
for (;;) { for (;;) {
int hits = rec->samples; int hits = rec->samples;
perf_record__mmap_read_all(rec); if (perf_record__mmap_read_all(rec) < 0) {
err = -1;
goto out_delete_session;
}
if (hits == rec->samples) { if (hits == rec->samples) {
if (done) if (done)
......
...@@ -638,6 +638,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used) ...@@ -638,6 +638,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __used)
"Show a column with the sum of periods"), "Show a column with the sum of periods"),
OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "", OPT_CALLBACK_NOOPT('b', "branch-stack", &sort__branch_mode, "",
"use branch records for histogram filling", parse_branch_mode), "use branch records for histogram filling", parse_branch_mode),
OPT_STRING(0, "objdump", &objdump_path, "path",
"objdump binary to use for disassembly and annotations"),
OPT_END() OPT_END()
}; };
......
...@@ -1153,18 +1153,23 @@ static const struct option options[] = { ...@@ -1153,18 +1153,23 @@ static const struct option options[] = {
OPT_END() OPT_END()
}; };
static bool have_cmd(int argc, const char **argv) static int have_cmd(int argc, const char **argv)
{ {
char **__argv = malloc(sizeof(const char *) * argc); char **__argv = malloc(sizeof(const char *) * argc);
if (!__argv) if (!__argv) {
die("malloc"); pr_err("malloc failed\n");
return -1;
}
memcpy(__argv, argv, sizeof(const char *) * argc); memcpy(__argv, argv, sizeof(const char *) * argc);
argc = parse_options(argc, (const char **)__argv, record_options, argc = parse_options(argc, (const char **)__argv, record_options,
NULL, PARSE_OPT_STOP_AT_NON_OPTION); NULL, PARSE_OPT_STOP_AT_NON_OPTION);
free(__argv); free(__argv);
return argc != 0; system_wide = (argc == 0);
return 0;
} }
int cmd_script(int argc, const char **argv, const char *prefix __used) int cmd_script(int argc, const char **argv, const char *prefix __used)
...@@ -1231,13 +1236,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) ...@@ -1231,13 +1236,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
if (pipe(live_pipe) < 0) { if (pipe(live_pipe) < 0) {
perror("failed to create pipe"); perror("failed to create pipe");
exit(-1); return -1;
} }
pid = fork(); pid = fork();
if (pid < 0) { if (pid < 0) {
perror("failed to fork"); perror("failed to fork");
exit(-1); return -1;
} }
if (!pid) { if (!pid) {
...@@ -1249,13 +1254,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) ...@@ -1249,13 +1254,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
if (is_top_script(argv[0])) { if (is_top_script(argv[0])) {
system_wide = true; system_wide = true;
} else if (!system_wide) { } else if (!system_wide) {
system_wide = !have_cmd(argc - rep_args, if (have_cmd(argc - rep_args, &argv[rep_args]) != 0) {
&argv[rep_args]); err = -1;
goto out;
}
} }
__argv = malloc((argc + 6) * sizeof(const char *)); __argv = malloc((argc + 6) * sizeof(const char *));
if (!__argv) if (!__argv) {
die("malloc"); pr_err("malloc failed\n");
err = -ENOMEM;
goto out;
}
__argv[j++] = "/bin/sh"; __argv[j++] = "/bin/sh";
__argv[j++] = rec_script_path; __argv[j++] = rec_script_path;
...@@ -1277,8 +1287,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) ...@@ -1277,8 +1287,12 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
close(live_pipe[1]); close(live_pipe[1]);
__argv = malloc((argc + 4) * sizeof(const char *)); __argv = malloc((argc + 4) * sizeof(const char *));
if (!__argv) if (!__argv) {
die("malloc"); pr_err("malloc failed\n");
err = -ENOMEM;
goto out;
}
j = 0; j = 0;
__argv[j++] = "/bin/sh"; __argv[j++] = "/bin/sh";
__argv[j++] = rep_script_path; __argv[j++] = rep_script_path;
...@@ -1303,12 +1317,20 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) ...@@ -1303,12 +1317,20 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
if (!rec_script_path) if (!rec_script_path)
system_wide = false; system_wide = false;
else if (!system_wide) else if (!system_wide) {
system_wide = !have_cmd(argc - 1, &argv[1]); if (have_cmd(argc - 1, &argv[1]) != 0) {
err = -1;
goto out;
}
}
__argv = malloc((argc + 2) * sizeof(const char *)); __argv = malloc((argc + 2) * sizeof(const char *));
if (!__argv) if (!__argv) {
die("malloc"); pr_err("malloc failed\n");
err = -ENOMEM;
goto out;
}
__argv[j++] = "/bin/sh"; __argv[j++] = "/bin/sh";
__argv[j++] = script_path; __argv[j++] = script_path;
if (system_wide) if (system_wide)
...@@ -1357,18 +1379,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __used) ...@@ -1357,18 +1379,18 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
input = open(session->filename, O_RDONLY); /* input_name */ input = open(session->filename, O_RDONLY); /* input_name */
if (input < 0) { if (input < 0) {
perror("failed to open file"); perror("failed to open file");
exit(-1); return -1;
} }
err = fstat(input, &perf_stat); err = fstat(input, &perf_stat);
if (err < 0) { if (err < 0) {
perror("failed to stat file"); perror("failed to stat file");
exit(-1); return -1;
} }
if (!perf_stat.st_size) { if (!perf_stat.st_size) {
fprintf(stderr, "zero-sized file, nothing to do!\n"); fprintf(stderr, "zero-sized file, nothing to do!\n");
exit(0); return 0;
} }
scripting_ops = script_spec__lookup(generate_script_lang); scripting_ops = script_spec__lookup(generate_script_lang);
......
...@@ -428,7 +428,7 @@ static int run_perf_stat(int argc __used, const char **argv) ...@@ -428,7 +428,7 @@ static int run_perf_stat(int argc __used, const char **argv)
if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) { if (forks && (pipe(child_ready_pipe) < 0 || pipe(go_pipe) < 0)) {
perror("failed to create pipes"); perror("failed to create pipes");
exit(1); return -1;
} }
if (forks) { if (forks) {
...@@ -510,7 +510,8 @@ static int run_perf_stat(int argc __used, const char **argv) ...@@ -510,7 +510,8 @@ static int run_perf_stat(int argc __used, const char **argv)
} }
if (child_pid != -1) if (child_pid != -1)
kill(child_pid, SIGTERM); kill(child_pid, SIGTERM);
die("Not all events could be opened.\n");
pr_err("Not all events could be opened.\n");
return -1; return -1;
} }
counter->supported = true; counter->supported = true;
...@@ -1189,7 +1190,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) ...@@ -1189,7 +1190,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used)
output = fopen(output_name, mode); output = fopen(output_name, mode);
if (!output) { if (!output) {
perror("failed to create output file"); perror("failed to create output file");
exit(-1); return -1;
} }
clock_gettime(CLOCK_REALTIME, &tm); clock_gettime(CLOCK_REALTIME, &tm);
fprintf(output, "# started on %s\n", ctime(&tm.tv_sec)); fprintf(output, "# started on %s\n", ctime(&tm.tv_sec));
......
...@@ -1092,6 +1092,116 @@ static int test__perf_pmu(void) ...@@ -1092,6 +1092,116 @@ static int test__perf_pmu(void)
return perf_pmu__test(); return perf_pmu__test();
} }
static int perf_evsel__roundtrip_cache_name_test(void)
{
char name[128];
int type, op, err = 0, ret = 0, i, idx;
struct perf_evsel *evsel;
struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
if (evlist == NULL)
return -ENOMEM;
for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
/* skip invalid cache type */
if (!perf_evsel__is_cache_op_valid(type, op))
continue;
for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
__perf_evsel__hw_cache_type_op_res_name(type, op, i,
name, sizeof(name));
err = parse_events(evlist, name, 0);
if (err)
ret = err;
}
}
}
idx = 0;
evsel = perf_evlist__first(evlist);
for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
/* skip invalid cache type */
if (!perf_evsel__is_cache_op_valid(type, op))
continue;
for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
__perf_evsel__hw_cache_type_op_res_name(type, op, i,
name, sizeof(name));
if (evsel->idx != idx)
continue;
++idx;
if (strcmp(perf_evsel__name(evsel), name)) {
pr_debug("%s != %s\n", perf_evsel__name(evsel), name);
ret = -1;
}
evsel = perf_evsel__next(evsel);
}
}
}
perf_evlist__delete(evlist);
return ret;
}
static int __perf_evsel__name_array_test(const char *names[], int nr_names)
{
int i, err;
struct perf_evsel *evsel;
struct perf_evlist *evlist = perf_evlist__new(NULL, NULL);
if (evlist == NULL)
return -ENOMEM;
for (i = 0; i < nr_names; ++i) {
err = parse_events(evlist, names[i], 0);
if (err) {
pr_debug("failed to parse event '%s', err %d\n",
names[i], err);
goto out_delete_evlist;
}
}
err = 0;
list_for_each_entry(evsel, &evlist->entries, node) {
if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) {
--err;
pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]);
}
}
out_delete_evlist:
perf_evlist__delete(evlist);
return err;
}
#define perf_evsel__name_array_test(names) \
__perf_evsel__name_array_test(names, ARRAY_SIZE(names))
static int perf_evsel__roundtrip_name_test(void)
{
int err = 0, ret = 0;
err = perf_evsel__name_array_test(perf_evsel__hw_names);
if (err)
ret = err;
err = perf_evsel__name_array_test(perf_evsel__sw_names);
if (err)
ret = err;
err = perf_evsel__roundtrip_cache_name_test();
if (err)
ret = err;
return ret;
}
static struct test { static struct test {
const char *desc; const char *desc;
int (*func)(void); int (*func)(void);
...@@ -1134,6 +1244,10 @@ static struct test { ...@@ -1134,6 +1244,10 @@ static struct test {
.desc = "Test dso data interface", .desc = "Test dso data interface",
.func = dso__test_data, .func = dso__test_data,
}, },
{
.desc = "roundtrip evsel->name check",
.func = perf_evsel__roundtrip_name_test,
},
{ {
.func = NULL, .func = NULL,
}, },
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <pthread.h> #include <pthread.h>
const char *disassembler_style; const char *disassembler_style;
const char *objdump_path;
static struct ins *ins__find(const char *name); static struct ins *ins__find(const char *name);
static int disasm_line__parse(char *line, char **namep, char **rawp); static int disasm_line__parse(char *line, char **namep, char **rawp);
...@@ -820,9 +821,10 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) ...@@ -820,9 +821,10 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
dso, dso->long_name, sym, sym->name); dso, dso->long_name, sym, sym->name);
snprintf(command, sizeof(command), snprintf(command, sizeof(command),
"objdump %s%s --start-address=0x%016" PRIx64 "%s %s%s --start-address=0x%016" PRIx64
" --stop-address=0x%016" PRIx64 " --stop-address=0x%016" PRIx64
" -d %s %s -C %s|grep -v %s|expand", " -d %s %s -C %s|grep -v %s|expand",
objdump_path ? objdump_path : "objdump",
disassembler_style ? "-M " : "", disassembler_style ? "-M " : "",
disassembler_style ? disassembler_style : "", disassembler_style ? disassembler_style : "",
map__rip_2objdump(map, sym->start), map__rip_2objdump(map, sym->start),
......
...@@ -152,5 +152,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx, ...@@ -152,5 +152,6 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
#endif #endif
extern const char *disassembler_style; extern const char *disassembler_style;
extern const char *objdump_path;
#endif /* __PERF_ANNOTATE_H */ #endif /* __PERF_ANNOTATE_H */
...@@ -120,7 +120,9 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, ...@@ -120,7 +120,9 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
if (!full) { if (!full) {
event->comm.tid = pid; event->comm.tid = pid;
process(tool, event, &synth_sample, machine); if (process(tool, event, &synth_sample, machine) != 0)
return -1;
goto out; goto out;
} }
...@@ -151,7 +153,10 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool, ...@@ -151,7 +153,10 @@ static pid_t perf_event__synthesize_comm(struct perf_tool *tool,
event->comm.tid = pid; event->comm.tid = pid;
process(tool, event, &synth_sample, machine); if (process(tool, event, &synth_sample, machine) != 0) {
tgid = -1;
break;
}
} }
closedir(tasks); closedir(tasks);
...@@ -167,6 +172,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, ...@@ -167,6 +172,7 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
{ {
char filename[PATH_MAX]; char filename[PATH_MAX];
FILE *fp; FILE *fp;
int rc = 0;
snprintf(filename, sizeof(filename), "/proc/%d/maps", pid); snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
...@@ -231,18 +237,22 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool, ...@@ -231,18 +237,22 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
event->mmap.pid = tgid; event->mmap.pid = tgid;
event->mmap.tid = pid; event->mmap.tid = pid;
process(tool, event, &synth_sample, machine); if (process(tool, event, &synth_sample, machine) != 0) {
rc = -1;
break;
}
} }
} }
fclose(fp); fclose(fp);
return 0; return rc;
} }
int perf_event__synthesize_modules(struct perf_tool *tool, int perf_event__synthesize_modules(struct perf_tool *tool,
perf_event__handler_t process, perf_event__handler_t process,
struct machine *machine) struct machine *machine)
{ {
int rc = 0;
struct rb_node *nd; struct rb_node *nd;
struct map_groups *kmaps = &machine->kmaps; struct map_groups *kmaps = &machine->kmaps;
union perf_event *event = zalloc((sizeof(event->mmap) + union perf_event *event = zalloc((sizeof(event->mmap) +
...@@ -284,11 +294,14 @@ int perf_event__synthesize_modules(struct perf_tool *tool, ...@@ -284,11 +294,14 @@ int perf_event__synthesize_modules(struct perf_tool *tool,
memcpy(event->mmap.filename, pos->dso->long_name, memcpy(event->mmap.filename, pos->dso->long_name,
pos->dso->long_name_len + 1); pos->dso->long_name_len + 1);
process(tool, event, &synth_sample, machine); if (process(tool, event, &synth_sample, machine) != 0) {
rc = -1;
break;
}
} }
free(event); free(event);
return 0; return rc;
} }
static int __event__synthesize_thread(union perf_event *comm_event, static int __event__synthesize_thread(union perf_event *comm_event,
...@@ -392,12 +405,16 @@ int perf_event__synthesize_threads(struct perf_tool *tool, ...@@ -392,12 +405,16 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
if (*end) /* only interested in proper numerical dirents */ if (*end) /* only interested in proper numerical dirents */
continue; continue;
__event__synthesize_thread(comm_event, mmap_event, pid, 1, if (__event__synthesize_thread(comm_event, mmap_event, pid, 1,
process, tool, machine); process, tool, machine) != 0) {
err = -1;
goto out_closedir;
}
} }
closedir(proc);
err = 0; err = 0;
out_closedir:
closedir(proc);
out_free_mmap: out_free_mmap:
free(mmap_event); free(mmap_event);
out_free_comm: out_free_comm:
......
...@@ -889,3 +889,16 @@ int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *even ...@@ -889,3 +889,16 @@ int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *even
struct perf_evsel *evsel = perf_evlist__first(evlist); struct perf_evsel *evsel = perf_evlist__first(evlist);
return perf_evsel__parse_sample(evsel, event, sample, swapped); return perf_evsel__parse_sample(evsel, event, sample, swapped);
} }
size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
{
struct perf_evsel *evsel;
size_t printed = 0;
list_for_each_entry(evsel, &evlist->entries, node) {
printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
perf_evsel__name(evsel));
}
return printed + fprintf(fp, "\n");;
}
...@@ -143,4 +143,6 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist) ...@@ -143,4 +143,6 @@ static inline struct perf_evsel *perf_evlist__last(struct perf_evlist *evlist)
{ {
return list_entry(evlist->entries.prev, struct perf_evsel, node); return list_entry(evlist->entries.prev, struct perf_evsel, node);
} }
size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
#endif /* __PERF_EVLIST_H */ #endif /* __PERF_EVLIST_H */
...@@ -68,7 +68,7 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx) ...@@ -68,7 +68,7 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
return evsel; return evsel;
} }
static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = { const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
"cycles", "cycles",
"instructions", "instructions",
"cache-references", "cache-references",
...@@ -131,12 +131,12 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size) ...@@ -131,12 +131,12 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
return r + perf_evsel__add_modifiers(evsel, bf + r, size - r); return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
} }
static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = { const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
"cpu-clock", "cpu-clock",
"task-clock", "task-clock",
"page-faults", "page-faults",
"context-switches", "context-switches",
"CPU-migrations", "cpu-migrations",
"minor-faults", "minor-faults",
"major-faults", "major-faults",
"alignment-faults", "alignment-faults",
......
...@@ -97,8 +97,10 @@ extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX] ...@@ -97,8 +97,10 @@ extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
[PERF_EVSEL__MAX_ALIASES]; [PERF_EVSEL__MAX_ALIASES];
extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX] extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
[PERF_EVSEL__MAX_ALIASES]; [PERF_EVSEL__MAX_ALIASES];
const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX] extern const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
[PERF_EVSEL__MAX_ALIASES]; [PERF_EVSEL__MAX_ALIASES];
extern const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX];
extern const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX];
int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result, int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
char *bf, size_t size); char *bf, size_t size);
const char *perf_evsel__name(struct perf_evsel *evsel); const char *perf_evsel__name(struct perf_evsel *evsel);
......
...@@ -610,11 +610,10 @@ static int write_event_desc(int fd, struct perf_header *h __used, ...@@ -610,11 +610,10 @@ static int write_event_desc(int fd, struct perf_header *h __used,
struct perf_evlist *evlist) struct perf_evlist *evlist)
{ {
struct perf_evsel *evsel; struct perf_evsel *evsel;
u32 nre = 0, nri, sz; u32 nre, nri, sz;
int ret; int ret;
list_for_each_entry(evsel, &evlist->entries, node) nre = evlist->nr_entries;
nre++;
/* /*
* write number of events * write number of events
...@@ -1441,6 +1440,9 @@ static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp) ...@@ -1441,6 +1440,9 @@ static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp)
if (ret != sizeof(pmu_num)) if (ret != sizeof(pmu_num))
goto error; goto error;
if (ph->needs_swap)
pmu_num = bswap_32(pmu_num);
if (!pmu_num) { if (!pmu_num) {
fprintf(fp, "# pmu mappings: not available\n"); fprintf(fp, "# pmu mappings: not available\n");
return; return;
...@@ -1449,6 +1451,9 @@ static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp) ...@@ -1449,6 +1451,9 @@ static void print_pmu_mappings(struct perf_header *ph, int fd, FILE *fp)
while (pmu_num) { while (pmu_num) {
if (read(fd, &type, sizeof(type)) != sizeof(type)) if (read(fd, &type, sizeof(type)) != sizeof(type))
break; break;
if (ph->needs_swap)
type = bswap_32(type);
name = do_read_string(fd, ph); name = do_read_string(fd, ph);
if (!name) if (!name)
break; break;
...@@ -2290,33 +2295,39 @@ static int read_attr(int fd, struct perf_header *ph, ...@@ -2290,33 +2295,39 @@ static int read_attr(int fd, struct perf_header *ph,
return ret <= 0 ? -1 : 0; return ret <= 0 ? -1 : 0;
} }
static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel, static int perf_evsel__prepare_tracepoint_event(struct perf_evsel *evsel,
struct pevent *pevent) struct pevent *pevent)
{ {
struct event_format *event = pevent_find_event(pevent, struct event_format *event;
evsel->attr.config);
char bf[128]; char bf[128];
/* already prepared */
if (evsel->tp_format)
return 0;
event = pevent_find_event(pevent, evsel->attr.config);
if (event == NULL) if (event == NULL)
return -1; return -1;
if (!evsel->name) {
snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name); snprintf(bf, sizeof(bf), "%s:%s", event->system, event->name);
evsel->name = strdup(bf); evsel->name = strdup(bf);
if (event->name == NULL) if (evsel->name == NULL)
return -1; return -1;
}
evsel->tp_format = event; evsel->tp_format = event;
return 0; return 0;
} }
static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist, static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
struct pevent *pevent) struct pevent *pevent)
{ {
struct perf_evsel *pos; struct perf_evsel *pos;
list_for_each_entry(pos, &evlist->entries, node) { list_for_each_entry(pos, &evlist->entries, node) {
if (pos->attr.type == PERF_TYPE_TRACEPOINT && if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
perf_evsel__set_tracepoint_name(pos, pevent)) perf_evsel__prepare_tracepoint_event(pos, pevent))
return -1; return -1;
} }
...@@ -2404,7 +2415,8 @@ int perf_session__read_header(struct perf_session *session, int fd) ...@@ -2404,7 +2415,8 @@ int perf_session__read_header(struct perf_session *session, int fd)
lseek(fd, header->data_offset, SEEK_SET); lseek(fd, header->data_offset, SEEK_SET);
if (perf_evlist__set_tracepoint_names(session->evlist, session->pevent)) if (perf_evlist__prepare_tracepoint_events(session->evlist,
session->pevent))
goto out_delete_evlist; goto out_delete_evlist;
header->frozen = 1; header->frozen = 1;
...@@ -2638,7 +2650,8 @@ int perf_event__process_tracing_data(union perf_event *event, ...@@ -2638,7 +2650,8 @@ int perf_event__process_tracing_data(union perf_event *event,
if (size_read + padding != size) if (size_read + padding != size)
die("tracing data size mismatch"); die("tracing data size mismatch");
perf_evlist__set_tracepoint_names(session->evlist, session->pevent); perf_evlist__prepare_tracepoint_events(session->evlist,
session->pevent);
return size_read + padding; return size_read + padding;
} }
......
...@@ -52,9 +52,9 @@ int intlist__add(struct intlist *ilist, int i) ...@@ -52,9 +52,9 @@ int intlist__add(struct intlist *ilist, int i)
return rblist__add_node(&ilist->rblist, (void *)((long)i)); return rblist__add_node(&ilist->rblist, (void *)((long)i));
} }
void intlist__remove(struct intlist *ilist __used, struct int_node *node) void intlist__remove(struct intlist *ilist, struct int_node *node)
{ {
int_node__delete(node); rblist__remove_node(&ilist->rblist, &node->rb_node);
} }
struct int_node *intlist__find(struct intlist *ilist, int i) struct int_node *intlist__find(struct intlist *ilist, int i)
......
...@@ -308,7 +308,7 @@ int parse_events_add_cache(struct list_head **list, int *idx, ...@@ -308,7 +308,7 @@ int parse_events_add_cache(struct list_head **list, int *idx,
for (i = 0; (i < 2) && (op_result[i]); i++) { for (i = 0; (i < 2) && (op_result[i]); i++) {
char *str = op_result[i]; char *str = op_result[i];
snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str); n += snprintf(name + n, MAX_NAME_LEN - n, "-%s", str);
if (cache_op == -1) { if (cache_op == -1) {
cache_op = parse_aliases(str, perf_evsel__hw_cache_op, cache_op = parse_aliases(str, perf_evsel__hw_cache_op,
......
...@@ -25,16 +25,16 @@ ...@@ -25,16 +25,16 @@
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include "../../perf.h"
#include "../util.h" #include "../util.h"
#include <EXTERN.h>
#include <perl.h>
#include "../../perf.h"
#include "../thread.h" #include "../thread.h"
#include "../event.h" #include "../event.h"
#include "../trace-event.h" #include "../trace-event.h"
#include "../evsel.h" #include "../evsel.h"
#include <EXTERN.h>
#include <perl.h>
void boot_Perf__Trace__Context(pTHX_ CV *cv); void boot_Perf__Trace__Context(pTHX_ CV *cv);
void boot_DynaLoader(pTHX_ CV *cv); void boot_DynaLoader(pTHX_ CV *cv);
typedef PerlInterpreter * INTERP; typedef PerlInterpreter * INTERP;
......
...@@ -692,7 +692,7 @@ static int perf_session_deliver_event(struct perf_session *session, ...@@ -692,7 +692,7 @@ static int perf_session_deliver_event(struct perf_session *session,
struct perf_tool *tool, struct perf_tool *tool,
u64 file_offset); u64 file_offset);
static void flush_sample_queue(struct perf_session *s, static int flush_sample_queue(struct perf_session *s,
struct perf_tool *tool) struct perf_tool *tool)
{ {
struct ordered_samples *os = &s->ordered_samples; struct ordered_samples *os = &s->ordered_samples;
...@@ -705,7 +705,7 @@ static void flush_sample_queue(struct perf_session *s, ...@@ -705,7 +705,7 @@ static void flush_sample_queue(struct perf_session *s,
int ret; int ret;
if (!tool->ordered_samples || !limit) if (!tool->ordered_samples || !limit)
return; return 0;
list_for_each_entry_safe(iter, tmp, head, list) { list_for_each_entry_safe(iter, tmp, head, list) {
if (iter->timestamp > limit) if (iter->timestamp > limit)
...@@ -715,9 +715,12 @@ static void flush_sample_queue(struct perf_session *s, ...@@ -715,9 +715,12 @@ static void flush_sample_queue(struct perf_session *s,
s->header.needs_swap); 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 {
perf_session_deliver_event(s, iter->event, &sample, tool, ret = perf_session_deliver_event(s, iter->event, &sample, tool,
iter->file_offset); iter->file_offset);
if (ret)
return ret;
}
os->last_flush = iter->timestamp; os->last_flush = iter->timestamp;
list_del(&iter->list); list_del(&iter->list);
...@@ -737,6 +740,8 @@ static void flush_sample_queue(struct perf_session *s, ...@@ -737,6 +740,8 @@ static void flush_sample_queue(struct perf_session *s,
} }
os->nr_samples = 0; os->nr_samples = 0;
return 0;
} }
/* /*
...@@ -782,10 +787,11 @@ static int process_finished_round(struct perf_tool *tool, ...@@ -782,10 +787,11 @@ static int process_finished_round(struct perf_tool *tool,
union perf_event *event __used, union perf_event *event __used,
struct perf_session *session) struct perf_session *session)
{ {
flush_sample_queue(session, tool); int ret = flush_sample_queue(session, tool);
if (!ret)
session->ordered_samples.next_flush = session->ordered_samples.max_timestamp; session->ordered_samples.next_flush = session->ordered_samples.max_timestamp;
return 0; return ret;
} }
/* The queue is ordered by time */ /* The queue is ordered by time */
...@@ -1443,7 +1449,7 @@ int __perf_session__process_events(struct perf_session *session, ...@@ -1443,7 +1449,7 @@ int __perf_session__process_events(struct perf_session *session,
err = 0; err = 0;
/* do the final flush for ordered samples */ /* do the final flush for ordered samples */
session->ordered_samples.next_flush = ULLONG_MAX; session->ordered_samples.next_flush = ULLONG_MAX;
flush_sample_queue(session, tool); err = flush_sample_queue(session, tool);
out_err: out_err:
perf_session__warn_about_errors(session, tool); perf_session__warn_about_errors(session, tool);
perf_session_free_sample_buffers(session); perf_session_free_sample_buffers(session);
......
...@@ -93,7 +93,7 @@ int strlist__load(struct strlist *self, const char *filename) ...@@ -93,7 +93,7 @@ int strlist__load(struct strlist *self, const char *filename)
void strlist__remove(struct strlist *slist, struct str_node *snode) void strlist__remove(struct strlist *slist, struct str_node *snode)
{ {
str_node__delete(snode, slist->dupstr); rblist__remove_node(&slist->rblist, &snode->rb_node);
} }
struct str_node *strlist__find(struct strlist *slist, const char *entry) struct str_node *strlist__find(struct strlist *slist, const char *entry)
......
...@@ -117,8 +117,8 @@ int perf_target__strerror(struct perf_target *target, int errnum, ...@@ -117,8 +117,8 @@ int perf_target__strerror(struct perf_target *target, int errnum,
if (err != buf) { if (err != buf) {
size_t len = strlen(err); size_t len = strlen(err);
char *c = mempcpy(buf, err, min(buflen - 1, len)); memcpy(buf, err, min(buflen - 1, len));
*c = '\0'; *(buf + min(buflen - 1, len)) = '\0';
} }
return 0; return 0;
......
...@@ -69,11 +69,6 @@ ...@@ -69,11 +69,6 @@
#include <sys/poll.h> #include <sys/poll.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <inttypes.h> #include <inttypes.h>
#include "../../../include/linux/magic.h" #include "../../../include/linux/magic.h"
#include "types.h" #include "types.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment