Commit 4d9218da 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 version when building out of tree, as when using one of these:

    $ make help | grep perf
      perf-tar-src-pkg    - Build perf-3.12.0.tar source tarball
      perf-targz-src-pkg  - Build perf-3.12.0.tar.gz source tarball
      perf-tarbz2-src-pkg - Build perf-3.12.0.tar.bz2 source tarball
      perf-tarxz-src-pkg  - Build perf-3.12.0.tar.xz source tarball
    $

    from David Ahern.

  * Don't relookup fields by name in each sample in 'trace',
    by Arnaldo Carvalho de Melo.

  * 'perf record' code cleanups, from David Ahern.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 8a4d0b56 8ce000e8
...@@ -115,7 +115,9 @@ git --git-dir=$(srctree)/.git archive --prefix=$(perf-tar)/ \ ...@@ -115,7 +115,9 @@ git --git-dir=$(srctree)/.git archive --prefix=$(perf-tar)/ \
-o $(perf-tar).tar; \ -o $(perf-tar).tar; \
mkdir -p $(perf-tar); \ mkdir -p $(perf-tar); \
git --git-dir=$(srctree)/.git rev-parse HEAD > $(perf-tar)/HEAD; \ git --git-dir=$(srctree)/.git rev-parse HEAD > $(perf-tar)/HEAD; \
tar rf $(perf-tar).tar $(perf-tar)/HEAD; \ (cd $(srctree)/tools/perf; \
util/PERF-VERSION-GEN ../../$(perf-tar)/ 2>/dev/null); \
tar rf $(perf-tar).tar $(perf-tar)/HEAD $(perf-tar)/PERF-VERSION-FILE; \
rm -r $(perf-tar); \ rm -r $(perf-tar); \
$(if $(findstring tar-src,$@),, \ $(if $(findstring tar-src,$@),, \
$(if $(findstring bz2,$@),bzip2, \ $(if $(findstring bz2,$@),bzip2, \
......
...@@ -106,8 +106,8 @@ static int perf_event__repipe_sample(struct perf_tool *tool, ...@@ -106,8 +106,8 @@ static int perf_event__repipe_sample(struct perf_tool *tool,
struct perf_evsel *evsel, struct perf_evsel *evsel,
struct machine *machine) struct machine *machine)
{ {
if (evsel->handler.func) { if (evsel->handler) {
inject_handler f = evsel->handler.func; inject_handler f = evsel->handler;
return f(tool, event, sample, evsel, machine); return f(tool, event, sample, evsel, machine);
} }
...@@ -383,11 +383,11 @@ static int __cmd_inject(struct perf_inject *inject) ...@@ -383,11 +383,11 @@ static int __cmd_inject(struct perf_inject *inject)
if (perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID")) if (perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID"))
return -EINVAL; return -EINVAL;
evsel->handler.func = perf_inject__sched_switch; evsel->handler = perf_inject__sched_switch;
} else if (!strcmp(name, "sched:sched_process_exit")) } else if (!strcmp(name, "sched:sched_process_exit"))
evsel->handler.func = perf_inject__sched_process_exit; evsel->handler = perf_inject__sched_process_exit;
else if (!strncmp(name, "sched:sched_stat_", 17)) else if (!strncmp(name, "sched:sched_stat_", 17))
evsel->handler.func = perf_inject__sched_stat; evsel->handler = perf_inject__sched_stat;
} }
} }
......
...@@ -317,8 +317,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, ...@@ -317,8 +317,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid); dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
if (evsel->handler.func != NULL) { if (evsel->handler != NULL) {
tracepoint_handler f = evsel->handler.func; tracepoint_handler f = evsel->handler;
return f(evsel, sample); return f(evsel, sample);
} }
......
...@@ -819,8 +819,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, ...@@ -819,8 +819,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
return -1; return -1;
} }
if (evsel->handler.func != NULL) { if (evsel->handler != NULL) {
tracepoint_handler f = evsel->handler.func; tracepoint_handler f = evsel->handler;
return f(evsel, sample); return f(evsel, sample);
} }
......
...@@ -74,14 +74,8 @@ struct perf_record { ...@@ -74,14 +74,8 @@ struct perf_record {
bool no_buildid; bool no_buildid;
bool no_buildid_cache; bool no_buildid_cache;
long samples; long samples;
off_t post_processing_offset;
}; };
static void advance_output(struct perf_record *rec, size_t size)
{
rec->bytes_written += size;
}
static int write_output(struct perf_record *rec, void *buf, size_t size) static int write_output(struct perf_record *rec, void *buf, size_t size)
{ {
struct perf_data_file *file = &rec->file; struct perf_data_file *file = &rec->file;
...@@ -252,13 +246,14 @@ static int process_buildids(struct perf_record *rec) ...@@ -252,13 +246,14 @@ static int process_buildids(struct perf_record *rec)
{ {
struct perf_data_file *file = &rec->file; struct perf_data_file *file = &rec->file;
struct perf_session *session = rec->session; struct perf_session *session = rec->session;
u64 start = session->header.data_offset;
u64 size = lseek(file->fd, 0, SEEK_CUR); u64 size = lseek(file->fd, 0, SEEK_CUR);
if (size == 0) if (size == 0)
return 0; return 0;
return __perf_session__process_events(session, rec->post_processing_offset, return __perf_session__process_events(session, start,
size - rec->post_processing_offset, size - start,
size, &build_id__mark_dso_hit_ops); size, &build_id__mark_dso_hit_ops);
} }
...@@ -342,9 +337,28 @@ static int perf_record__mmap_read_all(struct perf_record *rec) ...@@ -342,9 +337,28 @@ static int perf_record__mmap_read_all(struct perf_record *rec)
return rc; return rc;
} }
static void perf_record__init_features(struct perf_record *rec)
{
struct perf_evlist *evsel_list = rec->evlist;
struct perf_session *session = rec->session;
int feat;
for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++)
perf_header__set_feat(&session->header, feat);
if (rec->no_buildid)
perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
if (!have_tracepoints(&evsel_list->entries))
perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
if (!rec->opts.branch_stack)
perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
}
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)
{ {
int err, feat; int err;
unsigned long waking = 0; unsigned long waking = 0;
const bool forks = argc > 0; const bool forks = argc > 0;
struct machine *machine; struct machine *machine;
...@@ -371,17 +385,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -371,17 +385,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
rec->session = session; rec->session = session;
for (feat = HEADER_FIRST_FEATURE; feat < HEADER_LAST_FEATURE; feat++) perf_record__init_features(rec);
perf_header__set_feat(&session->header, feat);
if (rec->no_buildid)
perf_header__clear_feat(&session->header, HEADER_BUILD_ID);
if (!have_tracepoints(&evsel_list->entries))
perf_header__clear_feat(&session->header, HEADER_TRACING_DATA);
if (!rec->opts.branch_stack)
perf_header__clear_feat(&session->header, HEADER_BRANCH_STACK);
if (forks) { if (forks) {
err = perf_evlist__prepare_workload(evsel_list, &opts->target, err = perf_evlist__prepare_workload(evsel_list, &opts->target,
...@@ -425,8 +429,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -425,8 +429,6 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
goto out_delete_session; goto out_delete_session;
} }
rec->post_processing_offset = lseek(file->fd, 0, SEEK_CUR);
machine = &session->machines.host; machine = &session->machines.host;
if (file->is_pipe) { if (file->is_pipe) {
...@@ -452,7 +454,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv) ...@@ -452,7 +454,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
pr_err("Couldn't record tracing data.\n"); pr_err("Couldn't record tracing data.\n");
goto out_delete_session; goto out_delete_session;
} }
advance_output(rec, err); rec->bytes_written += err;
} }
} }
......
...@@ -1427,8 +1427,8 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_ ...@@ -1427,8 +1427,8 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool __maybe_
evsel->hists.stats.total_period += sample->period; evsel->hists.stats.total_period += sample->period;
hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE); hists__inc_nr_events(&evsel->hists, PERF_RECORD_SAMPLE);
if (evsel->handler.func != NULL) { if (evsel->handler != NULL) {
tracepoint_handler f = evsel->handler.func; tracepoint_handler f = evsel->handler;
err = f(tool, evsel, sample, machine); err = f(tool, evsel, sample, machine);
} }
......
...@@ -483,8 +483,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused, ...@@ -483,8 +483,8 @@ static int process_sample_event(struct perf_tool *tool __maybe_unused,
if (sample->cpu > numcpus) if (sample->cpu > numcpus)
numcpus = sample->cpu; numcpus = sample->cpu;
if (evsel->handler.func != NULL) { if (evsel->handler != NULL) {
tracepoint_handler f = evsel->handler.func; tracepoint_handler f = evsel->handler;
return f(evsel, sample); return f(evsel, sample);
} }
......
...@@ -35,6 +35,189 @@ ...@@ -35,6 +35,189 @@
# define MADV_UNMERGEABLE 13 # define MADV_UNMERGEABLE 13
#endif #endif
struct tp_field {
int offset;
union {
u64 (*integer)(struct tp_field *field, struct perf_sample *sample);
void *(*pointer)(struct tp_field *field, struct perf_sample *sample);
};
};
#define TP_UINT_FIELD(bits) \
static u64 tp_field__u##bits(struct tp_field *field, struct perf_sample *sample) \
{ \
return *(u##bits *)(sample->raw_data + field->offset); \
}
TP_UINT_FIELD(8);
TP_UINT_FIELD(16);
TP_UINT_FIELD(32);
TP_UINT_FIELD(64);
#define TP_UINT_FIELD__SWAPPED(bits) \
static u64 tp_field__swapped_u##bits(struct tp_field *field, struct perf_sample *sample) \
{ \
u##bits value = *(u##bits *)(sample->raw_data + field->offset); \
return bswap_##bits(value);\
}
TP_UINT_FIELD__SWAPPED(16);
TP_UINT_FIELD__SWAPPED(32);
TP_UINT_FIELD__SWAPPED(64);
static int tp_field__init_uint(struct tp_field *field,
struct format_field *format_field,
bool needs_swap)
{
field->offset = format_field->offset;
switch (format_field->size) {
case 1:
field->integer = tp_field__u8;
break;
case 2:
field->integer = needs_swap ? tp_field__swapped_u16 : tp_field__u16;
break;
case 4:
field->integer = needs_swap ? tp_field__swapped_u32 : tp_field__u32;
break;
case 8:
field->integer = needs_swap ? tp_field__swapped_u64 : tp_field__u64;
break;
default:
return -1;
}
return 0;
}
static void *tp_field__ptr(struct tp_field *field, struct perf_sample *sample)
{
return sample->raw_data + field->offset;
}
static int tp_field__init_ptr(struct tp_field *field, struct format_field *format_field)
{
field->offset = format_field->offset;
field->pointer = tp_field__ptr;
return 0;
}
struct syscall_tp {
struct tp_field id;
union {
struct tp_field args, ret;
};
};
static int perf_evsel__init_tp_uint_field(struct perf_evsel *evsel,
struct tp_field *field,
const char *name)
{
struct format_field *format_field = perf_evsel__field(evsel, name);
if (format_field == NULL)
return -1;
return tp_field__init_uint(field, format_field, evsel->needs_swap);
}
#define perf_evsel__init_sc_tp_uint_field(evsel, name) \
({ struct syscall_tp *sc = evsel->priv;\
perf_evsel__init_tp_uint_field(evsel, &sc->name, #name); })
static int perf_evsel__init_tp_ptr_field(struct perf_evsel *evsel,
struct tp_field *field,
const char *name)
{
struct format_field *format_field = perf_evsel__field(evsel, name);
if (format_field == NULL)
return -1;
return tp_field__init_ptr(field, format_field);
}
#define perf_evsel__init_sc_tp_ptr_field(evsel, name) \
({ struct syscall_tp *sc = evsel->priv;\
perf_evsel__init_tp_ptr_field(evsel, &sc->name, #name); })
static void perf_evsel__delete_priv(struct perf_evsel *evsel)
{
free(evsel->priv);
evsel->priv = NULL;
perf_evsel__delete(evsel);
}
static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction,
void *handler, int idx)
{
struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction, idx);
if (evsel) {
evsel->priv = malloc(sizeof(struct syscall_tp));
if (evsel->priv == NULL)
goto out_delete;
if (perf_evsel__init_sc_tp_uint_field(evsel, id))
goto out_delete;
evsel->handler = handler;
}
return evsel;
out_delete:
perf_evsel__delete_priv(evsel);
return NULL;
}
#define perf_evsel__sc_tp_uint(evsel, name, sample) \
({ struct syscall_tp *fields = evsel->priv; \
fields->name.integer(&fields->name, sample); })
#define perf_evsel__sc_tp_ptr(evsel, name, sample) \
({ struct syscall_tp *fields = evsel->priv; \
fields->name.pointer(&fields->name, sample); })
static int perf_evlist__add_syscall_newtp(struct perf_evlist *evlist,
void *sys_enter_handler,
void *sys_exit_handler)
{
int ret = -1;
int idx = evlist->nr_entries;
struct perf_evsel *sys_enter, *sys_exit;
sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler, idx++);
if (sys_enter == NULL)
goto out;
if (perf_evsel__init_sc_tp_ptr_field(sys_enter, args))
goto out_delete_sys_enter;
sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler, idx++);
if (sys_exit == NULL)
goto out_delete_sys_enter;
if (perf_evsel__init_sc_tp_uint_field(sys_exit, ret))
goto out_delete_sys_exit;
perf_evlist__add(evlist, sys_enter);
perf_evlist__add(evlist, sys_exit);
ret = 0;
out:
return ret;
out_delete_sys_exit:
perf_evsel__delete_priv(sys_exit);
out_delete_sys_enter:
perf_evsel__delete_priv(sys_enter);
goto out;
}
struct syscall_arg { struct syscall_arg {
unsigned long val; unsigned long val;
struct thread *thread; struct thread *thread;
...@@ -1392,7 +1575,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, ...@@ -1392,7 +1575,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
void *args; void *args;
size_t printed = 0; size_t printed = 0;
struct thread *thread; struct thread *thread;
int id = perf_evsel__intval(evsel, sample, "id"); int id = perf_evsel__sc_tp_uint(evsel, id, sample);
struct syscall *sc = trace__syscall_info(trace, evsel, id); struct syscall *sc = trace__syscall_info(trace, evsel, id);
struct thread_trace *ttrace; struct thread_trace *ttrace;
...@@ -1407,12 +1590,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, ...@@ -1407,12 +1590,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
if (ttrace == NULL) if (ttrace == NULL)
return -1; return -1;
args = perf_evsel__rawptr(evsel, sample, "args"); args = perf_evsel__sc_tp_ptr(evsel, args, sample);
if (args == NULL) {
fprintf(trace->output, "Problems reading syscall arguments\n");
return -1;
}
ttrace = thread->priv; ttrace = thread->priv;
if (ttrace->entry_str == NULL) { if (ttrace->entry_str == NULL) {
...@@ -1445,7 +1623,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, ...@@ -1445,7 +1623,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
int ret; int ret;
u64 duration = 0; u64 duration = 0;
struct thread *thread; struct thread *thread;
int id = perf_evsel__intval(evsel, sample, "id"); int id = perf_evsel__sc_tp_uint(evsel, id, sample);
struct syscall *sc = trace__syscall_info(trace, evsel, id); struct syscall *sc = trace__syscall_info(trace, evsel, id);
struct thread_trace *ttrace; struct thread_trace *ttrace;
...@@ -1463,7 +1641,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, ...@@ -1463,7 +1641,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
if (trace->summary) if (trace->summary)
thread__update_stats(ttrace, id, sample); thread__update_stats(ttrace, id, sample);
ret = perf_evsel__intval(evsel, sample, "ret"); ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
if (id == trace->audit.open_id && ret >= 0 && trace->last_vfs_getname) { if (id == trace->audit.open_id && ret >= 0 && trace->last_vfs_getname) {
trace__set_fd_pathname(thread, ret, trace->last_vfs_getname); trace__set_fd_pathname(thread, ret, trace->last_vfs_getname);
...@@ -1570,7 +1748,7 @@ static int trace__process_sample(struct perf_tool *tool, ...@@ -1570,7 +1748,7 @@ static int trace__process_sample(struct perf_tool *tool,
struct trace *trace = container_of(tool, struct trace, tool); struct trace *trace = container_of(tool, struct trace, tool);
int err = 0; int err = 0;
tracepoint_handler handler = evsel->handler.func; tracepoint_handler handler = evsel->handler;
if (skip_sample(trace, sample)) if (skip_sample(trace, sample))
return 0; return 0;
...@@ -1656,7 +1834,7 @@ static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist) ...@@ -1656,7 +1834,7 @@ static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
return; return;
} }
evsel->handler.func = trace__vfs_getname; evsel->handler = trace__vfs_getname;
perf_evlist__add(evlist, evsel); perf_evlist__add(evlist, evsel);
} }
...@@ -1675,8 +1853,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -1675,8 +1853,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
goto out; goto out;
} }
if (perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_enter", trace__sys_enter) || if (perf_evlist__add_syscall_newtp(evlist, trace__sys_enter, trace__sys_exit))
perf_evlist__add_newtp(evlist, "raw_syscalls", "sys_exit", trace__sys_exit))
goto out_error_tp; goto out_error_tp;
perf_evlist__add_vfs_getname(evlist); perf_evlist__add_vfs_getname(evlist);
...@@ -1768,7 +1945,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -1768,7 +1945,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
goto next_event; goto next_event;
} }
handler = evsel->handler.func; handler = evsel->handler;
handler(trace, evsel, &sample); handler(trace, evsel, &sample);
next_event: next_event:
perf_evlist__mmap_consume(evlist, i); perf_evlist__mmap_consume(evlist, i);
......
...@@ -19,6 +19,9 @@ if test -d ../../.git -o -f ../../.git ...@@ -19,6 +19,9 @@ if test -d ../../.git -o -f ../../.git
then then
TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null ) TAG=$(git describe --abbrev=0 --match "v[0-9].[0-9]*" 2>/dev/null )
CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID" CID=$(git log -1 --abbrev=4 --pretty=format:"%h" 2>/dev/null) && CID="-g$CID"
elif test -f ../../PERF-VERSION-FILE
then
TAG=$(cut -d' ' -f3 ../../PERF-VERSION-FILE | sed -e 's/\"//g')
fi fi
if test -z "$TAG" if test -z "$TAG"
then then
......
...@@ -255,7 +255,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist, ...@@ -255,7 +255,7 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
if (evsel == NULL) if (evsel == NULL)
return -1; return -1;
evsel->handler.func = handler; evsel->handler = handler;
perf_evlist__add(evlist, evsel); perf_evlist__add(evlist, evsel);
return 0; return 0;
} }
......
...@@ -74,10 +74,7 @@ struct perf_evsel { ...@@ -74,10 +74,7 @@ struct perf_evsel {
off_t id_offset; off_t id_offset;
}; };
struct cgroup_sel *cgrp; struct cgroup_sel *cgrp;
struct { void *handler;
void *func;
void *data;
} handler;
struct cpu_map *cpus; struct cpu_map *cpus;
unsigned int sample_size; unsigned int sample_size;
int id_pos; int id_pos;
......
...@@ -1650,9 +1650,9 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session, ...@@ -1650,9 +1650,9 @@ int __perf_session__set_tracepoints_handlers(struct perf_session *session,
continue; continue;
err = -EEXIST; err = -EEXIST;
if (evsel->handler.func != NULL) if (evsel->handler != NULL)
goto out; goto out;
evsel->handler.func = assocs[i].handler; evsel->handler = assocs[i].handler;
} }
err = 0; err = 0;
......
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
#include "parse-events.h" #include "parse-events.h"
#include "thread.h" #include "thread.h"
#include "sort.h"
extern regex_t parent_regex; extern regex_t parent_regex;
extern const char *sort_order; extern const char *sort_order;
......
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