summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2012-09-08 13:26:02 +0200
committerIngo Molnar <mingo@kernel.org>2012-09-08 13:26:02 +0200
commitef34eb4da3eb62a1511592adf7c76d74faca0b14 (patch)
tree7f28887cf8c5d7059416769e152e79f68ce32830
parent479d875835a49e849683743ec50c30b6a429696b (diff)
parentb155a09015135cf59ada8d48109ccbd9891c1b42 (diff)
downloadop-kernel-dev-ef34eb4da3eb62a1511592adf7c76d74faca0b14.zip
op-kernel-dev-ef34eb4da3eb62a1511592adf7c76d74faca0b14.tar.gz
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: * Fix build for another rbtree.c change, from Adrian Hunter. * Fixes for perf to build on Android, from Irina Tirdea. * Make 'perf diff' command work with evsel hists, from Jiri Olsa. * Use the only field_sep var that is set up: symbol_conf.field_sep, fix from Jiri Olsa. * .gitignore compiled python binaries, from Namhyung Kim. * Get rid of die() in more libtraceevent places, from Namhyung Kim. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--tools/lib/traceevent/event-parse.c86
-rw-r--r--tools/lib/traceevent/event-parse.h3
-rw-r--r--tools/perf/.gitignore2
-rw-r--r--tools/perf/Documentation/perf-diff.txt3
-rw-r--r--tools/perf/Makefile8
-rw-r--r--tools/perf/builtin-diff.c93
-rw-r--r--tools/perf/config/feature-tests.mak14
-rw-r--r--tools/perf/perf.c1
-rw-r--r--tools/perf/util/annotate.h1
-rw-r--r--tools/perf/util/dso-test-data.c2
-rw-r--r--tools/perf/util/evsel.h7
-rw-r--r--tools/perf/util/help.c1
-rw-r--r--tools/perf/util/include/linux/rbtree.h1
-rw-r--r--tools/perf/util/session.h4
-rw-r--r--tools/perf/util/sort.c6
-rw-r--r--tools/perf/util/sort.h1
-rw-r--r--tools/perf/util/symbol.h3
-rw-r--r--tools/perf/util/top.h1
-rw-r--r--tools/perf/util/util.c6
19 files changed, 180 insertions, 63 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index b5b4d80..f4190b5 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -3889,8 +3889,11 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
goto cont_process;
case '*':
/* The argument is the length. */
- if (!arg)
- die("no argument match");
+ if (!arg) {
+ do_warning("no argument match");
+ event->flags |= EVENT_FL_FAILED;
+ goto out_failed;
+ }
len_arg = eval_num_arg(data, size, event, arg);
len_as_arg = 1;
arg = arg->next;
@@ -3923,15 +3926,21 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
case 'x':
case 'X':
case 'u':
- if (!arg)
- die("no argument match");
+ if (!arg) {
+ do_warning("no argument match");
+ event->flags |= EVENT_FL_FAILED;
+ goto out_failed;
+ }
len = ((unsigned long)ptr + 1) -
(unsigned long)saveptr;
/* should never happen */
- if (len > 31)
- die("bad format!");
+ if (len > 31) {
+ do_warning("bad format!");
+ event->flags |= EVENT_FL_FAILED;
+ len = 31;
+ }
memcpy(format, saveptr, len);
format[len] = 0;
@@ -3995,19 +4004,26 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
trace_seq_printf(s, format, (long long)val);
break;
default:
- die("bad count (%d)", ls);
+ do_warning("bad count (%d)", ls);
+ event->flags |= EVENT_FL_FAILED;
}
break;
case 's':
- if (!arg)
- die("no matching argument");
+ if (!arg) {
+ do_warning("no matching argument");
+ event->flags |= EVENT_FL_FAILED;
+ goto out_failed;
+ }
len = ((unsigned long)ptr + 1) -
(unsigned long)saveptr;
/* should never happen */
- if (len > 31)
- die("bad format!");
+ if (len > 31) {
+ do_warning("bad format!");
+ event->flags |= EVENT_FL_FAILED;
+ len = 31;
+ }
memcpy(format, saveptr, len);
format[len] = 0;
@@ -4025,6 +4041,11 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
trace_seq_putc(s, *ptr);
}
+ if (event->flags & EVENT_FL_FAILED) {
+out_failed:
+ trace_seq_printf(s, "[FAILED TO PARSE]");
+ }
+
if (args) {
free_args(args);
free(bprint_fmt);
@@ -4812,8 +4833,8 @@ int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
msg = strerror_r(errnum, buf, buflen);
if (msg != buf) {
size_t len = strlen(msg);
- char *c = mempcpy(buf, msg, min(buflen-1, len));
- *c = '\0';
+ memcpy(buf, msg, min(buflen - 1, len));
+ *(buf + min(buflen - 1, len)) = '\0';
}
return 0;
}
@@ -5059,6 +5080,7 @@ int pevent_register_print_function(struct pevent *pevent,
struct pevent_func_params *param;
enum pevent_func_arg_type type;
va_list ap;
+ int ret;
func_handle = find_func_handler(pevent, name);
if (func_handle) {
@@ -5071,14 +5093,21 @@ int pevent_register_print_function(struct pevent *pevent,
remove_func_handler(pevent, name);
}
- func_handle = malloc_or_die(sizeof(*func_handle));
+ func_handle = malloc(sizeof(*func_handle));
+ if (!func_handle) {
+ do_warning("Failed to allocate function handler");
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ }
memset(func_handle, 0, sizeof(*func_handle));
func_handle->ret_type = ret_type;
func_handle->name = strdup(name);
func_handle->func = func;
- if (!func_handle->name)
- die("Failed to allocate function name");
+ if (!func_handle->name) {
+ do_warning("Failed to allocate function name");
+ free(func_handle);
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ }
next_param = &(func_handle->params);
va_start(ap, name);
@@ -5088,11 +5117,17 @@ int pevent_register_print_function(struct pevent *pevent,
break;
if (type < 0 || type >= PEVENT_FUNC_ARG_MAX_TYPES) {
- warning("Invalid argument type %d", type);
+ do_warning("Invalid argument type %d", type);
+ ret = PEVENT_ERRNO__INVALID_ARG_TYPE;
goto out_free;
}
- param = malloc_or_die(sizeof(*param));
+ param = malloc(sizeof(*param));
+ if (!param) {
+ do_warning("Failed to allocate function param");
+ ret = PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ goto out_free;
+ }
param->type = type;
param->next = NULL;
@@ -5110,7 +5145,7 @@ int pevent_register_print_function(struct pevent *pevent,
out_free:
va_end(ap);
free_func_handle(func_handle);
- return -1;
+ return ret;
}
/**
@@ -5162,7 +5197,12 @@ int pevent_register_event_handler(struct pevent *pevent,
not_found:
/* Save for later use. */
- handle = malloc_or_die(sizeof(*handle));
+ handle = malloc(sizeof(*handle));
+ if (!handle) {
+ do_warning("Failed to allocate event handler");
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
+ }
+
memset(handle, 0, sizeof(*handle));
handle->id = id;
if (event_name)
@@ -5172,7 +5212,11 @@ int pevent_register_event_handler(struct pevent *pevent,
if ((event_name && !handle->event_name) ||
(sys_name && !handle->sys_name)) {
- die("Failed to allocate event/sys name");
+ do_warning("Failed to allocate event/sys name");
+ free((void *)handle->event_name);
+ free((void *)handle->sys_name);
+ free(handle);
+ return PEVENT_ERRNO__MEM_ALLOC_FAILED;
}
handle->func = func;
diff --git a/tools/lib/traceevent/event-parse.h b/tools/lib/traceevent/event-parse.h
index 863a0bb..3318963 100644
--- a/tools/lib/traceevent/event-parse.h
+++ b/tools/lib/traceevent/event-parse.h
@@ -351,7 +351,8 @@ enum pevent_flag {
_PE(READ_ID_FAILED, "failed to read event id"), \
_PE(READ_FORMAT_FAILED, "failed to read event format"), \
_PE(READ_PRINT_FAILED, "failed to read event print fmt"), \
- _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace")
+ _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\
+ _PE(INVALID_ARG_TYPE, "invalid argument type")
#undef _PE
#define _PE(__code, __str) PEVENT_ERRNO__ ## __code
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 26b823b..8f8fbc2 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -21,3 +21,5 @@ config.mak
config.mak.autogen
*-bison.*
*-flex.*
+*.pyc
+*.pyo
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index 74d7481..ab7f667 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -17,6 +17,9 @@ captured via perf record.
If no parameters are passed it will assume perf.data.old and perf.data.
+The differential profile is displayed only for events matching both
+specified perf.data files.
+
OPTIONS
-------
-M::
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index afd5075..3eda492 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -755,6 +755,14 @@ else
endif
endif
+ifdef NO_BACKTRACE
+ BASIC_CFLAGS += -DNO_BACKTRACE
+else
+ ifneq ($(call try-cc,$(SOURCE_BACKTRACE),),y)
+ BASIC_CFLAGS += -DNO_BACKTRACE
+ endif
+endif
+
ifdef ASCIIDOC8
export ASCIIDOC8
endif
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index d29d350..e9933fd 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -10,6 +10,7 @@
#include "util/event.h"
#include "util/hist.h"
#include "util/evsel.h"
+#include "util/evlist.h"
#include "util/session.h"
#include "util/tool.h"
#include "util/sort.h"
@@ -24,11 +25,6 @@ static char diff__default_sort_order[] = "dso,symbol";
static bool force;
static bool show_displacement;
-struct perf_diff {
- struct perf_tool tool;
- struct perf_session *session;
-};
-
static int hists__add_entry(struct hists *self,
struct addr_location *al, u64 period)
{
@@ -37,14 +33,12 @@ static int hists__add_entry(struct hists *self,
return -ENOMEM;
}
-static int diff__process_sample_event(struct perf_tool *tool,
+static int diff__process_sample_event(struct perf_tool *tool __used,
union perf_event *event,
struct perf_sample *sample,
- struct perf_evsel *evsel __used,
+ struct perf_evsel *evsel,
struct machine *machine)
{
- struct perf_diff *_diff = container_of(tool, struct perf_diff, tool);
- struct perf_session *session = _diff->session;
struct addr_location al;
if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) {
@@ -56,26 +50,24 @@ static int diff__process_sample_event(struct perf_tool *tool,
if (al.filtered || al.sym == NULL)
return 0;
- if (hists__add_entry(&session->hists, &al, sample->period)) {
+ if (hists__add_entry(&evsel->hists, &al, sample->period)) {
pr_warning("problem incrementing symbol period, skipping event\n");
return -1;
}
- session->hists.stats.total_period += sample->period;
+ evsel->hists.stats.total_period += sample->period;
return 0;
}
-static struct perf_diff diff = {
- .tool = {
- .sample = diff__process_sample_event,
- .mmap = perf_event__process_mmap,
- .comm = perf_event__process_comm,
- .exit = perf_event__process_task,
- .fork = perf_event__process_task,
- .lost = perf_event__process_lost,
- .ordered_samples = true,
- .ordering_requires_timestamps = true,
- },
+static struct perf_tool tool = {
+ .sample = diff__process_sample_event,
+ .mmap = perf_event__process_mmap,
+ .comm = perf_event__process_comm,
+ .exit = perf_event__process_task,
+ .fork = perf_event__process_task,
+ .lost = perf_event__process_lost,
+ .ordered_samples = true,
+ .ordering_requires_timestamps = true,
};
static void perf_session__insert_hist_entry_by_name(struct rb_root *root,
@@ -146,34 +138,71 @@ static void hists__match(struct hists *older, struct hists *newer)
}
}
+static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
+ struct perf_evlist *evlist)
+{
+ struct perf_evsel *e;
+
+ list_for_each_entry(e, &evlist->entries, node)
+ if (perf_evsel__match2(evsel, e))
+ return e;
+
+ return NULL;
+}
+
static int __cmd_diff(void)
{
int ret, i;
#define older (session[0])
#define newer (session[1])
struct perf_session *session[2];
+ struct perf_evlist *evlist_new, *evlist_old;
+ struct perf_evsel *evsel;
+ bool first = true;
older = perf_session__new(input_old, O_RDONLY, force, false,
- &diff.tool);
+ &tool);
newer = perf_session__new(input_new, O_RDONLY, force, false,
- &diff.tool);
+ &tool);
if (session[0] == NULL || session[1] == NULL)
return -ENOMEM;
for (i = 0; i < 2; ++i) {
- diff.session = session[i];
- ret = perf_session__process_events(session[i], &diff.tool);
+ ret = perf_session__process_events(session[i], &tool);
if (ret)
goto out_delete;
- hists__output_resort(&session[i]->hists);
}
- if (show_displacement)
- hists__resort_entries(&older->hists);
+ evlist_old = older->evlist;
+ evlist_new = newer->evlist;
+
+ list_for_each_entry(evsel, &evlist_new->entries, node)
+ hists__output_resort(&evsel->hists);
+
+ list_for_each_entry(evsel, &evlist_old->entries, node) {
+ hists__output_resort(&evsel->hists);
+
+ if (show_displacement)
+ hists__resort_entries(&evsel->hists);
+ }
+
+ list_for_each_entry(evsel, &evlist_new->entries, node) {
+ struct perf_evsel *evsel_old;
+
+ evsel_old = evsel_match(evsel, evlist_old);
+ if (!evsel_old)
+ continue;
+
+ fprintf(stdout, "%s# Event '%s'\n#\n", first ? "" : "\n",
+ perf_evsel__name(evsel));
+
+ first = false;
+
+ hists__match(&evsel_old->hists, &evsel->hists);
+ hists__fprintf(&evsel->hists, &evsel_old->hists,
+ show_displacement, true, 0, 0, stdout);
+ }
- hists__match(&older->hists, &newer->hists);
- hists__fprintf(&newer->hists, &older->hists,
- show_displacement, true, 0, 0, stdout);
out_delete:
for (i = 0; i < 2; ++i)
perf_session__delete(session[i]);
diff --git a/tools/perf/config/feature-tests.mak b/tools/perf/config/feature-tests.mak
index 2f1156a..116690a 100644
--- a/tools/perf/config/feature-tests.mak
+++ b/tools/perf/config/feature-tests.mak
@@ -179,3 +179,17 @@ int main(void)
}
endef
endif
+
+ifndef NO_BACKTRACE
+define SOURCE_BACKTRACE
+#include <execinfo.h>
+#include <stdio.h>
+
+int main(void)
+{
+ backtrace(NULL, 0);
+ backtrace_symbols(NULL, 0);
+ return 0;
+}
+endef
+endif
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index e7840e5..fb8578c 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -14,6 +14,7 @@
#include "util/run-command.h"
#include "util/parse-events.h"
#include "util/debugfs.h"
+#include <pthread.h>
const char perf_usage_string[] =
"perf [--version] [--help] COMMAND [ARGS]";
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index a6d6bc5..62a6e7a 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -7,6 +7,7 @@
#include "symbol.h"
#include <linux/list.h>
#include <linux/rbtree.h>
+#include <pthread.h>
struct ins;
diff --git a/tools/perf/util/dso-test-data.c b/tools/perf/util/dso-test-data.c
index 541cdc7..c6caede 100644
--- a/tools/perf/util/dso-test-data.c
+++ b/tools/perf/util/dso-test-data.c
@@ -23,7 +23,7 @@ static char *test_file(int size)
int fd, i;
unsigned char *buf;
- fd = mkostemp(templ, O_CREAT|O_WRONLY|O_TRUNC);
+ fd = mkstemp(templ);
buf = malloc(size);
if (!buf) {
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index a3f562c..390690e 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -124,6 +124,13 @@ void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads);
(evsel->attr.type == PERF_TYPE_##t && \
evsel->attr.config == PERF_COUNT_##c)
+static inline bool perf_evsel__match2(struct perf_evsel *e1,
+ struct perf_evsel *e2)
+{
+ return (e1->attr.type == e2->attr.type) &&
+ (e1->attr.config == e2->attr.config);
+}
+
int __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
int cpu, int thread, bool scale);
diff --git a/tools/perf/util/help.c b/tools/perf/util/help.c
index 6f2975a..4fa764d 100644
--- a/tools/perf/util/help.c
+++ b/tools/perf/util/help.c
@@ -3,6 +3,7 @@
#include "exec_cmd.h"
#include "levenshtein.h"
#include "help.h"
+#include <termios.h>
void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
{
diff --git a/tools/perf/util/include/linux/rbtree.h b/tools/perf/util/include/linux/rbtree.h
index 7a243a1..2a030c5 100644
--- a/tools/perf/util/include/linux/rbtree.h
+++ b/tools/perf/util/include/linux/rbtree.h
@@ -1 +1,2 @@
+#include <stdbool.h>
#include "../../../../include/linux/rbtree.h"
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 176a609..aab414f 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -36,9 +36,7 @@ struct perf_session {
struct pevent *pevent;
/*
* FIXME: Need to split this up further, we need global
- * stats + per event stats. 'perf diff' also needs
- * to properly support multiple events in a single
- * perf.data file.
+ * stats + per event stats.
*/
struct hists hists;
int fd;
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 0f5a0a4..7a2fbd8 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -12,8 +12,6 @@ int sort__branch_mode = -1; /* -1 = means not set */
enum sort_type sort__first_dimension;
-char * field_sep;
-
LIST_HEAD(hist_entry__sort_list);
static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
@@ -23,11 +21,11 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
va_start(ap, fmt);
n = vsnprintf(bf, size, fmt, ap);
- if (field_sep && n > 0) {
+ if (symbol_conf.field_sep && n > 0) {
char *sep = bf;
while (1) {
- sep = strchr(sep, *field_sep);
+ sep = strchr(sep, *symbol_conf.field_sep);
if (sep == NULL)
break;
*sep = '.';
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index e724b26..e459c98 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -32,7 +32,6 @@ extern const char default_sort_order[];
extern int sort__need_collapse;
extern int sort__has_parent;
extern int sort__branch_mode;
-extern char *field_sep;
extern struct sort_entry sort_comm;
extern struct sort_entry sort_dso;
extern struct sort_entry sort_sym;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index fc4b1e6..d3b330c 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -10,6 +10,9 @@
#include <linux/rbtree.h>
#include <stdio.h>
#include <byteswap.h>
+#if defined(__BIONIC__)
+#include <libgen.h>
+#endif
#ifndef NO_LIBELF_SUPPORT
#include <libelf.h>
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index 33347ca..86ff1b1 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -5,6 +5,7 @@
#include "types.h"
#include <stddef.h>
#include <stdbool.h>
+#include <termios.h>
struct perf_evlist;
struct perf_evsel;
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index 1b8775c..2055cf3 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -1,7 +1,9 @@
#include "../perf.h"
#include "util.h"
#include <sys/mman.h>
+#ifndef NO_BACKTRACE
#include <execinfo.h>
+#endif
#include <stdio.h>
#include <stdlib.h>
@@ -163,6 +165,7 @@ size_t hex_width(u64 v)
}
/* Obtain a backtrace and print it to stdout. */
+#ifndef NO_BACKTRACE
void dump_stack(void)
{
void *array[16];
@@ -177,3 +180,6 @@ void dump_stack(void)
free(strings);
}
+#else
+void dump_stack(void) {}
+#endif
OpenPOWER on IntegriCloud