You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar:
"A number of fixes:
- Fix segfault on perf trace -i perf.data, from Namhyung Kim.
- Fix segfault with --no-mmap-pages, from David Ahern.
- Don't force a refresh during progress update in the TUI, greatly
reducing startup costs, fix from Patrick Palka.
- Fix sw clock event period test wrt not checking if using >
max_sample_freq.
- Handle throttle events in 'object code reading' test, fix from
Adrian Hunter.
- Prevent condition that all sort keys are elided, fix from Namhyung
Kim.
- Round mmap pages to power 2, from David Ahern.
And a number of late arrival changes:
- Add summary only option to 'perf trace', suppressing the decoding
of events, from David Ahern
- 'perf trace --summary' formatting simplifications, from Pekka
Enberg.
- Beautify fifth argument of mmap() as fd, in 'perf trace', from
Namhyung Kim.
- Add direct access to dynamic arrays in libtraceevent, from Steven
Rostedt.
- Synthesize non-exec MMAP records when --data used, allowing the
resolution of data addresses to symbols (global variables, etc), by
Arnaldo Carvalho de Melo.
- Code cleanups by David Ahern and Adrian Hunter"
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits)
tools lib traceevent: Add direct access to dynamic arrays
perf target: Shorten perf_target__ to target__
perf tests: Handle throttle events in 'object code reading' test
perf evlist: Refactor mmap_pages parsing
perf evlist: Round mmap pages to power 2 - v2
perf record: Fix segfault with --no-mmap-pages
perf trace: Add summary only option
perf trace: Simplify '--summary' output
perf trace: Change syscall summary duration order
perf tests: Compensate lower sample freq with longer test loop
perf trace: Fix segfault on perf trace -i perf.data
perf trace: Separate tp syscall field caching into init routine to be reused
perf trace: Beautify fifth argument of mmap() as fd
perf tests: Use lower sample_freq in sw clock event period test
perf tests: Check return of perf_evlist__open sw clock event period test
perf record: Move existing write_output into helper function
perf record: Use correct return type for write()
perf tools: Prevent condition that all sort keys are elided
perf machine: Simplify synthesize_threads method
perf machine: Introduce synthesize_threads method out of open coded equivalent
...
This commit is contained in:
@@ -3435,6 +3435,19 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
|
||||
goto out_warning_op;
|
||||
}
|
||||
break;
|
||||
case PRINT_DYNAMIC_ARRAY:
|
||||
/* Without [], we pass the address to the dynamic data */
|
||||
offset = pevent_read_number(pevent,
|
||||
data + arg->dynarray.field->offset,
|
||||
arg->dynarray.field->size);
|
||||
/*
|
||||
* The actual length of the dynamic array is stored
|
||||
* in the top half of the field, and the offset
|
||||
* is in the bottom half of the 32 bit field.
|
||||
*/
|
||||
offset &= 0xffff;
|
||||
val = (unsigned long long)(data + offset);
|
||||
break;
|
||||
default: /* not sure what to do there */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -93,9 +93,15 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
|
||||
--comm::
|
||||
Show process COMM right beside its ID, on by default, disable with --no-comm.
|
||||
|
||||
-s::
|
||||
--summary::
|
||||
Show a summary of syscalls by thread with min, max, and average times (in
|
||||
msec) and relative stddev.
|
||||
Show only a summary of syscalls by thread with min, max, and average times
|
||||
(in msec) and relative stddev.
|
||||
|
||||
-S::
|
||||
--with-summary::
|
||||
Show all syscalls followed by a summary by thread with min, max, and
|
||||
average times (in msec) and relative stddev.
|
||||
|
||||
--tool_stats::
|
||||
Show tool stats such as number of times fd->pathname was discovered thru
|
||||
|
||||
@@ -1510,13 +1510,13 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
|
||||
/*
|
||||
* target related setups
|
||||
*/
|
||||
err = perf_target__validate(&kvm->opts.target);
|
||||
err = target__validate(&kvm->opts.target);
|
||||
if (err) {
|
||||
perf_target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ);
|
||||
target__strerror(&kvm->opts.target, err, errbuf, BUFSIZ);
|
||||
ui__warning("%s", errbuf);
|
||||
}
|
||||
|
||||
if (perf_target__none(&kvm->opts.target))
|
||||
if (target__none(&kvm->opts.target))
|
||||
kvm->opts.target.system_wide = true;
|
||||
|
||||
|
||||
@@ -1544,18 +1544,8 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
|
||||
}
|
||||
kvm->session->evlist = kvm->evlist;
|
||||
perf_session__set_id_hdr_size(kvm->session);
|
||||
|
||||
|
||||
if (perf_target__has_task(&kvm->opts.target))
|
||||
perf_event__synthesize_thread_map(&kvm->tool,
|
||||
kvm->evlist->threads,
|
||||
perf_event__process,
|
||||
&kvm->session->machines.host);
|
||||
else
|
||||
perf_event__synthesize_threads(&kvm->tool, perf_event__process,
|
||||
&kvm->session->machines.host);
|
||||
|
||||
|
||||
machine__synthesize_threads(&kvm->session->machines.host, &kvm->opts.target,
|
||||
kvm->evlist->threads, false);
|
||||
err = kvm_live_open_events(kvm);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
+16
-19
@@ -76,12 +76,12 @@ struct perf_record {
|
||||
long samples;
|
||||
};
|
||||
|
||||
static int write_output(struct perf_record *rec, void *buf, size_t size)
|
||||
static int do_write_output(struct perf_record *rec, void *buf, size_t size)
|
||||
{
|
||||
struct perf_data_file *file = &rec->file;
|
||||
|
||||
while (size) {
|
||||
int ret = write(file->fd, buf, size);
|
||||
ssize_t ret = write(file->fd, buf, size);
|
||||
|
||||
if (ret < 0) {
|
||||
pr_err("failed to write perf data, error: %m\n");
|
||||
@@ -97,6 +97,11 @@ static int write_output(struct perf_record *rec, void *buf, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_output(struct perf_record *rec, void *buf, size_t size)
|
||||
{
|
||||
return do_write_output(rec, buf, size);
|
||||
}
|
||||
|
||||
static int process_synthesized_event(struct perf_tool *tool,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample __maybe_unused,
|
||||
@@ -480,16 +485,8 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||
perf_event__synthesize_guest_os, tool);
|
||||
}
|
||||
|
||||
if (perf_target__has_task(&opts->target))
|
||||
err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
|
||||
process_synthesized_event,
|
||||
machine);
|
||||
else if (perf_target__has_cpu(&opts->target))
|
||||
err = perf_event__synthesize_threads(tool, process_synthesized_event,
|
||||
machine);
|
||||
else /* command specified */
|
||||
err = 0;
|
||||
|
||||
err = __machine__synthesize_threads(machine, tool, &opts->target, evsel_list->threads,
|
||||
process_synthesized_event, opts->sample_address);
|
||||
if (err != 0)
|
||||
goto out_delete_session;
|
||||
|
||||
@@ -509,7 +506,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||
* (apart from group members) have enable_on_exec=1 set,
|
||||
* so don't spoil it by prematurely enabling them.
|
||||
*/
|
||||
if (!perf_target__none(&opts->target))
|
||||
if (!target__none(&opts->target))
|
||||
perf_evlist__enable(evsel_list);
|
||||
|
||||
/*
|
||||
@@ -538,7 +535,7 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
|
||||
* die with the process and we wait for that. Thus no need to
|
||||
* disable events in this case.
|
||||
*/
|
||||
if (done && !disabled && !perf_target__none(&opts->target)) {
|
||||
if (done && !disabled && !target__none(&opts->target)) {
|
||||
perf_evlist__disable(evsel_list);
|
||||
disabled = true;
|
||||
}
|
||||
@@ -909,7 +906,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
|
||||
argc = parse_options(argc, argv, record_options, record_usage,
|
||||
PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
if (!argc && perf_target__none(&rec->opts.target))
|
||||
if (!argc && target__none(&rec->opts.target))
|
||||
usage_with_options(record_usage, record_options);
|
||||
|
||||
if (nr_cgroups && !rec->opts.target.system_wide) {
|
||||
@@ -939,17 +936,17 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
goto out_symbol_exit;
|
||||
}
|
||||
|
||||
err = perf_target__validate(&rec->opts.target);
|
||||
err = target__validate(&rec->opts.target);
|
||||
if (err) {
|
||||
perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
|
||||
target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
|
||||
ui__warning("%s", errbuf);
|
||||
}
|
||||
|
||||
err = perf_target__parse_uid(&rec->opts.target);
|
||||
err = target__parse_uid(&rec->opts.target);
|
||||
if (err) {
|
||||
int saved_errno = errno;
|
||||
|
||||
perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
|
||||
target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
|
||||
ui__error("%s", errbuf);
|
||||
|
||||
err = -saved_errno;
|
||||
|
||||
+10
-11
@@ -108,7 +108,7 @@ enum {
|
||||
|
||||
static struct perf_evlist *evsel_list;
|
||||
|
||||
static struct perf_target target = {
|
||||
static struct target target = {
|
||||
.uid = UINT_MAX,
|
||||
};
|
||||
|
||||
@@ -294,11 +294,10 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
|
||||
|
||||
attr->inherit = !no_inherit;
|
||||
|
||||
if (perf_target__has_cpu(&target))
|
||||
if (target__has_cpu(&target))
|
||||
return perf_evsel__open_per_cpu(evsel, perf_evsel__cpus(evsel));
|
||||
|
||||
if (!perf_target__has_task(&target) &&
|
||||
perf_evsel__is_group_leader(evsel)) {
|
||||
if (!target__has_task(&target) && perf_evsel__is_group_leader(evsel)) {
|
||||
attr->disabled = 1;
|
||||
if (!initial_delay)
|
||||
attr->enable_on_exec = 1;
|
||||
@@ -1236,7 +1235,7 @@ static void print_stat(int argc, const char **argv)
|
||||
fprintf(output, "\'system wide");
|
||||
else if (target.cpu_list)
|
||||
fprintf(output, "\'CPU(s) %s", target.cpu_list);
|
||||
else if (!perf_target__has_task(&target)) {
|
||||
else if (!target__has_task(&target)) {
|
||||
fprintf(output, "\'%s", argv[0]);
|
||||
for (i = 1; i < argc; i++)
|
||||
fprintf(output, " %s", argv[i]);
|
||||
@@ -1667,7 +1666,7 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
} else if (big_num_opt == 0) /* User passed --no-big-num */
|
||||
big_num = false;
|
||||
|
||||
if (!argc && perf_target__none(&target))
|
||||
if (!argc && target__none(&target))
|
||||
usage_with_options(stat_usage, options);
|
||||
|
||||
if (run_count < 0) {
|
||||
@@ -1680,8 +1679,8 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
}
|
||||
|
||||
/* no_aggr, cgroup are for system-wide only */
|
||||
if ((aggr_mode != AGGR_GLOBAL || nr_cgroups)
|
||||
&& !perf_target__has_cpu(&target)) {
|
||||
if ((aggr_mode != AGGR_GLOBAL || nr_cgroups) &&
|
||||
!target__has_cpu(&target)) {
|
||||
fprintf(stderr, "both cgroup and no-aggregation "
|
||||
"modes only available in system-wide mode\n");
|
||||
|
||||
@@ -1694,14 +1693,14 @@ int cmd_stat(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
if (add_default_attributes())
|
||||
goto out;
|
||||
|
||||
perf_target__validate(&target);
|
||||
target__validate(&target);
|
||||
|
||||
if (perf_evlist__create_maps(evsel_list, &target) < 0) {
|
||||
if (perf_target__has_task(&target)) {
|
||||
if (target__has_task(&target)) {
|
||||
pr_err("Problems finding threads of monitor\n");
|
||||
parse_options_usage(stat_usage, options, "p", 1);
|
||||
parse_options_usage(NULL, options, "t", 1);
|
||||
} else if (perf_target__has_cpu(&target)) {
|
||||
} else if (target__has_cpu(&target)) {
|
||||
perror("failed to parse CPUs map");
|
||||
parse_options_usage(stat_usage, options, "C", 1);
|
||||
parse_options_usage(NULL, options, "a", 1);
|
||||
|
||||
@@ -950,14 +950,8 @@ static int __cmd_top(struct perf_top *top)
|
||||
if (ret)
|
||||
goto out_delete;
|
||||
|
||||
if (perf_target__has_task(&opts->target))
|
||||
perf_event__synthesize_thread_map(&top->tool, top->evlist->threads,
|
||||
perf_event__process,
|
||||
&top->session->machines.host);
|
||||
else
|
||||
perf_event__synthesize_threads(&top->tool, perf_event__process,
|
||||
&top->session->machines.host);
|
||||
|
||||
machine__synthesize_threads(&top->session->machines.host, &opts->target,
|
||||
top->evlist->threads, false);
|
||||
ret = perf_top__start_counters(top);
|
||||
if (ret)
|
||||
goto out_delete;
|
||||
@@ -973,7 +967,7 @@ static int __cmd_top(struct perf_top *top)
|
||||
* XXX 'top' still doesn't start workloads like record, trace, but should,
|
||||
* so leave the check here.
|
||||
*/
|
||||
if (!perf_target__none(&opts->target))
|
||||
if (!target__none(&opts->target))
|
||||
perf_evlist__enable(top->evlist);
|
||||
|
||||
/* Wait for a minimal set of events before starting the snapshot */
|
||||
@@ -1059,7 +1053,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
.sym_pcnt_filter = 5,
|
||||
};
|
||||
struct perf_record_opts *opts = &top.record_opts;
|
||||
struct perf_target *target = &opts->target;
|
||||
struct target *target = &opts->target;
|
||||
const struct option options[] = {
|
||||
OPT_CALLBACK('e', "event", &top.evlist, "event",
|
||||
"event selector. use 'perf list' to list available events",
|
||||
@@ -1175,24 +1169,24 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
|
||||
setup_browser(false);
|
||||
|
||||
status = perf_target__validate(target);
|
||||
status = target__validate(target);
|
||||
if (status) {
|
||||
perf_target__strerror(target, status, errbuf, BUFSIZ);
|
||||
target__strerror(target, status, errbuf, BUFSIZ);
|
||||
ui__warning("%s", errbuf);
|
||||
}
|
||||
|
||||
status = perf_target__parse_uid(target);
|
||||
status = target__parse_uid(target);
|
||||
if (status) {
|
||||
int saved_errno = errno;
|
||||
|
||||
perf_target__strerror(target, status, errbuf, BUFSIZ);
|
||||
target__strerror(target, status, errbuf, BUFSIZ);
|
||||
ui__error("%s", errbuf);
|
||||
|
||||
status = -saved_errno;
|
||||
goto out_delete_evlist;
|
||||
}
|
||||
|
||||
if (perf_target__none(target))
|
||||
if (target__none(target))
|
||||
target->system_wide = true;
|
||||
|
||||
if (perf_evlist__create_maps(top.evlist, target) < 0)
|
||||
|
||||
+80
-63
@@ -149,21 +149,32 @@ static void perf_evsel__delete_priv(struct perf_evsel *evsel)
|
||||
perf_evsel__delete(evsel);
|
||||
}
|
||||
|
||||
static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction,
|
||||
void *handler, int idx)
|
||||
static int perf_evsel__init_syscall_tp(struct perf_evsel *evsel, void *handler)
|
||||
{
|
||||
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;
|
||||
|
||||
evsel->priv = malloc(sizeof(struct syscall_tp));
|
||||
if (evsel->priv != NULL) {
|
||||
if (perf_evsel__init_sc_tp_uint_field(evsel, id))
|
||||
goto out_delete;
|
||||
|
||||
evsel->handler = handler;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOMEM;
|
||||
|
||||
out_delete:
|
||||
free(evsel->priv);
|
||||
evsel->priv = NULL;
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void *handler)
|
||||
{
|
||||
struct perf_evsel *evsel = perf_evsel__newtp("raw_syscalls", direction);
|
||||
|
||||
if (evsel) {
|
||||
if (perf_evsel__init_syscall_tp(evsel, handler))
|
||||
goto out_delete;
|
||||
}
|
||||
|
||||
return evsel;
|
||||
@@ -186,17 +197,16 @@ static int perf_evlist__add_syscall_newtp(struct perf_evlist *evlist,
|
||||
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++);
|
||||
sys_enter = perf_evsel__syscall_newtp("sys_enter", sys_enter_handler);
|
||||
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++);
|
||||
sys_exit = perf_evsel__syscall_newtp("sys_exit", sys_exit_handler);
|
||||
if (sys_exit == NULL)
|
||||
goto out_delete_sys_enter;
|
||||
|
||||
@@ -953,7 +963,8 @@ static struct syscall_fmt {
|
||||
{ .name = "mmap", .hexret = true,
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* addr */
|
||||
[2] = SCA_MMAP_PROT, /* prot */
|
||||
[3] = SCA_MMAP_FLAGS, /* flags */ }, },
|
||||
[3] = SCA_MMAP_FLAGS, /* flags */
|
||||
[4] = SCA_FD, /* fd */ }, },
|
||||
{ .name = "mprotect", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* start */
|
||||
[2] = SCA_MMAP_PROT, /* prot */ }, },
|
||||
@@ -1157,6 +1168,7 @@ struct trace {
|
||||
bool sched;
|
||||
bool multiple_threads;
|
||||
bool summary;
|
||||
bool summary_only;
|
||||
bool show_comm;
|
||||
bool show_tool_stats;
|
||||
double duration_filter;
|
||||
@@ -1342,15 +1354,8 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
|
||||
if (trace->host == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
if (perf_target__has_task(&trace->opts.target)) {
|
||||
err = perf_event__synthesize_thread_map(&trace->tool, evlist->threads,
|
||||
trace__tool_process,
|
||||
trace->host);
|
||||
} else {
|
||||
err = perf_event__synthesize_threads(&trace->tool, trace__tool_process,
|
||||
trace->host);
|
||||
}
|
||||
|
||||
err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
|
||||
evlist->threads, trace__tool_process, false);
|
||||
if (err)
|
||||
symbol__exit();
|
||||
|
||||
@@ -1607,7 +1612,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
|
||||
args, trace, thread);
|
||||
|
||||
if (!strcmp(sc->name, "exit_group") || !strcmp(sc->name, "exit")) {
|
||||
if (!trace->duration_filter) {
|
||||
if (!trace->duration_filter && !trace->summary_only) {
|
||||
trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
|
||||
fprintf(trace->output, "%-70s\n", ttrace->entry_str);
|
||||
}
|
||||
@@ -1660,6 +1665,9 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
|
||||
} else if (trace->duration_filter)
|
||||
goto out;
|
||||
|
||||
if (trace->summary_only)
|
||||
goto out;
|
||||
|
||||
trace__fprintf_entry_head(trace, thread, duration, sample->time, trace->output);
|
||||
|
||||
if (ttrace->entry_pending) {
|
||||
@@ -1762,16 +1770,6 @@ static int trace__process_sample(struct perf_tool *tool,
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool
|
||||
perf_session__has_tp(struct perf_session *session, const char *name)
|
||||
{
|
||||
struct perf_evsel *evsel;
|
||||
|
||||
evsel = perf_evlist__find_tracepoint_by_name(session->evlist, name);
|
||||
|
||||
return evsel != NULL;
|
||||
}
|
||||
|
||||
static int parse_target_str(struct trace *trace)
|
||||
{
|
||||
if (trace->opts.target.pid) {
|
||||
@@ -1824,8 +1822,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
|
||||
|
||||
static void perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
|
||||
{
|
||||
struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname",
|
||||
evlist->nr_entries);
|
||||
struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
|
||||
if (evsel == NULL)
|
||||
return;
|
||||
|
||||
@@ -2009,8 +2006,6 @@ out_error:
|
||||
static int trace__replay(struct trace *trace)
|
||||
{
|
||||
const struct perf_evsel_str_handler handlers[] = {
|
||||
{ "raw_syscalls:sys_enter", trace__sys_enter, },
|
||||
{ "raw_syscalls:sys_exit", trace__sys_exit, },
|
||||
{ "probe:vfs_getname", trace__vfs_getname, },
|
||||
};
|
||||
struct perf_data_file file = {
|
||||
@@ -2018,6 +2013,7 @@ static int trace__replay(struct trace *trace)
|
||||
.mode = PERF_DATA_MODE_READ,
|
||||
};
|
||||
struct perf_session *session;
|
||||
struct perf_evsel *evsel;
|
||||
int err = -1;
|
||||
|
||||
trace->tool.sample = trace__process_sample;
|
||||
@@ -2049,13 +2045,29 @@ static int trace__replay(struct trace *trace)
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
if (!perf_session__has_tp(session, "raw_syscalls:sys_enter")) {
|
||||
pr_err("Data file does not have raw_syscalls:sys_enter events\n");
|
||||
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
|
||||
"raw_syscalls:sys_enter");
|
||||
if (evsel == NULL) {
|
||||
pr_err("Data file does not have raw_syscalls:sys_enter event\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!perf_session__has_tp(session, "raw_syscalls:sys_exit")) {
|
||||
pr_err("Data file does not have raw_syscalls:sys_exit events\n");
|
||||
if (perf_evsel__init_syscall_tp(evsel, trace__sys_enter) < 0 ||
|
||||
perf_evsel__init_sc_tp_ptr_field(evsel, args)) {
|
||||
pr_err("Error during initialize raw_syscalls:sys_enter event\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
evsel = perf_evlist__find_tracepoint_by_name(session->evlist,
|
||||
"raw_syscalls:sys_exit");
|
||||
if (evsel == NULL) {
|
||||
pr_err("Data file does not have raw_syscalls:sys_exit event\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (perf_evsel__init_syscall_tp(evsel, trace__sys_exit) < 0 ||
|
||||
perf_evsel__init_sc_tp_uint_field(evsel, ret)) {
|
||||
pr_err("Error during initialize raw_syscalls:sys_exit event\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2082,12 +2094,7 @@ static size_t trace__fprintf_threads_header(FILE *fp)
|
||||
{
|
||||
size_t printed;
|
||||
|
||||
printed = fprintf(fp, "\n _____________________________________________________________________________\n");
|
||||
printed += fprintf(fp, " __) Summary of events (__\n\n");
|
||||
printed += fprintf(fp, " [ task - pid ] [ events ] [ ratio ] [ runtime ]\n");
|
||||
printed += fprintf(fp, " syscall count min max avg stddev\n");
|
||||
printed += fprintf(fp, " msec msec msec %%\n");
|
||||
printed += fprintf(fp, " _____________________________________________________________________________\n\n");
|
||||
printed = fprintf(fp, "\n Summary of events:\n\n");
|
||||
|
||||
return printed;
|
||||
}
|
||||
@@ -2105,6 +2112,10 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
|
||||
|
||||
printed += fprintf(fp, "\n");
|
||||
|
||||
printed += fprintf(fp, " msec/call\n");
|
||||
printed += fprintf(fp, " syscall calls min avg max stddev\n");
|
||||
printed += fprintf(fp, " --------------- -------- -------- -------- -------- ------\n");
|
||||
|
||||
/* each int_node is a syscall */
|
||||
while (inode) {
|
||||
stats = inode->priv;
|
||||
@@ -2119,10 +2130,10 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
|
||||
avg /= NSEC_PER_MSEC;
|
||||
|
||||
sc = &trace->syscalls.table[inode->i];
|
||||
printed += fprintf(fp, "%24s %14s : ", "", sc->name);
|
||||
printed += fprintf(fp, "%5" PRIu64 " %8.3f %8.3f",
|
||||
n, min, max);
|
||||
printed += fprintf(fp, " %8.3f %6.2f\n", avg, pct);
|
||||
printed += fprintf(fp, " %-15s", sc->name);
|
||||
printed += fprintf(fp, " %8" PRIu64 " %8.3f %8.3f",
|
||||
n, min, avg);
|
||||
printed += fprintf(fp, " %8.3f %6.2f\n", max, pct);
|
||||
}
|
||||
|
||||
inode = intlist__next(inode);
|
||||
@@ -2163,10 +2174,10 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
|
||||
else if (ratio > 5.0)
|
||||
color = PERF_COLOR_YELLOW;
|
||||
|
||||
printed += color_fprintf(fp, color, "%20s", thread__comm_str(thread));
|
||||
printed += fprintf(fp, " - %-5d :%11lu [", thread->tid, ttrace->nr_events);
|
||||
printed += color_fprintf(fp, color, "%5.1f%%", ratio);
|
||||
printed += fprintf(fp, " ] %10.3f ms\n", ttrace->runtime_ms);
|
||||
printed += color_fprintf(fp, color, " %s (%d), ", thread__comm_str(thread), thread->tid);
|
||||
printed += fprintf(fp, "%lu events, ", ttrace->nr_events);
|
||||
printed += color_fprintf(fp, color, "%.1f%%", ratio);
|
||||
printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
|
||||
printed += thread__dump_stats(ttrace, trace, fp);
|
||||
|
||||
data->printed += printed;
|
||||
@@ -2275,8 +2286,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
|
||||
OPT_BOOLEAN('T', "time", &trace.full_time,
|
||||
"Show full timestamp, not time relative to first start"),
|
||||
OPT_BOOLEAN(0, "summary", &trace.summary,
|
||||
"Show syscall summary with statistics"),
|
||||
OPT_BOOLEAN('s', "summary", &trace.summary_only,
|
||||
"Show only syscall summary with statistics"),
|
||||
OPT_BOOLEAN('S', "with-summary", &trace.summary,
|
||||
"Show all syscalls and summary with statistics"),
|
||||
OPT_END()
|
||||
};
|
||||
int err;
|
||||
@@ -2287,6 +2300,10 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
|
||||
argc = parse_options(argc, argv, trace_options, trace_usage, 0);
|
||||
|
||||
/* summary_only implies summary option, but don't overwrite summary if set */
|
||||
if (trace.summary_only)
|
||||
trace.summary = trace.summary_only;
|
||||
|
||||
if (output_name != NULL) {
|
||||
err = trace__open_output(&trace, output_name);
|
||||
if (err < 0) {
|
||||
@@ -2310,21 +2327,21 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
|
||||
}
|
||||
}
|
||||
|
||||
err = perf_target__validate(&trace.opts.target);
|
||||
err = target__validate(&trace.opts.target);
|
||||
if (err) {
|
||||
perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
|
||||
target__strerror(&trace.opts.target, err, bf, sizeof(bf));
|
||||
fprintf(trace.output, "%s", bf);
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
err = perf_target__parse_uid(&trace.opts.target);
|
||||
err = target__parse_uid(&trace.opts.target);
|
||||
if (err) {
|
||||
perf_target__strerror(&trace.opts.target, err, bf, sizeof(bf));
|
||||
target__strerror(&trace.opts.target, err, bf, sizeof(bf));
|
||||
fprintf(trace.output, "%s", bf);
|
||||
goto out_close;
|
||||
}
|
||||
|
||||
if (!argc && perf_target__none(&trace.opts.target))
|
||||
if (!argc && target__none(&trace.opts.target))
|
||||
trace.opts.target.system_wide = true;
|
||||
|
||||
if (input_name)
|
||||
|
||||
+1
-1
@@ -248,7 +248,7 @@ enum perf_call_graph_mode {
|
||||
};
|
||||
|
||||
struct perf_record_opts {
|
||||
struct perf_target target;
|
||||
struct target target;
|
||||
int call_graph;
|
||||
bool group;
|
||||
bool inherit_stat;
|
||||
|
||||
@@ -275,8 +275,19 @@ static int process_event(struct machine *machine, struct perf_evlist *evlist,
|
||||
if (event->header.type == PERF_RECORD_SAMPLE)
|
||||
return process_sample_event(machine, evlist, event, state);
|
||||
|
||||
if (event->header.type < PERF_RECORD_MAX)
|
||||
return machine__process_event(machine, event, NULL);
|
||||
if (event->header.type == PERF_RECORD_THROTTLE ||
|
||||
event->header.type == PERF_RECORD_UNTHROTTLE)
|
||||
return 0;
|
||||
|
||||
if (event->header.type < PERF_RECORD_MAX) {
|
||||
int ret;
|
||||
|
||||
ret = machine__process_event(machine, event, NULL);
|
||||
if (ret < 0)
|
||||
pr_debug("machine__process_event failed, event type %u\n",
|
||||
event->header.type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -441,7 +452,7 @@ static int do_test_code_reading(bool try_kcore)
|
||||
}
|
||||
|
||||
ret = perf_event__synthesize_thread_map(NULL, threads,
|
||||
perf_event__process, machine);
|
||||
perf_event__process, machine, false);
|
||||
if (ret < 0) {
|
||||
pr_debug("perf_event__synthesize_thread_map failed\n");
|
||||
goto out_err;
|
||||
|
||||
@@ -32,7 +32,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
|
||||
|
||||
int test__perf_evsel__tp_sched_test(void)
|
||||
{
|
||||
struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch", 0);
|
||||
struct perf_evsel *evsel = perf_evsel__newtp("sched", "sched_switch");
|
||||
int ret = 0;
|
||||
|
||||
if (evsel == NULL) {
|
||||
@@ -63,7 +63,7 @@ int test__perf_evsel__tp_sched_test(void)
|
||||
|
||||
perf_evsel__delete(evsel);
|
||||
|
||||
evsel = perf_evsel__newtp("sched", "sched_wakeup", 0);
|
||||
evsel = perf_evsel__newtp("sched", "sched_wakeup");
|
||||
|
||||
if (perf_evsel__test_field(evsel, "comm", 16, true))
|
||||
ret = -1;
|
||||
|
||||
@@ -65,7 +65,7 @@ int test__basic_mmap(void)
|
||||
char name[64];
|
||||
|
||||
snprintf(name, sizeof(name), "sys_enter_%s", syscall_names[i]);
|
||||
evsels[i] = perf_evsel__newtp("syscalls", name, i);
|
||||
evsels[i] = perf_evsel__newtp("syscalls", name);
|
||||
if (evsels[i] == NULL) {
|
||||
pr_debug("perf_evsel__new\n");
|
||||
goto out_free_evlist;
|
||||
|
||||
@@ -26,7 +26,7 @@ int test__open_syscall_event_on_all_cpus(void)
|
||||
|
||||
CPU_ZERO(&cpu_set);
|
||||
|
||||
evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
|
||||
evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
|
||||
if (evsel == NULL) {
|
||||
pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
|
||||
goto out_thread_map_delete;
|
||||
|
||||
@@ -27,7 +27,7 @@ int test__syscall_open_tp_fields(void)
|
||||
goto out;
|
||||
}
|
||||
|
||||
evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
|
||||
evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
|
||||
if (evsel == NULL) {
|
||||
pr_debug("%s: perf_evsel__newtp\n", __func__);
|
||||
goto out_delete_evlist;
|
||||
|
||||
@@ -15,7 +15,7 @@ int test__open_syscall_event(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
evsel = perf_evsel__newtp("syscalls", "sys_enter_open", 0);
|
||||
evsel = perf_evsel__newtp("syscalls", "sys_enter_open");
|
||||
if (evsel == NULL) {
|
||||
pr_debug("is debugfs mounted on /sys/kernel/debug?\n");
|
||||
goto out_thread_map_delete;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "util/cpumap.h"
|
||||
#include "util/thread_map.h"
|
||||
|
||||
#define NR_LOOPS 1000000
|
||||
#define NR_LOOPS 10000000
|
||||
|
||||
/*
|
||||
* This test will open software clock events (cpu-clock, task-clock)
|
||||
@@ -34,7 +34,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
|
||||
.freq = 1,
|
||||
};
|
||||
|
||||
attr.sample_freq = 10000;
|
||||
attr.sample_freq = 500;
|
||||
|
||||
evlist = perf_evlist__new();
|
||||
if (evlist == NULL) {
|
||||
@@ -42,7 +42,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
|
||||
return -1;
|
||||
}
|
||||
|
||||
evsel = perf_evsel__new(&attr, 0);
|
||||
evsel = perf_evsel__new(&attr);
|
||||
if (evsel == NULL) {
|
||||
pr_debug("perf_evsel__new\n");
|
||||
goto out_free_evlist;
|
||||
@@ -57,7 +57,14 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
|
||||
goto out_delete_maps;
|
||||
}
|
||||
|
||||
perf_evlist__open(evlist);
|
||||
if (perf_evlist__open(evlist)) {
|
||||
const char *knob = "/proc/sys/kernel/perf_event_max_sample_rate";
|
||||
|
||||
err = -errno;
|
||||
pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
|
||||
strerror(errno), knob, (u64)attr.sample_freq);
|
||||
goto out_delete_maps;
|
||||
}
|
||||
|
||||
err = perf_evlist__mmap(evlist, 128, true);
|
||||
if (err < 0) {
|
||||
|
||||
@@ -28,7 +28,7 @@ int test__task_exit(void)
|
||||
union perf_event *event;
|
||||
struct perf_evsel *evsel;
|
||||
struct perf_evlist *evlist;
|
||||
struct perf_target target = {
|
||||
struct target target = {
|
||||
.uid = UINT_MAX,
|
||||
.uses_mmap = true,
|
||||
};
|
||||
|
||||
@@ -18,13 +18,14 @@ static void tui_progress__update(struct ui_progress *p)
|
||||
if (p->total == 0)
|
||||
return;
|
||||
|
||||
ui__refresh_dimensions(true);
|
||||
ui__refresh_dimensions(false);
|
||||
pthread_mutex_lock(&ui__lock);
|
||||
y = SLtt_Screen_Rows / 2 - 2;
|
||||
SLsmg_set_color(0);
|
||||
SLsmg_draw_box(y, 0, 3, SLtt_Screen_Cols);
|
||||
SLsmg_gotorc(y++, 1);
|
||||
SLsmg_write_string((char *)p->title);
|
||||
SLsmg_fill_region(y, 1, 1, SLtt_Screen_Cols - 2, ' ');
|
||||
SLsmg_set_color(HE_COLORSET_SELECTED);
|
||||
bar = ((SLtt_Screen_Cols - 2) * p->curr) / p->total;
|
||||
SLsmg_fill_region(y, 1, 1, bar, ' ');
|
||||
|
||||
+30
-20
@@ -170,7 +170,8 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
|
||||
union perf_event *event,
|
||||
pid_t pid, pid_t tgid,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine)
|
||||
struct machine *machine,
|
||||
bool mmap_data)
|
||||
{
|
||||
char filename[PATH_MAX];
|
||||
FILE *fp;
|
||||
@@ -188,10 +189,6 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
|
||||
}
|
||||
|
||||
event->header.type = PERF_RECORD_MMAP;
|
||||
/*
|
||||
* Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
|
||||
*/
|
||||
event->header.misc = PERF_RECORD_MISC_USER;
|
||||
|
||||
while (1) {
|
||||
char bf[BUFSIZ];
|
||||
@@ -215,9 +212,17 @@ static int perf_event__synthesize_mmap_events(struct perf_tool *tool,
|
||||
|
||||
if (n != 5)
|
||||
continue;
|
||||
/*
|
||||
* Just like the kernel, see __perf_event_mmap in kernel/perf_event.c
|
||||
*/
|
||||
event->header.misc = PERF_RECORD_MISC_USER;
|
||||
|
||||
if (prot[2] != 'x')
|
||||
continue;
|
||||
if (prot[2] != 'x') {
|
||||
if (!mmap_data || prot[0] != 'r')
|
||||
continue;
|
||||
|
||||
event->header.misc |= PERF_RECORD_MISC_MMAP_DATA;
|
||||
}
|
||||
|
||||
if (!strcmp(execname, ""))
|
||||
strcpy(execname, anonstr);
|
||||
@@ -304,20 +309,21 @@ static int __event__synthesize_thread(union perf_event *comm_event,
|
||||
pid_t pid, int full,
|
||||
perf_event__handler_t process,
|
||||
struct perf_tool *tool,
|
||||
struct machine *machine)
|
||||
struct machine *machine, bool mmap_data)
|
||||
{
|
||||
pid_t tgid = perf_event__synthesize_comm(tool, comm_event, pid, full,
|
||||
process, machine);
|
||||
if (tgid == -1)
|
||||
return -1;
|
||||
return perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
|
||||
process, machine);
|
||||
process, machine, mmap_data);
|
||||
}
|
||||
|
||||
int perf_event__synthesize_thread_map(struct perf_tool *tool,
|
||||
struct thread_map *threads,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine)
|
||||
struct machine *machine,
|
||||
bool mmap_data)
|
||||
{
|
||||
union perf_event *comm_event, *mmap_event;
|
||||
int err = -1, thread, j;
|
||||
@@ -334,7 +340,8 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
|
||||
for (thread = 0; thread < threads->nr; ++thread) {
|
||||
if (__event__synthesize_thread(comm_event, mmap_event,
|
||||
threads->map[thread], 0,
|
||||
process, tool, machine)) {
|
||||
process, tool, machine,
|
||||
mmap_data)) {
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
@@ -356,10 +363,10 @@ int perf_event__synthesize_thread_map(struct perf_tool *tool,
|
||||
|
||||
/* if not, generate events for it */
|
||||
if (need_leader &&
|
||||
__event__synthesize_thread(comm_event,
|
||||
mmap_event,
|
||||
comm_event->comm.pid, 0,
|
||||
process, tool, machine)) {
|
||||
__event__synthesize_thread(comm_event, mmap_event,
|
||||
comm_event->comm.pid, 0,
|
||||
process, tool, machine,
|
||||
mmap_data)) {
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
@@ -374,7 +381,7 @@ out:
|
||||
|
||||
int perf_event__synthesize_threads(struct perf_tool *tool,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine)
|
||||
struct machine *machine, bool mmap_data)
|
||||
{
|
||||
DIR *proc;
|
||||
struct dirent dirent, *next;
|
||||
@@ -404,7 +411,7 @@ int perf_event__synthesize_threads(struct perf_tool *tool,
|
||||
* one thread couldn't be synthesized.
|
||||
*/
|
||||
__event__synthesize_thread(comm_event, mmap_event, pid, 1,
|
||||
process, tool, machine);
|
||||
process, tool, machine, mmap_data);
|
||||
}
|
||||
|
||||
err = 0;
|
||||
@@ -528,19 +535,22 @@ int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
|
||||
|
||||
size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
|
||||
{
|
||||
return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %s\n",
|
||||
return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64 "]: %c %s\n",
|
||||
event->mmap.pid, event->mmap.tid, event->mmap.start,
|
||||
event->mmap.len, event->mmap.pgoff, event->mmap.filename);
|
||||
event->mmap.len, event->mmap.pgoff,
|
||||
(event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
|
||||
event->mmap.filename);
|
||||
}
|
||||
|
||||
size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
|
||||
{
|
||||
return fprintf(fp, " %d/%d: [%#" PRIx64 "(%#" PRIx64 ") @ %#" PRIx64
|
||||
" %02x:%02x %"PRIu64" %"PRIu64"]: %s\n",
|
||||
" %02x:%02x %"PRIu64" %"PRIu64"]: %c %s\n",
|
||||
event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
|
||||
event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
|
||||
event->mmap2.min, event->mmap2.ino,
|
||||
event->mmap2.ino_generation,
|
||||
(event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
|
||||
event->mmap2.filename);
|
||||
}
|
||||
|
||||
|
||||
@@ -208,10 +208,10 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool,
|
||||
int perf_event__synthesize_thread_map(struct perf_tool *tool,
|
||||
struct thread_map *threads,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine);
|
||||
struct machine *machine, bool mmap_data);
|
||||
int perf_event__synthesize_threads(struct perf_tool *tool,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine);
|
||||
struct machine *machine, bool mmap_data);
|
||||
int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine,
|
||||
|
||||
+43
-30
@@ -117,6 +117,8 @@ void perf_evlist__delete(struct perf_evlist *evlist)
|
||||
void perf_evlist__add(struct perf_evlist *evlist, struct perf_evsel *entry)
|
||||
{
|
||||
list_add_tail(&entry->node, &evlist->entries);
|
||||
entry->idx = evlist->nr_entries;
|
||||
|
||||
if (!evlist->nr_entries++)
|
||||
perf_evlist__set_id_pos(evlist);
|
||||
}
|
||||
@@ -165,7 +167,7 @@ int perf_evlist__add_default(struct perf_evlist *evlist)
|
||||
|
||||
event_attr_init(&attr);
|
||||
|
||||
evsel = perf_evsel__new(&attr, 0);
|
||||
evsel = perf_evsel__new(&attr);
|
||||
if (evsel == NULL)
|
||||
goto error;
|
||||
|
||||
@@ -190,7 +192,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist,
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < nr_attrs; i++) {
|
||||
evsel = perf_evsel__new(attrs + i, evlist->nr_entries + i);
|
||||
evsel = perf_evsel__new_idx(attrs + i, evlist->nr_entries + i);
|
||||
if (evsel == NULL)
|
||||
goto out_delete_partial_list;
|
||||
list_add_tail(&evsel->node, &head);
|
||||
@@ -249,9 +251,8 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
|
||||
int perf_evlist__add_newtp(struct perf_evlist *evlist,
|
||||
const char *sys, const char *name, void *handler)
|
||||
{
|
||||
struct perf_evsel *evsel;
|
||||
struct perf_evsel *evsel = perf_evsel__newtp(sys, name);
|
||||
|
||||
evsel = perf_evsel__newtp(sys, name, evlist->nr_entries);
|
||||
if (evsel == NULL)
|
||||
return -1;
|
||||
|
||||
@@ -704,12 +705,10 @@ static size_t perf_evlist__mmap_size(unsigned long pages)
|
||||
return (pages + 1) * page_size;
|
||||
}
|
||||
|
||||
int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
|
||||
int unset __maybe_unused)
|
||||
static long parse_pages_arg(const char *str, unsigned long min,
|
||||
unsigned long max)
|
||||
{
|
||||
unsigned int *mmap_pages = opt->value;
|
||||
unsigned long pages, val;
|
||||
size_t size;
|
||||
static struct parse_tag tags[] = {
|
||||
{ .tag = 'B', .mult = 1 },
|
||||
{ .tag = 'K', .mult = 1 << 10 },
|
||||
@@ -718,33 +717,49 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
|
||||
{ .tag = 0 },
|
||||
};
|
||||
|
||||
if (str == NULL)
|
||||
return -EINVAL;
|
||||
|
||||
val = parse_tag_value(str, tags);
|
||||
if (val != (unsigned long) -1) {
|
||||
/* we got file size value */
|
||||
pages = PERF_ALIGN(val, page_size) / page_size;
|
||||
if (pages < (1UL << 31) && !is_power_of_2(pages)) {
|
||||
pages = next_pow2(pages);
|
||||
pr_info("rounding mmap pages size to %lu (%lu pages)\n",
|
||||
pages * page_size, pages);
|
||||
}
|
||||
} else {
|
||||
/* we got pages count value */
|
||||
char *eptr;
|
||||
pages = strtoul(str, &eptr, 10);
|
||||
if (*eptr != '\0') {
|
||||
pr_err("failed to parse --mmap_pages/-m value\n");
|
||||
return -1;
|
||||
}
|
||||
if (*eptr != '\0')
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (pages > UINT_MAX || pages > SIZE_MAX / page_size) {
|
||||
pr_err("--mmap_pages/-m value too big\n");
|
||||
return -1;
|
||||
if ((pages == 0) && (min == 0)) {
|
||||
/* leave number of pages at 0 */
|
||||
} else if (pages < (1UL << 31) && !is_power_of_2(pages)) {
|
||||
/* round pages up to next power of 2 */
|
||||
pages = next_pow2(pages);
|
||||
pr_info("rounding mmap pages size to %lu bytes (%lu pages)\n",
|
||||
pages * page_size, pages);
|
||||
}
|
||||
|
||||
size = perf_evlist__mmap_size(pages);
|
||||
if (!size) {
|
||||
pr_err("--mmap_pages/-m value must be a power of two.");
|
||||
if (pages > max)
|
||||
return -EINVAL;
|
||||
|
||||
return pages;
|
||||
}
|
||||
|
||||
int perf_evlist__parse_mmap_pages(const struct option *opt, const char *str,
|
||||
int unset __maybe_unused)
|
||||
{
|
||||
unsigned int *mmap_pages = opt->value;
|
||||
unsigned long max = UINT_MAX;
|
||||
long pages;
|
||||
|
||||
if (max < SIZE_MAX / page_size)
|
||||
max = SIZE_MAX / page_size;
|
||||
|
||||
pages = parse_pages_arg(str, 1, max);
|
||||
if (pages < 0) {
|
||||
pr_err("Invalid argument for --mmap_pages/-m\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -796,8 +811,7 @@ int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages,
|
||||
return perf_evlist__mmap_per_cpu(evlist, prot, mask);
|
||||
}
|
||||
|
||||
int perf_evlist__create_maps(struct perf_evlist *evlist,
|
||||
struct perf_target *target)
|
||||
int perf_evlist__create_maps(struct perf_evlist *evlist, struct target *target)
|
||||
{
|
||||
evlist->threads = thread_map__new_str(target->pid, target->tid,
|
||||
target->uid);
|
||||
@@ -805,9 +819,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist,
|
||||
if (evlist->threads == NULL)
|
||||
return -1;
|
||||
|
||||
if (perf_target__has_task(target))
|
||||
if (target__has_task(target))
|
||||
evlist->cpus = cpu_map__dummy_new();
|
||||
else if (!perf_target__has_cpu(target) && !target->uses_mmap)
|
||||
else if (!target__has_cpu(target) && !target->uses_mmap)
|
||||
evlist->cpus = cpu_map__dummy_new();
|
||||
else
|
||||
evlist->cpus = cpu_map__new(target->cpu_list);
|
||||
@@ -1016,8 +1030,7 @@ out_err:
|
||||
return err;
|
||||
}
|
||||
|
||||
int perf_evlist__prepare_workload(struct perf_evlist *evlist,
|
||||
struct perf_target *target,
|
||||
int perf_evlist__prepare_workload(struct perf_evlist *evlist, struct target *target,
|
||||
const char *argv[], bool pipe_output,
|
||||
bool want_signal)
|
||||
{
|
||||
@@ -1069,7 +1082,7 @@ int perf_evlist__prepare_workload(struct perf_evlist *evlist,
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (perf_target__none(target))
|
||||
if (target__none(target))
|
||||
evlist->threads->map[0] = evlist->workload.pid;
|
||||
|
||||
close(child_ready_pipe[1]);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user