Skip to content

Commit

Permalink
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/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>
  • Loading branch information
Ingo Molnar committed Sep 8, 2012
2 parents 479d875 + b155a09 commit ef34eb4
Show file tree
Hide file tree
Showing 19 changed files with 180 additions and 63 deletions.
86 changes: 65 additions & 21 deletions tools/lib/traceevent/event-parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
Expand All @@ -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;

Expand All @@ -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;
}

/**
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion tools/lib/traceevent/event-parse.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions tools/perf/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,5 @@ config.mak
config.mak.autogen
*-bison.*
*-flex.*
*.pyc
*.pyo
3 changes: 3 additions & 0 deletions tools/perf/Documentation/perf-diff.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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::
Expand Down
8 changes: 8 additions & 0 deletions tools/perf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
93 changes: 61 additions & 32 deletions tools/perf/builtin-diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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)
{
Expand All @@ -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) {
Expand All @@ -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,
Expand Down Expand Up @@ -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]);
Expand Down
14 changes: 14 additions & 0 deletions tools/perf/config/feature-tests.mak
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading

0 comments on commit ef34eb4

Please sign in to comment.