Commit 0afb1704 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:

New user selectable features:

  - Support recording running/enabled time in 'perf record' (Andi Kleen)

  - New tool: 'perf data' for converting perf.data to other formats,
    initially for the CTF (Common Trace Format) from LTTng (Jiri Olsa, Sebastian Siewior)

User visible changes:

  - Only insert blank duration bracket when tracing syscalls in 'perf trace' (Arnaldo Carvalho de Melo)

  - Filter out the trace pid when no threads are specified in 'perf trace' (Arnaldo Carvalho de Melo)

  - Add 'perf trace' man page entry for --event (Arnaldo Carvalho de Melo)

  - Dump stack on segfaults in 'perf trace' (Arnaldo Carvalho de Melo)

Infrastructure changes:

  - Introduce set_filter_pid and set_filter_pids methods in the evlist class (Arnaldo Carvalho de Melo)

  - Some perf_session untanglement patches, removing the need to pass a
    perf_session instance for things that are related to evlists, so that
    tools that don't deal with perf.data files like trace in live mode can
    make use of the ordered_events class (Arnaldo Carvalho de Melo)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents e9e4e443 54cf776a
...@@ -18,6 +18,7 @@ perf-y += builtin-lock.o ...@@ -18,6 +18,7 @@ perf-y += builtin-lock.o
perf-y += builtin-kvm.o perf-y += builtin-kvm.o
perf-y += builtin-inject.o perf-y += builtin-inject.o
perf-y += builtin-mem.o perf-y += builtin-mem.o
perf-y += builtin-data.o
perf-$(CONFIG_AUDIT) += builtin-trace.o perf-$(CONFIG_AUDIT) += builtin-trace.o
perf-$(CONFIG_LIBELF) += builtin-probe.o perf-$(CONFIG_LIBELF) += builtin-probe.o
......
perf-data(1)
==============
NAME
----
perf-data - Data file related processing
SYNOPSIS
--------
[verse]
'perf data' [<common options>] <command> [<options>]",
DESCRIPTION
-----------
Data file related processing.
COMMANDS
--------
convert::
Converts perf data file into another format (only CTF [1] format is support by now).
It's possible to set data-convert debug variable to get debug messages from conversion,
like:
perf --debug data-convert data convert ...
OPTIONS for 'convert'
---------------------
--to-ctf::
Triggers the CTF conversion, specify the path of CTF data directory.
-i::
Specify input perf data file path.
-v::
--verbose::
Be more verbose (show counter open errors, etc).
SEE ALSO
--------
linkperf:perf[1]
[1] Common Trace Format - http://www.efficios.com/ctf
...@@ -241,6 +241,9 @@ Capture machine state (registers) at interrupt, i.e., on counter overflows for ...@@ -241,6 +241,9 @@ Capture machine state (registers) at interrupt, i.e., on counter overflows for
each sample. List of captured registers depends on the architecture. This option each sample. List of captured registers depends on the architecture. This option
is off by default. is off by default.
--running-time::
Record running and enabled time for read events (:S)
SEE ALSO SEE ALSO
-------- --------
linkperf:perf-stat[1], linkperf:perf-list[1] linkperf:perf-stat[1], linkperf:perf-list[1]
...@@ -55,6 +55,9 @@ OPTIONS ...@@ -55,6 +55,9 @@ OPTIONS
--uid=:: --uid=::
Record events in threads owned by uid. Name or number. Record events in threads owned by uid. Name or number.
--filter-pids=::
Filter out events for these pids and for 'trace' itself (comma separated list).
-v:: -v::
--verbose=:: --verbose=::
Verbosity level. Verbosity level.
...@@ -115,6 +118,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. ...@@ -115,6 +118,9 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
--syscalls:: --syscalls::
Trace system calls. This options is enabled by default. Trace system calls. This options is enabled by default.
--event::
Trace other events, see 'perf list' for a complete list.
PAGEFAULTS PAGEFAULTS
---------- ----------
......
...@@ -13,11 +13,16 @@ SYNOPSIS ...@@ -13,11 +13,16 @@ SYNOPSIS
OPTIONS OPTIONS
------- -------
--debug:: --debug::
Setup debug variable (just verbose for now) in value Setup debug variable (see list below) in value
range (0, 10). Use like: range (0, 10). Use like:
--debug verbose # sets verbose = 1 --debug verbose # sets verbose = 1
--debug verbose=2 # sets verbose = 2 --debug verbose=2 # sets verbose = 2
List of debug variables allowed to set:
verbose - general debug messages
ordered-events - ordered events object debug messages
data-convert - data convert command debug messages
--buildid-dir:: --buildid-dir::
Setup buildid cache directory. It has higher priority than Setup buildid cache directory. It has higher priority than
buildid.dir config file option. buildid.dir config file option.
......
...@@ -68,7 +68,9 @@ include config/utilities.mak ...@@ -68,7 +68,9 @@ include config/utilities.mak
# for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode # for reading the x32 mode 32-bit compatibility VDSO in 64-bit mode
# #
# Define NO_ZLIB if you do not want to support compressed kernel modules # Define NO_ZLIB if you do not want to support compressed kernel modules
#
# Define NO_LIBBABELTRACE if you do not want libbabeltrace support
# for CTF data format.
ifeq ($(srctree),) ifeq ($(srctree),)
srctree := $(patsubst %/,%,$(dir $(shell pwd))) srctree := $(patsubst %/,%,$(dir $(shell pwd)))
......
#include <linux/compiler.h>
#include "builtin.h"
#include "perf.h"
#include "debug.h"
#include "parse-options.h"
#include "data-convert-bt.h"
typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
struct data_cmd {
const char *name;
const char *summary;
data_cmd_fn_t fn;
};
static struct data_cmd data_cmds[];
#define for_each_cmd(cmd) \
for (cmd = data_cmds; cmd && cmd->name; cmd++)
static const struct option data_options[] = {
OPT_END()
};
static const char * const data_usage[] = {
"perf data [<common options>] <command> [<options>]",
NULL
};
static void print_usage(void)
{
struct data_cmd *cmd;
printf("Usage:\n");
printf("\t%s\n\n", data_usage[0]);
printf("\tAvailable commands:\n");
for_each_cmd(cmd) {
printf("\t %s\t- %s\n", cmd->name, cmd->summary);
}
printf("\n");
}
static const char * const data_convert_usage[] = {
"perf data convert [<options>]",
NULL
};
static int cmd_data_convert(int argc, const char **argv,
const char *prefix __maybe_unused)
{
const char *to_ctf = NULL;
const struct option options[] = {
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
OPT_STRING('i', "input", &input_name, "file", "input file name"),
#ifdef HAVE_LIBBABELTRACE_SUPPORT
OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"),
#endif
OPT_END()
};
#ifndef HAVE_LIBBABELTRACE_SUPPORT
pr_err("No conversion support compiled in.\n");
return -1;
#endif
argc = parse_options(argc, argv, options,
data_convert_usage, 0);
if (argc) {
usage_with_options(data_convert_usage, options);
return -1;
}
if (to_ctf) {
#ifdef HAVE_LIBBABELTRACE_SUPPORT
return bt_convert__perf2ctf(input_name, to_ctf);
#else
pr_err("The libbabeltrace support is not compiled in.\n");
return -1;
#endif
}
return 0;
}
static struct data_cmd data_cmds[] = {
{ "convert", "converts data file between formats", cmd_data_convert },
{ NULL },
};
int cmd_data(int argc, const char **argv, const char *prefix)
{
struct data_cmd *cmd;
const char *cmdstr;
/* No command specified. */
if (argc < 2)
goto usage;
argc = parse_options(argc, argv, data_options, data_usage,
PARSE_OPT_STOP_AT_NON_OPTION);
if (argc < 1)
goto usage;
cmdstr = argv[0];
for_each_cmd(cmd) {
if (strcmp(cmd->name, cmdstr))
continue;
return cmd->fn(argc, argv, prefix);
}
pr_err("Unknown command: %s\n", cmdstr);
usage:
print_usage();
return -1;
}
...@@ -839,6 +839,8 @@ struct option __record_options[] = { ...@@ -839,6 +839,8 @@ struct option __record_options[] = {
"use per-thread mmaps"), "use per-thread mmaps"),
OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs, OPT_BOOLEAN('I', "intr-regs", &record.opts.sample_intr_regs,
"Sample machine registers on interrupt"), "Sample machine registers on interrupt"),
OPT_BOOLEAN(0, "running-time", &record.opts.running_time,
"Record running/enabled time of read (:S) events"),
OPT_END() OPT_END()
}; };
......
...@@ -1473,9 +1473,9 @@ static int perf_sched__read_events(struct perf_sched *sched, ...@@ -1473,9 +1473,9 @@ static int perf_sched__read_events(struct perf_sched *sched,
goto out_delete; goto out_delete;
} }
sched->nr_events = session->stats.nr_events[0]; sched->nr_events = session->evlist->stats.nr_events[0];
sched->nr_lost_events = session->stats.total_lost; sched->nr_lost_events = session->evlist->stats.total_lost;
sched->nr_lost_chunks = session->stats.nr_events[PERF_RECORD_LOST]; sched->nr_lost_chunks = session->evlist->stats.nr_events[PERF_RECORD_LOST];
} }
if (psession) if (psession)
......
...@@ -716,7 +716,7 @@ static void perf_event__process_sample(struct perf_tool *tool, ...@@ -716,7 +716,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
if (!machine) { if (!machine) {
pr_err("%u unprocessable samples recorded.\r", pr_err("%u unprocessable samples recorded.\r",
top->session->stats.nr_unprocessable_samples++); top->session->evlist->stats.nr_unprocessable_samples++);
return; return;
} }
...@@ -856,7 +856,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx) ...@@ -856,7 +856,7 @@ static void perf_top__mmap_read_idx(struct perf_top *top, int idx)
hists__inc_nr_events(evsel__hists(evsel), event->header.type); hists__inc_nr_events(evsel__hists(evsel), event->header.type);
machine__process_event(machine, event, &sample); machine__process_event(machine, event, &sample);
} else } else
++session->stats.nr_unknown_events; ++session->evlist->stats.nr_unknown_events;
next_event: next_event:
perf_evlist__mmap_consume(top->evlist, idx); perf_evlist__mmap_consume(top->evlist, idx);
} }
......
...@@ -1229,6 +1229,10 @@ struct trace { ...@@ -1229,6 +1229,10 @@ struct trace {
const char *last_vfs_getname; const char *last_vfs_getname;
struct intlist *tid_list; struct intlist *tid_list;
struct intlist *pid_list; struct intlist *pid_list;
struct {
size_t nr;
pid_t *entries;
} filter_pids;
double duration_filter; double duration_filter;
double runtime_ms; double runtime_ms;
struct { struct {
...@@ -1840,7 +1844,11 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, ...@@ -1840,7 +1844,11 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
{ {
trace__printf_interrupted_entry(trace, sample); trace__printf_interrupted_entry(trace, sample);
trace__fprintf_tstamp(trace, sample->time, trace->output); trace__fprintf_tstamp(trace, sample->time, trace->output);
fprintf(trace->output, "(%9.9s): %s:", " ", evsel->name);
if (trace->trace_syscalls)
fprintf(trace->output, "( ): ");
fprintf(trace->output, "%s:", evsel->name);
if (evsel->tp_format) { if (evsel->tp_format) {
event_format__fprintf(evsel->tp_format, sample->cpu, event_format__fprintf(evsel->tp_format, sample->cpu,
...@@ -2084,10 +2092,39 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist, ...@@ -2084,10 +2092,39 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
return 0; return 0;
} }
static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
{
const u32 type = event->header.type;
struct perf_evsel *evsel;
if (!trace->full_time && trace->base_time == 0)
trace->base_time = sample->time;
if (type != PERF_RECORD_SAMPLE) {
trace__process_event(trace, trace->host, event, sample);
return;
}
evsel = perf_evlist__id2evsel(trace->evlist, sample->id);
if (evsel == NULL) {
fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample->id);
return;
}
if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
sample->raw_data == NULL) {
fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
perf_evsel__name(evsel), sample->tid,
sample->cpu, sample->raw_size);
} else {
tracepoint_handler handler = evsel->handler;
handler(trace, evsel, event, sample);
}
}
static int trace__run(struct trace *trace, int argc, const char **argv) static int trace__run(struct trace *trace, int argc, const char **argv)
{ {
struct perf_evlist *evlist = trace->evlist; struct perf_evlist *evlist = trace->evlist;
struct perf_evsel *evsel;
int err = -1, i; int err = -1, i;
unsigned long before; unsigned long before;
const bool forks = argc > 0; const bool forks = argc > 0;
...@@ -2147,6 +2184,22 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -2147,6 +2184,22 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
if (err < 0) if (err < 0)
goto out_error_open; goto out_error_open;
/*
* Better not use !target__has_task() here because we need to cover the
* case where no threads were specified in the command line, but a
* workload was, and in that case we will fill in the thread_map when
* we fork the workload in perf_evlist__prepare_workload.
*/
if (trace->filter_pids.nr > 0)
err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
else if (evlist->threads->map[0] == -1)
err = perf_evlist__set_filter_pid(evlist, getpid());
if (err < 0) {
printf("err=%d,%s\n", -err, strerror(-err));
exit(1);
}
err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false); err = perf_evlist__mmap(evlist, trace->opts.mmap_pages, false);
if (err < 0) if (err < 0)
goto out_error_mmap; goto out_error_mmap;
...@@ -2166,8 +2219,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -2166,8 +2219,6 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
union perf_event *event; union perf_event *event;
while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) { while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
const u32 type = event->header.type;
tracepoint_handler handler;
struct perf_sample sample; struct perf_sample sample;
++trace->nr_events; ++trace->nr_events;
...@@ -2178,30 +2229,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -2178,30 +2229,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
goto next_event; goto next_event;
} }
if (!trace->full_time && trace->base_time == 0) trace__handle_event(trace, event, &sample);
trace->base_time = sample.time;
if (type != PERF_RECORD_SAMPLE) {
trace__process_event(trace, trace->host, event, &sample);
continue;
}
evsel = perf_evlist__id2evsel(evlist, sample.id);
if (evsel == NULL) {
fprintf(trace->output, "Unknown tp ID %" PRIu64 ", skipping...\n", sample.id);
goto next_event;
}
if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
sample.raw_data == NULL) {
fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
perf_evsel__name(evsel), sample.tid,
sample.cpu, sample.raw_size);
goto next_event;
}
handler = evsel->handler;
handler(trace, evsel, event, &sample);
next_event: next_event:
perf_evlist__mmap_consume(evlist, i); perf_evlist__mmap_consume(evlist, i);
...@@ -2478,6 +2506,38 @@ static int trace__set_duration(const struct option *opt, const char *str, ...@@ -2478,6 +2506,38 @@ static int trace__set_duration(const struct option *opt, const char *str,
return 0; return 0;
} }
static int trace__set_filter_pids(const struct option *opt, const char *str,
int unset __maybe_unused)
{
int ret = -1;
size_t i;
struct trace *trace = opt->value;
/*
* FIXME: introduce a intarray class, plain parse csv and create a
* { int nr, int entries[] } struct...
*/
struct intlist *list = intlist__new(str);
if (list == NULL)
return -1;
i = trace->filter_pids.nr = intlist__nr_entries(list) + 1;
trace->filter_pids.entries = calloc(i, sizeof(pid_t));
if (trace->filter_pids.entries == NULL)
goto out;
trace->filter_pids.entries[0] = getpid();
for (i = 1; i < trace->filter_pids.nr; ++i)
trace->filter_pids.entries[i] = intlist__entry(list, i - 1)->i;
intlist__delete(list);
ret = 0;
out:
return ret;
}
static int trace__open_output(struct trace *trace, const char *filename) static int trace__open_output(struct trace *trace, const char *filename)
{ {
struct stat st; struct stat st;
...@@ -2568,6 +2628,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -2568,6 +2628,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
"trace events on existing process id"), "trace events on existing process id"),
OPT_STRING('t', "tid", &trace.opts.target.tid, "tid", OPT_STRING('t', "tid", &trace.opts.target.tid, "tid",
"trace events on existing thread id"), "trace events on existing thread id"),
OPT_CALLBACK(0, "filter-pids", &trace, "float",
"show only events with duration > N.M ms", trace__set_filter_pids),
OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide, OPT_BOOLEAN('a', "all-cpus", &trace.opts.target.system_wide,
"system-wide collection from all CPUs"), "system-wide collection from all CPUs"),
OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu", OPT_STRING('C', "cpu", &trace.opts.target.cpu_list, "cpu",
...@@ -2598,6 +2660,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -2598,6 +2660,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
int err; int err;
char bf[BUFSIZ]; char bf[BUFSIZ];
signal(SIGSEGV, sighandler_dump_stack);
signal(SIGFPE, sighandler_dump_stack);
trace.evlist = perf_evlist__new(); trace.evlist = perf_evlist__new();
if (trace.evlist == NULL) if (trace.evlist == NULL)
return -ENOMEM; return -ENOMEM;
......
...@@ -37,6 +37,7 @@ extern int cmd_test(int argc, const char **argv, const char *prefix); ...@@ -37,6 +37,7 @@ extern int cmd_test(int argc, const char **argv, const char *prefix);
extern int cmd_trace(int argc, const char **argv, const char *prefix); extern int cmd_trace(int argc, const char **argv, const char *prefix);
extern int cmd_inject(int argc, const char **argv, const char *prefix); extern int cmd_inject(int argc, const char **argv, const char *prefix);
extern int cmd_mem(int argc, const char **argv, const char *prefix); extern int cmd_mem(int argc, const char **argv, const char *prefix);
extern int cmd_data(int argc, const char **argv, const char *prefix);
extern int find_scripts(char **scripts_array, char **scripts_path_array); extern int find_scripts(char **scripts_array, char **scripts_path_array);
#endif #endif
...@@ -7,6 +7,7 @@ perf-archive mainporcelain common ...@@ -7,6 +7,7 @@ perf-archive mainporcelain common
perf-bench mainporcelain common perf-bench mainporcelain common
perf-buildid-cache mainporcelain common perf-buildid-cache mainporcelain common
perf-buildid-list mainporcelain common perf-buildid-list mainporcelain common
perf-data mainporcelain common
perf-diff mainporcelain common perf-diff mainporcelain common
perf-evlist mainporcelain common perf-evlist mainporcelain common
perf-inject mainporcelain common perf-inject mainporcelain common
......
...@@ -96,6 +96,17 @@ ifndef NO_LIBELF ...@@ -96,6 +96,17 @@ ifndef NO_LIBELF
FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
endif endif
ifndef NO_LIBBABELTRACE
# for linking with debug library, run like:
# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
ifdef LIBBABELTRACE_DIR
LIBBABELTRACE_CFLAGS := -I$(LIBBABELTRACE_DIR)/include
LIBBABELTRACE_LDFLAGS := -L$(LIBBABELTRACE_DIR)/lib
endif
FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
endif
# include ARCH specific config # include ARCH specific config
-include $(src-perf)/arch/$(ARCH)/Makefile -include $(src-perf)/arch/$(ARCH)/Makefile
...@@ -216,6 +227,7 @@ CORE_FEATURE_TESTS = \ ...@@ -216,6 +227,7 @@ CORE_FEATURE_TESTS = \
stackprotector-all \ stackprotector-all \
timerfd \ timerfd \
libdw-dwarf-unwind \ libdw-dwarf-unwind \
libbabeltrace \
zlib zlib
LIB_FEATURE_TESTS = \ LIB_FEATURE_TESTS = \
...@@ -231,6 +243,7 @@ LIB_FEATURE_TESTS = \ ...@@ -231,6 +243,7 @@ LIB_FEATURE_TESTS = \
libslang \ libslang \
libunwind \ libunwind \
libdw-dwarf-unwind \ libdw-dwarf-unwind \
libbabeltrace \
zlib zlib
VF_FEATURE_TESTS = \ VF_FEATURE_TESTS = \
...@@ -692,6 +705,18 @@ else ...@@ -692,6 +705,18 @@ else
NO_PERF_READ_VDSOX32 := 1 NO_PERF_READ_VDSOX32 := 1
endif endif
ifndef NO_LIBBABELTRACE
ifeq ($(feature-libbabeltrace), 0)
msg := $(warning No libbabeltrace found, disables 'perf data' CTF format support, please install libbabeltrace-devel/libbabeltrace-ctf-dev);
NO_LIBBABELTRACE := 1
else
CFLAGS += -DHAVE_LIBBABELTRACE_SUPPORT $(LIBBABELTRACE_CFLAGS)
LDFLAGS += $(LIBBABELTRACE_LDFLAGS)
EXTLIBS += -lbabeltrace-ctf
$(call detected,CONFIG_LIBBABELTRACE)
endif
endif
# Among the variables below, these: # Among the variables below, these:
# perfexecdir # perfexecdir
# template_dir # template_dir
......
...@@ -29,6 +29,7 @@ FILES= \ ...@@ -29,6 +29,7 @@ FILES= \
test-stackprotector-all.bin \ test-stackprotector-all.bin \
test-timerfd.bin \ test-timerfd.bin \
test-libdw-dwarf-unwind.bin \ test-libdw-dwarf-unwind.bin \
test-libbabeltrace.bin \
test-compile-32.bin \ test-compile-32.bin \
test-compile-x32.bin \ test-compile-x32.bin \
test-zlib.bin test-zlib.bin
...@@ -43,7 +44,7 @@ BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS) ...@@ -43,7 +44,7 @@ BUILD = $(CC) $(CFLAGS) -o $(OUTPUT)$@ $(patsubst %.bin,%.c,$@) $(LDFLAGS)
############################### ###############################
test-all.bin: test-all.bin:
$(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz $(BUILD) -Werror -fstack-protector-all -O2 -Werror -D_FORTIFY_SOURCE=2 -ldw -lelf -lnuma -lelf -laudit -I/usr/include/slang -lslang $(shell $(PKG_CONFIG) --libs --cflags gtk+-2.0 2>/dev/null) $(FLAGS_PERL_EMBED) $(FLAGS_PYTHON_EMBED) -DPACKAGE='"perf"' -lbfd -ldl -lz -lbabeltrace
test-hello.bin: test-hello.bin:
$(BUILD) $(BUILD)
...@@ -133,7 +134,10 @@ test-timerfd.bin: ...@@ -133,7 +134,10 @@ test-timerfd.bin:
$(BUILD) $(BUILD)
test-libdw-dwarf-unwind.bin: test-libdw-dwarf-unwind.bin:
$(BUILD) $(BUILD) # -ldw provided by $(FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind)
test-libbabeltrace.bin:
$(BUILD) # -lbabeltrace provided by $(FEATURE_CHECK_LDFLAGS-libbabeltrace)
test-sync-compare-and-swap.bin: test-sync-compare-and-swap.bin:
$(BUILD) -Werror $(BUILD) -Werror
......
...@@ -101,6 +101,10 @@ ...@@ -101,6 +101,10 @@
# include "test-pthread_attr_setaffinity_np.c" # include "test-pthread_attr_setaffinity_np.c"
#undef main #undef main
#define main main_test_libbabeltrace
# include "test-libbabeltrace.c"
#undef main
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
main_test_libpython(); main_test_libpython();
...@@ -126,6 +130,7 @@ int main(int argc, char *argv[]) ...@@ -126,6 +130,7 @@ int main(int argc, char *argv[])
main_test_sync_compare_and_swap(argc, argv); main_test_sync_compare_and_swap(argc, argv);
main_test_zlib(); main_test_zlib();
main_test_pthread_attr_setaffinity_np(); main_test_pthread_attr_setaffinity_np();
main_test_libbabeltrace();
return 0; return 0;
} }
#include <babeltrace/ctf-writer/writer.h>
int main(void)
{
bt_ctf_stream_class_get_packet_context_type((void *) 0);
return 0;
}
...@@ -62,6 +62,7 @@ static struct cmd_struct commands[] = { ...@@ -62,6 +62,7 @@ static struct cmd_struct commands[] = {
#endif #endif
{ "inject", cmd_inject, 0 }, { "inject", cmd_inject, 0 },
{ "mem", cmd_mem, 0 }, { "mem", cmd_mem, 0 },
{ "data", cmd_data, 0 },
}; };
struct pager_config { struct pager_config {
......
...@@ -53,6 +53,7 @@ struct record_opts { ...@@ -53,6 +53,7 @@ struct record_opts {
bool sample_time; bool sample_time;
bool period; bool period;
bool sample_intr_regs; bool sample_intr_regs;
bool running_time;
unsigned int freq; unsigned int freq;
unsigned int mmap_pages; unsigned int mmap_pages;
unsigned int user_freq; unsigned int user_freq;
......
...@@ -88,6 +88,8 @@ libperf-$(CONFIG_DWARF) += dwarf-aux.o ...@@ -88,6 +88,8 @@ libperf-$(CONFIG_DWARF) += dwarf-aux.o
libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
libperf-y += scripting-engines/ libperf-y += scripting-engines/
libperf-$(CONFIG_PERF_REGS) += perf_regs.o libperf-$(CONFIG_PERF_REGS) += perf_regs.o
......
This diff is collapsed.
#ifndef __DATA_CONVERT_BT_H
#define __DATA_CONVERT_BT_H
#ifdef HAVE_LIBBABELTRACE_SUPPORT
int bt_convert__perf2ctf(const char *input_name, const char *to_ctf);
#endif /* HAVE_LIBBABELTRACE_SUPPORT */
#endif /* __DATA_CONVERT_BT_H */
...@@ -20,6 +20,7 @@ int verbose; ...@@ -20,6 +20,7 @@ int verbose;
bool dump_trace = false, quiet = false; bool dump_trace = false, quiet = false;
int debug_ordered_events; int debug_ordered_events;
static int redirect_to_stderr; static int redirect_to_stderr;
int debug_data_convert;
static int _eprintf(int level, int var, const char *fmt, va_list args) static int _eprintf(int level, int var, const char *fmt, va_list args)
{ {
...@@ -147,6 +148,7 @@ static struct debug_variable { ...@@ -147,6 +148,7 @@ static struct debug_variable {
{ .name = "verbose", .ptr = &verbose }, { .name = "verbose", .ptr = &verbose },
{ .name = "ordered-events", .ptr = &debug_ordered_events}, { .name = "ordered-events", .ptr = &debug_ordered_events},
{ .name = "stderr", .ptr = &redirect_to_stderr}, { .name = "stderr", .ptr = &redirect_to_stderr},
{ .name = "data-convert", .ptr = &debug_data_convert },
{ .name = NULL, } { .name = NULL, }
}; };
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
extern int verbose; extern int verbose;
extern bool quiet, dump_trace; extern bool quiet, dump_trace;
extern int debug_ordered_events; extern int debug_ordered_events;
extern int debug_data_convert;
#ifndef pr_fmt #ifndef pr_fmt
#define pr_fmt(fmt) fmt #define pr_fmt(fmt) fmt
......
...@@ -615,7 +615,7 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp) ...@@ -615,7 +615,7 @@ size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
else else
s = ""; s = "";
return fprintf(fp, "%s: %s:%d\n", s, event->comm.comm, event->comm.tid); return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
} }
int perf_event__process_comm(struct perf_tool *tool __maybe_unused, int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
......
...@@ -1085,6 +1085,38 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter) ...@@ -1085,6 +1085,38 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
return err; return err;
} }
int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids)
{
char *filter;
int ret = -1;
size_t i;
for (i = 0; i < npids; ++i) {
if (i == 0) {
if (asprintf(&filter, "common_pid != %d", pids[i]) < 0)
return -1;
} else {
char *tmp;
if (asprintf(&tmp, "%s && common_pid != %d", filter, pids[i]) < 0)
goto out_free;
free(filter);
filter = tmp;
}
}
ret = perf_evlist__set_filter(evlist, filter);
out_free:
free(filter);
return ret;
}
int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid)
{
return perf_evlist__set_filter_pids(evlist, 1, &pid);
}
bool perf_evlist__valid_sample_type(struct perf_evlist *evlist) bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
{ {
struct perf_evsel *pos; struct perf_evsel *pos;
......
...@@ -51,6 +51,7 @@ struct perf_evlist { ...@@ -51,6 +51,7 @@ struct perf_evlist {
struct thread_map *threads; struct thread_map *threads;
struct cpu_map *cpus; struct cpu_map *cpus;
struct perf_evsel *selected; struct perf_evsel *selected;
struct events_stats stats;
}; };
struct perf_evsel_str_handler { struct perf_evsel_str_handler {
...@@ -77,6 +78,8 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist, ...@@ -77,6 +78,8 @@ int perf_evlist__add_newtp(struct perf_evlist *evlist,
const char *sys, const char *name, void *handler); const char *sys, const char *name, void *handler);
int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid);
int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids);
struct perf_evsel * struct perf_evsel *
perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id); perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
......
...@@ -734,6 +734,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) ...@@ -734,6 +734,12 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
if (opts->sample_transaction) if (opts->sample_transaction)
perf_evsel__set_sample_bit(evsel, TRANSACTION); perf_evsel__set_sample_bit(evsel, TRANSACTION);
if (opts->running_time) {
evsel->attr.read_format |=
PERF_FORMAT_TOTAL_TIME_ENABLED |
PERF_FORMAT_TOTAL_TIME_RUNNING;
}
/* /*
* XXX see the function comment above * XXX see the function comment above
* *
......
...@@ -166,7 +166,7 @@ static int __ordered_events__flush(struct perf_session *s, ...@@ -166,7 +166,7 @@ static int __ordered_events__flush(struct perf_session *s,
struct ui_progress prog; struct ui_progress prog;
int ret; int ret;
if (!tool->ordered_events || !limit) if (!limit)
return 0; return 0;
if (show_progress) if (show_progress)
...@@ -216,6 +216,9 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool, ...@@ -216,6 +216,9 @@ int ordered_events__flush(struct perf_session *s, struct perf_tool *tool,
}; };
int err; int err;
if (oe->nr_events == 0)
return 0;
switch (how) { switch (how) {
case OE_FLUSH__FINAL: case OE_FLUSH__FINAL:
oe->next_flush = ULLONG_MAX; oe->next_flush = ULLONG_MAX;
......
This diff is collapsed.
...@@ -20,7 +20,6 @@ struct perf_session { ...@@ -20,7 +20,6 @@ struct perf_session {
struct machines machines; struct machines machines;
struct perf_evlist *evlist; struct perf_evlist *evlist;
struct trace_event tevent; struct trace_event tevent;
struct events_stats stats;
bool repipe; bool repipe;
bool one_mmap; bool one_mmap;
void *one_mmap_addr; void *one_mmap_addr;
......
...@@ -269,6 +269,13 @@ void dump_stack(void) ...@@ -269,6 +269,13 @@ void dump_stack(void)
void dump_stack(void) {} void dump_stack(void) {}
#endif #endif
void sighandler_dump_stack(int sig)
{
psignal(sig, "perf");
dump_stack();
exit(sig);
}
void get_term_dimensions(struct winsize *ws) void get_term_dimensions(struct winsize *ws)
{ {
char *s = getenv("LINES"); char *s = getenv("LINES");
......
...@@ -277,6 +277,7 @@ char *ltrim(char *s); ...@@ -277,6 +277,7 @@ char *ltrim(char *s);
char *rtrim(char *s); char *rtrim(char *s);
void dump_stack(void); void dump_stack(void);
void sighandler_dump_stack(int sig);
extern unsigned int page_size; extern unsigned int page_size;
extern int cacheline_size; extern int cacheline_size;
......
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