Fixes for perf/urgent
. Fix fallback to --stdio when TUI not supported, from Namhyung Kim. . Use right cast for pointers/long in libtraceevent, from Namhyung Kim. . Be consistent on using the right error reporting interface for fatal errors, from Namhyung Kim. . Fix fallback to --stdio when TUI not supported, from Namhyung Kim. . Use the right index in asm only view in the annotate browser. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.14 (GNU/Linux) iQIcBAABAgAGBQJPxWNBAAoJENZQFvNTUqpA3uUQAIiWGKi92UQqEqBYxMni2STT YxelXCmN3O9D69YkYRNq3IJLTAWNEYD0b8/sR0IRVUky5tNBbw0Ssbylris+29JL 3tamcDmhPUtIs/YYM6UxkdD9e6t/xCSqoMtxcm1jRjdBXHP2QNbN+SXe48hnrOyk gUQRna8oY1rsUx8p8xK5V/vLy7zt0Y7sEqwTictU2+M26Wm59w54Yt+cXNcKNFlv KRCabf9hwQf7WHCwRNn/RxA+aEjYj/zkH+GCO0VqzKiwMzU9hevOOggsNo1tJaiM S7vW9FJKxUfek7XIVVIeKhE0j09l2gwRZM6HPpchwmrOCB5yuGNOTifJ4OJxoNgy uk5GtkFOwnUkeJhG+jSFDVIsr7x9UAS10lmsoBWacWBWgrxDDRYQidCUPTGHpnBz P480Y0ld+6vChNxrrJa+TQYu2cyuEaTFRRxsoMCHwC1bKWYLv+KBRIWcUsDbVfHd JHR3dJBBMVIGgLgEVcttNP7rxrq0NGccvE3LPe7RhHe1b2xx1NyYcdTAvzyJb+9c 10kW1qLmmEO8sT0gZDFso/KalCPO+l31mv2u/7RnV2OlslvNwbSP7XJBRlg4Kidg J8qh4LNVbSV/Wcbsh1F4MT0sZcuNV2nec6kjFYXfmhD7SYGAnZt7ypUdUA5m8fPB LbJdC6A/G5ZOJYlJaXXg =O7Yi -----END PGP SIGNATURE----- Merge tag 'perf-urgent-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/urgent Fixes for perf/urgent from Arnaldo Carvalho de Melo: * Fix fallback to --stdio when TUI not supported, from Namhyung Kim. * Use right cast for pointers/long in libtraceevent, from Namhyung Kim. * Be consistent on using the right error reporting interface for fatal errors, from Namhyung Kim. * Fix fallback to --stdio when TUI not supported, from Namhyung Kim. * Use the right index in asm only view in the annotate browser. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
55b78e34b1
13 changed files with 150 additions and 60 deletions
|
@ -1584,7 +1584,7 @@ get_value(struct event_format *event,
|
|||
const char *name;
|
||||
|
||||
name = get_comm(event, record);
|
||||
return (unsigned long long)name;
|
||||
return (unsigned long)name;
|
||||
}
|
||||
|
||||
pevent_read_number_field(field, record->data, &val);
|
||||
|
|
|
@ -80,7 +80,7 @@ ifeq ("$(origin DEBUG)", "command line")
|
|||
PERF_DEBUG = $(DEBUG)
|
||||
endif
|
||||
ifndef PERF_DEBUG
|
||||
CFLAGS_OPTIMIZE = -O6
|
||||
CFLAGS_OPTIMIZE = -O6 -D_FORTIFY_SOURCE=2
|
||||
endif
|
||||
|
||||
ifdef PARSER_DEBUG
|
||||
|
@ -89,7 +89,7 @@ ifdef PARSER_DEBUG
|
|||
PARSER_DEBUG_CFLAGS := -DPARSER_DEBUG
|
||||
endif
|
||||
|
||||
CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) -D_FORTIFY_SOURCE=2 $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS)
|
||||
CFLAGS = -fno-omit-frame-pointer -ggdb3 -Wall -Wextra -std=gnu99 $(CFLAGS_WERROR) $(CFLAGS_OPTIMIZE) $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) $(PARSER_DEBUG_CFLAGS)
|
||||
EXTLIBS = -lpthread -lrt -lelf -lm
|
||||
ALL_CFLAGS = $(CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
|
||||
ALL_LDFLAGS = $(LDFLAGS)
|
||||
|
|
|
@ -215,7 +215,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
|
|||
}
|
||||
|
||||
if (total_nr_samples == 0) {
|
||||
ui__warning("The %s file has no samples!\n", session->filename);
|
||||
ui__error("The %s file has no samples!\n", session->filename);
|
||||
goto out_delete;
|
||||
}
|
||||
out_delete:
|
||||
|
|
|
@ -264,7 +264,7 @@ static void perf_record__open(struct perf_record *rec)
|
|||
}
|
||||
|
||||
if (err == ENOENT) {
|
||||
ui__warning("The %s event is not supported.\n",
|
||||
ui__error("The %s event is not supported.\n",
|
||||
event_name(pos));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
@ -858,8 +858,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
|
|||
usage_with_options(record_usage, record_options);
|
||||
|
||||
if (rec->force && rec->append_file) {
|
||||
fprintf(stderr, "Can't overwrite and append at the same time."
|
||||
" You need to choose between -f and -A");
|
||||
ui__error("Can't overwrite and append at the same time."
|
||||
" You need to choose between -f and -A");
|
||||
usage_with_options(record_usage, record_options);
|
||||
} else if (rec->append_file) {
|
||||
rec->write_mode = WRITE_APPEND;
|
||||
|
@ -868,8 +868,8 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
|
|||
}
|
||||
|
||||
if (nr_cgroups && !rec->opts.target.system_wide) {
|
||||
fprintf(stderr, "cgroup monitoring only available in"
|
||||
" system-wide mode\n");
|
||||
ui__error("cgroup monitoring only available in"
|
||||
" system-wide mode\n");
|
||||
usage_with_options(record_usage, record_options);
|
||||
}
|
||||
|
||||
|
@ -905,7 +905,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
|
|||
int saved_errno = errno;
|
||||
|
||||
perf_target__strerror(&rec->opts.target, err, errbuf, BUFSIZ);
|
||||
ui__warning("%s", errbuf);
|
||||
ui__error("%s", errbuf);
|
||||
|
||||
err = -saved_errno;
|
||||
goto out_free_fd;
|
||||
|
@ -933,7 +933,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
|
|||
else if (rec->opts.freq) {
|
||||
rec->opts.default_interval = rec->opts.freq;
|
||||
} else {
|
||||
fprintf(stderr, "frequency and count are zero, aborting\n");
|
||||
ui__error("frequency and count are zero, aborting\n");
|
||||
err = -EINVAL;
|
||||
goto out_free_fd;
|
||||
}
|
||||
|
|
|
@ -251,13 +251,13 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
|
|||
|
||||
if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
|
||||
if (sort__has_parent) {
|
||||
ui__warning("Selected --sort parent, but no "
|
||||
ui__error("Selected --sort parent, but no "
|
||||
"callchain data. Did you call "
|
||||
"'perf record' without -g?\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (symbol_conf.use_callchain) {
|
||||
ui__warning("Selected -g but no callchain data. Did "
|
||||
ui__error("Selected -g but no callchain data. Did "
|
||||
"you call 'perf record' without -g?\n");
|
||||
return -1;
|
||||
}
|
||||
|
@ -266,17 +266,15 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
|
|||
!symbol_conf.use_callchain) {
|
||||
symbol_conf.use_callchain = true;
|
||||
if (callchain_register_param(&callchain_param) < 0) {
|
||||
ui__warning("Can't register callchain "
|
||||
"params.\n");
|
||||
ui__error("Can't register callchain params.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (sort__branch_mode == 1) {
|
||||
if (!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
|
||||
fprintf(stderr, "selected -b but no branch data."
|
||||
" Did you call perf record without"
|
||||
" -b?\n");
|
||||
ui__error("Selected -b but no branch data. "
|
||||
"Did you call perf record without -b?\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -420,7 +418,7 @@ static int __cmd_report(struct perf_report *rep)
|
|||
}
|
||||
|
||||
if (nr_samples == 0) {
|
||||
ui__warning("The %s file has no samples!\n", session->filename);
|
||||
ui__error("The %s file has no samples!\n", session->filename);
|
||||
goto out_delete;
|
||||
}
|
||||
|
||||
|
|
|
@ -953,22 +953,22 @@ static void perf_top__start_counters(struct perf_top *top)
|
|||
attr->config = PERF_COUNT_SW_CPU_CLOCK;
|
||||
if (counter->name) {
|
||||
free(counter->name);
|
||||
counter->name = strdup(event_name(counter));
|
||||
counter->name = NULL;
|
||||
}
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
if (err == ENOENT) {
|
||||
ui__warning("The %s event is not supported.\n",
|
||||
ui__error("The %s event is not supported.\n",
|
||||
event_name(counter));
|
||||
goto out_err;
|
||||
} else if (err == EMFILE) {
|
||||
ui__warning("Too many events are opened.\n"
|
||||
ui__error("Too many events are opened.\n"
|
||||
"Try again after reducing the number of events\n");
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
ui__warning("The sys_perf_event_open() syscall "
|
||||
ui__error("The sys_perf_event_open() syscall "
|
||||
"returned with %d (%s). /bin/dmesg "
|
||||
"may provide additional information.\n"
|
||||
"No CONFIG_PERF_EVENTS=y kernel support "
|
||||
|
@ -978,7 +978,7 @@ static void perf_top__start_counters(struct perf_top *top)
|
|||
}
|
||||
|
||||
if (perf_evlist__mmap(evlist, top->mmap_pages, false) < 0) {
|
||||
ui__warning("Failed to mmap with %d (%s)\n",
|
||||
ui__error("Failed to mmap with %d (%s)\n",
|
||||
errno, strerror(errno));
|
||||
goto out_err;
|
||||
}
|
||||
|
@ -994,12 +994,12 @@ static int perf_top__setup_sample_type(struct perf_top *top)
|
|||
{
|
||||
if (!top->sort_has_symbols) {
|
||||
if (symbol_conf.use_callchain) {
|
||||
ui__warning("Selected -g but \"sym\" not present in --sort/-s.");
|
||||
ui__error("Selected -g but \"sym\" not present in --sort/-s.");
|
||||
return -EINVAL;
|
||||
}
|
||||
} else if (!top->dont_use_callchains && callchain_param.mode != CHAIN_NONE) {
|
||||
if (callchain_register_param(&callchain_param) < 0) {
|
||||
ui__warning("Can't register callchain params.\n");
|
||||
ui__error("Can't register callchain params.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
@ -1041,7 +1041,7 @@ static int __cmd_top(struct perf_top *top)
|
|||
|
||||
if (pthread_create(&thread, NULL, (use_browser > 0 ? display_thread_tui :
|
||||
display_thread), top)) {
|
||||
printf("Could not create display thread.\n");
|
||||
ui__error("Could not create display thread.\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
@ -1050,7 +1050,7 @@ static int __cmd_top(struct perf_top *top)
|
|||
|
||||
param.sched_priority = top->realtime_prio;
|
||||
if (sched_setscheduler(0, SCHED_FIFO, ¶m)) {
|
||||
printf("Could not set realtime priority.\n");
|
||||
ui__error("Could not set realtime priority.\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
@ -1274,7 +1274,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
|
|||
int saved_errno = errno;
|
||||
|
||||
perf_target__strerror(&top.target, status, errbuf, BUFSIZ);
|
||||
ui__warning("%s", errbuf);
|
||||
ui__error("%s", errbuf);
|
||||
|
||||
status = -saved_errno;
|
||||
goto out_delete_evlist;
|
||||
|
@ -1288,7 +1288,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
|
|||
|
||||
if (!top.evlist->nr_entries &&
|
||||
perf_evlist__add_default(top.evlist) < 0) {
|
||||
pr_err("Not enough memory for event selector list\n");
|
||||
ui__error("Not enough memory for event selector list\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
|
@ -1305,7 +1305,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __used)
|
|||
else if (top.freq) {
|
||||
top.default_interval = top.freq;
|
||||
} else {
|
||||
fprintf(stderr, "frequency and count are zero, aborting\n");
|
||||
ui__error("frequency and count are zero, aborting\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
|
|
@ -227,7 +227,7 @@ struct perf_record_opts {
|
|||
unsigned int freq;
|
||||
unsigned int mmap_pages;
|
||||
unsigned int user_freq;
|
||||
int branch_stack;
|
||||
u64 branch_stack;
|
||||
u64 default_interval;
|
||||
u64 user_interval;
|
||||
};
|
||||
|
|
|
@ -300,10 +300,14 @@ static void annotate_browser__set_rb_top(struct annotate_browser *browser,
|
|||
{
|
||||
struct browser_disasm_line *bpos;
|
||||
struct disasm_line *pos;
|
||||
u32 idx;
|
||||
|
||||
bpos = rb_entry(nd, struct browser_disasm_line, rb_node);
|
||||
pos = ((struct disasm_line *)bpos) - 1;
|
||||
annotate_browser__set_top(browser, pos, bpos->idx);
|
||||
idx = bpos->idx;
|
||||
if (browser->hide_src_code)
|
||||
idx = bpos->idx_asm;
|
||||
annotate_browser__set_top(browser, pos, idx);
|
||||
browser->curr_hot = nd;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ void setup_browser(bool fallback_to_pager)
|
|||
break;
|
||||
/* fall through */
|
||||
default:
|
||||
use_browser = 0;
|
||||
if (fallback_to_pager)
|
||||
setup_pager();
|
||||
break;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "cpumap.h"
|
||||
#include "thread_map.h"
|
||||
#include "target.h"
|
||||
#include "../../include/linux/perf_event.h"
|
||||
|
||||
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
|
||||
#define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
|
||||
|
@ -64,6 +65,95 @@ struct perf_evsel *perf_evsel__new(struct perf_event_attr *attr, int idx)
|
|||
return evsel;
|
||||
}
|
||||
|
||||
static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
|
||||
"cycles",
|
||||
"instructions",
|
||||
"cache-references",
|
||||
"cache-misses",
|
||||
"branches",
|
||||
"branch-misses",
|
||||
"bus-cycles",
|
||||
"stalled-cycles-frontend",
|
||||
"stalled-cycles-backend",
|
||||
"ref-cycles",
|
||||
};
|
||||
|
||||
const char *__perf_evsel__hw_name(u64 config)
|
||||
{
|
||||
if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
|
||||
return perf_evsel__hw_names[config];
|
||||
|
||||
return "unknown-hardware";
|
||||
}
|
||||
|
||||
static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
|
||||
{
|
||||
int colon = 0;
|
||||
struct perf_event_attr *attr = &evsel->attr;
|
||||
int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(attr->config));
|
||||
bool exclude_guest_default = false;
|
||||
|
||||
#define MOD_PRINT(context, mod) do { \
|
||||
if (!attr->exclude_##context) { \
|
||||
if (!colon) colon = r++; \
|
||||
r += scnprintf(bf + r, size - r, "%c", mod); \
|
||||
} } while(0)
|
||||
|
||||
if (attr->exclude_kernel || attr->exclude_user || attr->exclude_hv) {
|
||||
MOD_PRINT(kernel, 'k');
|
||||
MOD_PRINT(user, 'u');
|
||||
MOD_PRINT(hv, 'h');
|
||||
exclude_guest_default = true;
|
||||
}
|
||||
|
||||
if (attr->precise_ip) {
|
||||
if (!colon)
|
||||
colon = r++;
|
||||
r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
|
||||
exclude_guest_default = true;
|
||||
}
|
||||
|
||||
if (attr->exclude_host || attr->exclude_guest == exclude_guest_default) {
|
||||
MOD_PRINT(host, 'H');
|
||||
MOD_PRINT(guest, 'G');
|
||||
}
|
||||
#undef MOD_PRINT
|
||||
if (colon)
|
||||
bf[colon] = ':';
|
||||
return r;
|
||||
}
|
||||
|
||||
int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (evsel->attr.type) {
|
||||
case PERF_TYPE_RAW:
|
||||
ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
|
||||
break;
|
||||
|
||||
case PERF_TYPE_HARDWARE:
|
||||
ret = perf_evsel__hw_name(evsel, bf, size);
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* FIXME
|
||||
*
|
||||
* This is the minimal perf_evsel__name so that we can
|
||||
* reconstruct event names taking into account event modifiers.
|
||||
*
|
||||
* The old event_name uses it now for raw anr hw events, so that
|
||||
* we don't drag all the parsing stuff into the python binding.
|
||||
*
|
||||
* On the next devel cycle the rest of the event naming will be
|
||||
* brought here.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
|
||||
struct perf_evsel *first)
|
||||
{
|
||||
|
|
|
@ -83,6 +83,9 @@ void perf_evsel__config(struct perf_evsel *evsel,
|
|||
struct perf_record_opts *opts,
|
||||
struct perf_evsel *first);
|
||||
|
||||
const char* __perf_evsel__hw_name(u64 config);
|
||||
int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size);
|
||||
|
||||
int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
|
||||
int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
|
||||
int perf_evsel__alloc_counts(struct perf_evsel *evsel, int ncpus);
|
||||
|
|
|
@ -62,19 +62,6 @@ static struct event_symbol event_symbols[] = {
|
|||
#define PERF_EVENT_TYPE(config) __PERF_EVENT_FIELD(config, TYPE)
|
||||
#define PERF_EVENT_ID(config) __PERF_EVENT_FIELD(config, EVENT)
|
||||
|
||||
static const char *hw_event_names[PERF_COUNT_HW_MAX] = {
|
||||
"cycles",
|
||||
"instructions",
|
||||
"cache-references",
|
||||
"cache-misses",
|
||||
"branches",
|
||||
"branch-misses",
|
||||
"bus-cycles",
|
||||
"stalled-cycles-frontend",
|
||||
"stalled-cycles-backend",
|
||||
"ref-cycles",
|
||||
};
|
||||
|
||||
static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
|
||||
"cpu-clock",
|
||||
"task-clock",
|
||||
|
@ -300,6 +287,16 @@ const char *event_name(struct perf_evsel *evsel)
|
|||
u64 config = evsel->attr.config;
|
||||
int type = evsel->attr.type;
|
||||
|
||||
if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) {
|
||||
/*
|
||||
* XXX minimal fix, see comment on perf_evsen__name, this static buffer
|
||||
* will go away together with event_name in the next devel cycle.
|
||||
*/
|
||||
static char bf[128];
|
||||
perf_evsel__name(evsel, bf, sizeof(bf));
|
||||
return bf;
|
||||
}
|
||||
|
||||
if (evsel->name)
|
||||
return evsel->name;
|
||||
|
||||
|
@ -317,9 +314,7 @@ const char *__event_name(int type, u64 config)
|
|||
|
||||
switch (type) {
|
||||
case PERF_TYPE_HARDWARE:
|
||||
if (config < PERF_COUNT_HW_MAX && hw_event_names[config])
|
||||
return hw_event_names[config];
|
||||
return "unknown-hardware";
|
||||
return __perf_evsel__hw_name(config);
|
||||
|
||||
case PERF_TYPE_HW_CACHE: {
|
||||
u8 cache_type, cache_op, cache_result;
|
||||
|
|
|
@ -188,28 +188,27 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
|
|||
nt = realloc(threads, (sizeof(*threads) +
|
||||
sizeof(pid_t) * total_tasks));
|
||||
if (nt == NULL)
|
||||
goto out_free_threads;
|
||||
goto out_free_namelist;
|
||||
|
||||
threads = nt;
|
||||
|
||||
if (threads) {
|
||||
for (i = 0; i < items; i++)
|
||||
threads->map[j++] = atoi(namelist[i]->d_name);
|
||||
threads->nr = total_tasks;
|
||||
}
|
||||
|
||||
for (i = 0; i < items; i++)
|
||||
for (i = 0; i < items; i++) {
|
||||
threads->map[j++] = atoi(namelist[i]->d_name);
|
||||
free(namelist[i]);
|
||||
}
|
||||
threads->nr = total_tasks;
|
||||
free(namelist);
|
||||
|
||||
if (!threads)
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
strlist__delete(slist);
|
||||
return threads;
|
||||
|
||||
out_free_namelist:
|
||||
for (i = 0; i < items; i++)
|
||||
free(namelist[i]);
|
||||
free(namelist);
|
||||
|
||||
out_free_threads:
|
||||
free(threads);
|
||||
threads = NULL;
|
||||
|
|
Loading…
Reference in a new issue