Commit ef34eb4d 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:

 * 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: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 479d8758 b155a090
...@@ -3889,8 +3889,11 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event ...@@ -3889,8 +3889,11 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
goto cont_process; goto cont_process;
case '*': case '*':
/* The argument is the length. */ /* The argument is the length. */
if (!arg) if (!arg) {
die("no argument match"); do_warning("no argument match");
event->flags |= EVENT_FL_FAILED;
goto out_failed;
}
len_arg = eval_num_arg(data, size, event, arg); len_arg = eval_num_arg(data, size, event, arg);
len_as_arg = 1; len_as_arg = 1;
arg = arg->next; arg = arg->next;
...@@ -3923,15 +3926,21 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event ...@@ -3923,15 +3926,21 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
case 'x': case 'x':
case 'X': case 'X':
case 'u': case 'u':
if (!arg) if (!arg) {
die("no argument match"); do_warning("no argument match");
event->flags |= EVENT_FL_FAILED;
goto out_failed;
}
len = ((unsigned long)ptr + 1) - len = ((unsigned long)ptr + 1) -
(unsigned long)saveptr; (unsigned long)saveptr;
/* should never happen */ /* should never happen */
if (len > 31) if (len > 31) {
die("bad format!"); do_warning("bad format!");
event->flags |= EVENT_FL_FAILED;
len = 31;
}
memcpy(format, saveptr, len); memcpy(format, saveptr, len);
format[len] = 0; format[len] = 0;
...@@ -3995,19 +4004,26 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event ...@@ -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); trace_seq_printf(s, format, (long long)val);
break; break;
default: default:
die("bad count (%d)", ls); do_warning("bad count (%d)", ls);
event->flags |= EVENT_FL_FAILED;
} }
break; break;
case 's': case 's':
if (!arg) if (!arg) {
die("no matching argument"); do_warning("no matching argument");
event->flags |= EVENT_FL_FAILED;
goto out_failed;
}
len = ((unsigned long)ptr + 1) - len = ((unsigned long)ptr + 1) -
(unsigned long)saveptr; (unsigned long)saveptr;
/* should never happen */ /* should never happen */
if (len > 31) if (len > 31) {
die("bad format!"); do_warning("bad format!");
event->flags |= EVENT_FL_FAILED;
len = 31;
}
memcpy(format, saveptr, len); memcpy(format, saveptr, len);
format[len] = 0; format[len] = 0;
...@@ -4025,6 +4041,11 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event ...@@ -4025,6 +4041,11 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
trace_seq_putc(s, *ptr); trace_seq_putc(s, *ptr);
} }
if (event->flags & EVENT_FL_FAILED) {
out_failed:
trace_seq_printf(s, "[FAILED TO PARSE]");
}
if (args) { if (args) {
free_args(args); free_args(args);
free(bprint_fmt); free(bprint_fmt);
...@@ -4812,8 +4833,8 @@ int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum, ...@@ -4812,8 +4833,8 @@ int pevent_strerror(struct pevent *pevent, enum pevent_errno errnum,
msg = strerror_r(errnum, buf, buflen); msg = strerror_r(errnum, buf, buflen);
if (msg != buf) { if (msg != buf) {
size_t len = strlen(msg); size_t len = strlen(msg);
char *c = mempcpy(buf, msg, min(buflen-1, len)); memcpy(buf, msg, min(buflen - 1, len));
*c = '\0'; *(buf + min(buflen - 1, len)) = '\0';
} }
return 0; return 0;
} }
...@@ -5059,6 +5080,7 @@ int pevent_register_print_function(struct pevent *pevent, ...@@ -5059,6 +5080,7 @@ int pevent_register_print_function(struct pevent *pevent,
struct pevent_func_params *param; struct pevent_func_params *param;
enum pevent_func_arg_type type; enum pevent_func_arg_type type;
va_list ap; va_list ap;
int ret;
func_handle = find_func_handler(pevent, name); func_handle = find_func_handler(pevent, name);
if (func_handle) { if (func_handle) {
...@@ -5071,14 +5093,21 @@ int pevent_register_print_function(struct pevent *pevent, ...@@ -5071,14 +5093,21 @@ int pevent_register_print_function(struct pevent *pevent,
remove_func_handler(pevent, name); 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)); memset(func_handle, 0, sizeof(*func_handle));
func_handle->ret_type = ret_type; func_handle->ret_type = ret_type;
func_handle->name = strdup(name); func_handle->name = strdup(name);
func_handle->func = func; func_handle->func = func;
if (!func_handle->name) if (!func_handle->name) {
die("Failed to allocate function name"); do_warning("Failed to allocate function name");
free(func_handle);
return PEVENT_ERRNO__MEM_ALLOC_FAILED;
}
next_param = &(func_handle->params); next_param = &(func_handle->params);
va_start(ap, name); va_start(ap, name);
...@@ -5088,11 +5117,17 @@ int pevent_register_print_function(struct pevent *pevent, ...@@ -5088,11 +5117,17 @@ int pevent_register_print_function(struct pevent *pevent,
break; break;
if (type < 0 || type >= PEVENT_FUNC_ARG_MAX_TYPES) { 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; 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->type = type;
param->next = NULL; param->next = NULL;
...@@ -5110,7 +5145,7 @@ int pevent_register_print_function(struct pevent *pevent, ...@@ -5110,7 +5145,7 @@ int pevent_register_print_function(struct pevent *pevent,
out_free: out_free:
va_end(ap); va_end(ap);
free_func_handle(func_handle); free_func_handle(func_handle);
return -1; return ret;
} }
/** /**
...@@ -5162,7 +5197,12 @@ int pevent_register_event_handler(struct pevent *pevent, ...@@ -5162,7 +5197,12 @@ int pevent_register_event_handler(struct pevent *pevent,
not_found: not_found:
/* Save for later use. */ /* 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)); memset(handle, 0, sizeof(*handle));
handle->id = id; handle->id = id;
if (event_name) if (event_name)
...@@ -5172,7 +5212,11 @@ int pevent_register_event_handler(struct pevent *pevent, ...@@ -5172,7 +5212,11 @@ int pevent_register_event_handler(struct pevent *pevent,
if ((event_name && !handle->event_name) || if ((event_name && !handle->event_name) ||
(sys_name && !handle->sys_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; handle->func = func;
......
...@@ -351,7 +351,8 @@ enum pevent_flag { ...@@ -351,7 +351,8 @@ enum pevent_flag {
_PE(READ_ID_FAILED, "failed to read event id"), \ _PE(READ_ID_FAILED, "failed to read event id"), \
_PE(READ_FORMAT_FAILED, "failed to read event format"), \ _PE(READ_FORMAT_FAILED, "failed to read event format"), \
_PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ _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 #undef _PE
#define _PE(__code, __str) PEVENT_ERRNO__ ## __code #define _PE(__code, __str) PEVENT_ERRNO__ ## __code
......
...@@ -21,3 +21,5 @@ config.mak ...@@ -21,3 +21,5 @@ config.mak
config.mak.autogen config.mak.autogen
*-bison.* *-bison.*
*-flex.* *-flex.*
*.pyc
*.pyo
...@@ -17,6 +17,9 @@ captured via perf record. ...@@ -17,6 +17,9 @@ captured via perf record.
If no parameters are passed it will assume perf.data.old and perf.data. 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 OPTIONS
------- -------
-M:: -M::
......
...@@ -755,6 +755,14 @@ else ...@@ -755,6 +755,14 @@ else
endif endif
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 ifdef ASCIIDOC8
export ASCIIDOC8 export ASCIIDOC8
endif endif
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "util/event.h" #include "util/event.h"
#include "util/hist.h" #include "util/hist.h"
#include "util/evsel.h" #include "util/evsel.h"
#include "util/evlist.h"
#include "util/session.h" #include "util/session.h"
#include "util/tool.h" #include "util/tool.h"
#include "util/sort.h" #include "util/sort.h"
...@@ -24,11 +25,6 @@ static char diff__default_sort_order[] = "dso,symbol"; ...@@ -24,11 +25,6 @@ static char diff__default_sort_order[] = "dso,symbol";
static bool force; static bool force;
static bool show_displacement; static bool show_displacement;
struct perf_diff {
struct perf_tool tool;
struct perf_session *session;
};
static int hists__add_entry(struct hists *self, static int hists__add_entry(struct hists *self,
struct addr_location *al, u64 period) struct addr_location *al, u64 period)
{ {
...@@ -37,14 +33,12 @@ static int hists__add_entry(struct hists *self, ...@@ -37,14 +33,12 @@ static int hists__add_entry(struct hists *self,
return -ENOMEM; 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, union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
struct perf_evsel *evsel __used, struct perf_evsel *evsel,
struct machine *machine) struct machine *machine)
{ {
struct perf_diff *_diff = container_of(tool, struct perf_diff, tool);
struct perf_session *session = _diff->session;
struct addr_location al; struct addr_location al;
if (perf_event__preprocess_sample(event, machine, &al, sample, NULL) < 0) { 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, ...@@ -56,26 +50,24 @@ static int diff__process_sample_event(struct perf_tool *tool,
if (al.filtered || al.sym == NULL) if (al.filtered || al.sym == NULL)
return 0; 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"); pr_warning("problem incrementing symbol period, skipping event\n");
return -1; return -1;
} }
session->hists.stats.total_period += sample->period; evsel->hists.stats.total_period += sample->period;
return 0; return 0;
} }
static struct perf_diff diff = { static struct perf_tool tool = {
.tool = { .sample = diff__process_sample_event,
.sample = diff__process_sample_event, .mmap = perf_event__process_mmap,
.mmap = perf_event__process_mmap, .comm = perf_event__process_comm,
.comm = perf_event__process_comm, .exit = perf_event__process_task,
.exit = perf_event__process_task, .fork = perf_event__process_task,
.fork = perf_event__process_task, .lost = perf_event__process_lost,
.lost = perf_event__process_lost, .ordered_samples = true,
.ordered_samples = true, .ordering_requires_timestamps = true,
.ordering_requires_timestamps = true,
},
}; };
static void perf_session__insert_hist_entry_by_name(struct rb_root *root, 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) ...@@ -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) static int __cmd_diff(void)
{ {
int ret, i; int ret, i;
#define older (session[0]) #define older (session[0])
#define newer (session[1]) #define newer (session[1])
struct perf_session *session[2]; 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, older = perf_session__new(input_old, O_RDONLY, force, false,
&diff.tool); &tool);
newer = perf_session__new(input_new, O_RDONLY, force, false, newer = perf_session__new(input_new, O_RDONLY, force, false,
&diff.tool); &tool);
if (session[0] == NULL || session[1] == NULL) if (session[0] == NULL || session[1] == NULL)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < 2; ++i) { for (i = 0; i < 2; ++i) {
diff.session = session[i]; ret = perf_session__process_events(session[i], &tool);
ret = perf_session__process_events(session[i], &diff.tool);
if (ret) if (ret)
goto out_delete; goto out_delete;
hists__output_resort(&session[i]->hists);
} }
if (show_displacement) evlist_old = older->evlist;
hists__resort_entries(&older->hists); 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: out_delete:
for (i = 0; i < 2; ++i) for (i = 0; i < 2; ++i)
perf_session__delete(session[i]); perf_session__delete(session[i]);
......
...@@ -179,3 +179,17 @@ int main(void) ...@@ -179,3 +179,17 @@ int main(void)
} }
endef endef
endif 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
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "util/run-command.h" #include "util/run-command.h"
#include "util/parse-events.h" #include "util/parse-events.h"
#include "util/debugfs.h" #include "util/debugfs.h"
#include <pthread.h>
const char perf_usage_string[] = const char perf_usage_string[] =
"perf [--version] [--help] COMMAND [ARGS]"; "perf [--version] [--help] COMMAND [ARGS]";
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "symbol.h" #include "symbol.h"
#include <linux/list.h> #include <linux/list.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
#include <pthread.h>
struct ins; struct ins;
......
...@@ -23,7 +23,7 @@ static char *test_file(int size) ...@@ -23,7 +23,7 @@ static char *test_file(int size)
int fd, i; int fd, i;
unsigned char *buf; unsigned char *buf;
fd = mkostemp(templ, O_CREAT|O_WRONLY|O_TRUNC); fd = mkstemp(templ);
buf = malloc(size); buf = malloc(size);
if (!buf) { if (!buf) {
......
...@@ -124,6 +124,13 @@ void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads); ...@@ -124,6 +124,13 @@ void perf_evsel__close(struct perf_evsel *evsel, int ncpus, int nthreads);
(evsel->attr.type == PERF_TYPE_##t && \ (evsel->attr.type == PERF_TYPE_##t && \
evsel->attr.config == PERF_COUNT_##c) 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 __perf_evsel__read_on_cpu(struct perf_evsel *evsel,
int cpu, int thread, bool scale); int cpu, int thread, bool scale);
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
#include "exec_cmd.h" #include "exec_cmd.h"
#include "levenshtein.h" #include "levenshtein.h"
#include "help.h" #include "help.h"
#include <termios.h>
void add_cmdname(struct cmdnames *cmds, const char *name, size_t len) void add_cmdname(struct cmdnames *cmds, const char *name, size_t len)
{ {
......
#include <stdbool.h>
#include "../../../../include/linux/rbtree.h" #include "../../../../include/linux/rbtree.h"
...@@ -36,9 +36,7 @@ struct perf_session { ...@@ -36,9 +36,7 @@ struct perf_session {
struct pevent *pevent; struct pevent *pevent;
/* /*
* FIXME: Need to split this up further, we need global * FIXME: Need to split this up further, we need global
* stats + per event stats. 'perf diff' also needs * stats + per event stats.
* to properly support multiple events in a single
* perf.data file.
*/ */
struct hists hists; struct hists hists;
int fd; int fd;
......
...@@ -12,8 +12,6 @@ int sort__branch_mode = -1; /* -1 = means not set */ ...@@ -12,8 +12,6 @@ int sort__branch_mode = -1; /* -1 = means not set */
enum sort_type sort__first_dimension; enum sort_type sort__first_dimension;
char * field_sep;
LIST_HEAD(hist_entry__sort_list); LIST_HEAD(hist_entry__sort_list);
static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...) 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, ...) ...@@ -23,11 +21,11 @@ static int repsep_snprintf(char *bf, size_t size, const char *fmt, ...)
va_start(ap, fmt); va_start(ap, fmt);
n = vsnprintf(bf, size, fmt, ap); n = vsnprintf(bf, size, fmt, ap);
if (field_sep && n > 0) { if (symbol_conf.field_sep && n > 0) {
char *sep = bf; char *sep = bf;
while (1) { while (1) {
sep = strchr(sep, *field_sep); sep = strchr(sep, *symbol_conf.field_sep);
if (sep == NULL) if (sep == NULL)
break; break;
*sep = '.'; *sep = '.';
......
...@@ -32,7 +32,6 @@ extern const char default_sort_order[]; ...@@ -32,7 +32,6 @@ extern const char default_sort_order[];
extern int sort__need_collapse; extern int sort__need_collapse;
extern int sort__has_parent; extern int sort__has_parent;
extern int sort__branch_mode; extern int sort__branch_mode;
extern char *field_sep;
extern struct sort_entry sort_comm; extern struct sort_entry sort_comm;
extern struct sort_entry sort_dso; extern struct sort_entry sort_dso;
extern struct sort_entry sort_sym; extern struct sort_entry sort_sym;
......
...@@ -10,6 +10,9 @@ ...@@ -10,6 +10,9 @@
#include <linux/rbtree.h> #include <linux/rbtree.h>
#include <stdio.h> #include <stdio.h>
#include <byteswap.h> #include <byteswap.h>
#if defined(__BIONIC__)
#include <libgen.h>
#endif
#ifndef NO_LIBELF_SUPPORT #ifndef NO_LIBELF_SUPPORT
#include <libelf.h> #include <libelf.h>
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "types.h" #include "types.h"
#include <stddef.h> #include <stddef.h>
#include <stdbool.h> #include <stdbool.h>
#include <termios.h>
struct perf_evlist; struct perf_evlist;
struct perf_evsel; struct perf_evsel;
......
#include "../perf.h" #include "../perf.h"
#include "util.h" #include "util.h"
#include <sys/mman.h> #include <sys/mman.h>
#ifndef NO_BACKTRACE
#include <execinfo.h> #include <execinfo.h>
#endif
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -163,6 +165,7 @@ size_t hex_width(u64 v) ...@@ -163,6 +165,7 @@ size_t hex_width(u64 v)
} }
/* Obtain a backtrace and print it to stdout. */ /* Obtain a backtrace and print it to stdout. */
#ifndef NO_BACKTRACE
void dump_stack(void) void dump_stack(void)
{ {
void *array[16]; void *array[16];
...@@ -177,3 +180,6 @@ void dump_stack(void) ...@@ -177,3 +180,6 @@ void dump_stack(void)
free(strings); free(strings);
} }
#else
void dump_stack(void) {}
#endif
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