Commit b6b6c18f 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 features:

  - Deref sys_enter pointer args with contents from probe:vfs_getname, showing
    pathnames instead of pointers in many syscalls in 'perf trace'. (Arnaldo Carvalho de Melo)

  - Make 'perf trace' write to stderr by default, just like 'strace'. (Milian Woff)

Infrastructure changes:

  - color_vfprintf() fixes. (Andi Kleen, Jiri Olsa)

  - Allow enabling/disabling PERF_SAMPLE_TIME per event. (Kan Liang)

  - Fix build errors with mipsel-linux-uclibc compiler. (Petri Gynther)
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 75f80859 f151f53a
#include <stdlib.h>
#if !defined(__UCLIBC__)
#include <gnu/libc-version.h> #include <gnu/libc-version.h>
#else
#define XSTR(s) STR(s)
#define STR(s) #s
#endif
int main(void) int main(void)
{ {
#if !defined(__UCLIBC__)
const char *version = gnu_get_libc_version(); const char *version = gnu_get_libc_version();
#else
const char *version = XSTR(__GLIBC__) "." XSTR(__GLIBC_MINOR__);
#endif
return (long)version; return (long)version;
} }
...@@ -49,7 +49,9 @@ OPTIONS ...@@ -49,7 +49,9 @@ OPTIONS
These params can be used to overload default config values per event. These params can be used to overload default config values per event.
Here is a list of the params. Here is a list of the params.
- 'period': Set event sampling period - 'period': Set event sampling period
- 'time': Disable/enable time stamping. Acceptable values are 1 for
enabling time stamping. 0 for disabling time stamping.
The default is 1.
Note: If user explicitly sets options which conflict with the params, Note: If user explicitly sets options which conflict with the params,
the value set by the params will be overridden. the value set by the params will be overridden.
......
...@@ -779,7 +779,7 @@ int record_parse_callchain_opt(const struct option *opt, ...@@ -779,7 +779,7 @@ int record_parse_callchain_opt(const struct option *opt,
return 0; return 0;
} }
ret = parse_callchain_record_opt(arg); ret = parse_callchain_record_opt(arg, &callchain_param);
if (!ret) if (!ret)
callchain_debug(); callchain_debug();
......
...@@ -1861,7 +1861,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) ...@@ -1861,7 +1861,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
else else
symbol_conf.use_callchain = false; symbol_conf.use_callchain = false;
if (pevent_set_function_resolver(session->tevent.pevent, if (session->tevent.pevent &&
pevent_set_function_resolver(session->tevent.pevent,
machine__resolve_kernel_addr, machine__resolve_kernel_addr,
&session->machines.host) < 0) { &session->machines.host) < 0) {
pr_err("%s: failed to set libtraceevent function resolver\n", __func__); pr_err("%s: failed to set libtraceevent function resolver\n", __func__);
......
This diff is collapsed.
...@@ -53,7 +53,7 @@ static int get_stack_size(const char *str, unsigned long *_size) ...@@ -53,7 +53,7 @@ static int get_stack_size(const char *str, unsigned long *_size)
} }
#endif /* HAVE_DWARF_UNWIND_SUPPORT */ #endif /* HAVE_DWARF_UNWIND_SUPPORT */
int parse_callchain_record_opt(const char *arg) int parse_callchain_record_opt(const char *arg, struct callchain_param *param)
{ {
char *tok, *name, *saveptr = NULL; char *tok, *name, *saveptr = NULL;
char *buf; char *buf;
...@@ -73,7 +73,7 @@ int parse_callchain_record_opt(const char *arg) ...@@ -73,7 +73,7 @@ int parse_callchain_record_opt(const char *arg)
/* Framepointer style */ /* Framepointer style */
if (!strncmp(name, "fp", sizeof("fp"))) { if (!strncmp(name, "fp", sizeof("fp"))) {
if (!strtok_r(NULL, ",", &saveptr)) { if (!strtok_r(NULL, ",", &saveptr)) {
callchain_param.record_mode = CALLCHAIN_FP; param->record_mode = CALLCHAIN_FP;
ret = 0; ret = 0;
} else } else
pr_err("callchain: No more arguments " pr_err("callchain: No more arguments "
...@@ -86,20 +86,20 @@ int parse_callchain_record_opt(const char *arg) ...@@ -86,20 +86,20 @@ int parse_callchain_record_opt(const char *arg)
const unsigned long default_stack_dump_size = 8192; const unsigned long default_stack_dump_size = 8192;
ret = 0; ret = 0;
callchain_param.record_mode = CALLCHAIN_DWARF; param->record_mode = CALLCHAIN_DWARF;
callchain_param.dump_size = default_stack_dump_size; param->dump_size = default_stack_dump_size;
tok = strtok_r(NULL, ",", &saveptr); tok = strtok_r(NULL, ",", &saveptr);
if (tok) { if (tok) {
unsigned long size = 0; unsigned long size = 0;
ret = get_stack_size(tok, &size); ret = get_stack_size(tok, &size);
callchain_param.dump_size = size; param->dump_size = size;
} }
#endif /* HAVE_DWARF_UNWIND_SUPPORT */ #endif /* HAVE_DWARF_UNWIND_SUPPORT */
} else if (!strncmp(name, "lbr", sizeof("lbr"))) { } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
if (!strtok_r(NULL, ",", &saveptr)) { if (!strtok_r(NULL, ",", &saveptr)) {
callchain_param.record_mode = CALLCHAIN_LBR; param->record_mode = CALLCHAIN_LBR;
ret = 0; ret = 0;
} else } else
pr_err("callchain: No more arguments " pr_err("callchain: No more arguments "
...@@ -219,7 +219,7 @@ int perf_callchain_config(const char *var, const char *value) ...@@ -219,7 +219,7 @@ int perf_callchain_config(const char *var, const char *value)
var += sizeof("call-graph.") - 1; var += sizeof("call-graph.") - 1;
if (!strcmp(var, "record-mode")) if (!strcmp(var, "record-mode"))
return parse_callchain_record_opt(value); return parse_callchain_record_opt(value, &callchain_param);
#ifdef HAVE_DWARF_UNWIND_SUPPORT #ifdef HAVE_DWARF_UNWIND_SUPPORT
if (!strcmp(var, "dump-size")) { if (!strcmp(var, "dump-size")) {
unsigned long size = 0; unsigned long size = 0;
......
...@@ -177,7 +177,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node * ...@@ -177,7 +177,7 @@ int fill_callchain_info(struct addr_location *al, struct callchain_cursor_node *
bool hide_unresolved); bool hide_unresolved);
extern const char record_callchain_help[]; extern const char record_callchain_help[];
int parse_callchain_record_opt(const char *arg); int parse_callchain_record_opt(const char *arg, struct callchain_param *param);
int parse_callchain_report_opt(const char *arg); int parse_callchain_report_opt(const char *arg);
int perf_callchain_config(const char *var, const char *value); int perf_callchain_config(const char *var, const char *value);
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
unsigned long perf_event_open_cloexec_flag(void); unsigned long perf_event_open_cloexec_flag(void);
#ifdef __GLIBC_PREREQ #ifdef __GLIBC_PREREQ
#if !__GLIBC_PREREQ(2, 6) #if !__GLIBC_PREREQ(2, 6) && !defined(__UCLIBC__)
extern int sched_getcpu(void) __THROW; extern int sched_getcpu(void) __THROW;
#endif #endif
#endif #endif
......
...@@ -67,8 +67,9 @@ static int __color_vsnprintf(char *bf, size_t size, const char *color, ...@@ -67,8 +67,9 @@ static int __color_vsnprintf(char *bf, size_t size, const char *color,
return r; return r;
} }
/* Colors are not included in return value */
static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
va_list args, const char *trail) va_list args)
{ {
int r = 0; int r = 0;
...@@ -83,12 +84,10 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt, ...@@ -83,12 +84,10 @@ static int __color_vfprintf(FILE *fp, const char *color, const char *fmt,
} }
if (perf_use_color_default && *color) if (perf_use_color_default && *color)
r += fprintf(fp, "%s", color); fprintf(fp, "%s", color);
r += vfprintf(fp, fmt, args); r += vfprintf(fp, fmt, args);
if (perf_use_color_default && *color) if (perf_use_color_default && *color)
r += fprintf(fp, "%s", PERF_COLOR_RESET); fprintf(fp, "%s", PERF_COLOR_RESET);
if (trail)
r += fprintf(fp, "%s", trail);
return r; return r;
} }
...@@ -100,7 +99,7 @@ int color_vsnprintf(char *bf, size_t size, const char *color, ...@@ -100,7 +99,7 @@ int color_vsnprintf(char *bf, size_t size, const char *color,
int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args) int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args)
{ {
return __color_vfprintf(fp, color, fmt, args, NULL); return __color_vfprintf(fp, color, fmt, args);
} }
int color_snprintf(char *bf, size_t size, const char *color, int color_snprintf(char *bf, size_t size, const char *color,
...@@ -126,16 +125,6 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...) ...@@ -126,16 +125,6 @@ int color_fprintf(FILE *fp, const char *color, const char *fmt, ...)
return r; return r;
} }
int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...)
{
va_list args;
int r;
va_start(args, fmt);
r = __color_vfprintf(fp, color, fmt, args, "\n");
va_end(args);
return r;
}
/* /*
* This function splits the buffer by newlines and colors the lines individually. * This function splits the buffer by newlines and colors the lines individually.
* *
......
...@@ -35,7 +35,6 @@ int color_vsnprintf(char *bf, size_t size, const char *color, ...@@ -35,7 +35,6 @@ int color_vsnprintf(char *bf, size_t size, const char *color,
int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args); int color_vfprintf(FILE *fp, const char *color, const char *fmt, va_list args);
int color_fprintf(FILE *fp, const char *color, const char *fmt, ...); int color_fprintf(FILE *fp, const char *color, const char *fmt, ...);
int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...); int color_snprintf(char *bf, size_t size, const char *color, const char *fmt, ...);
int color_fprintf_ln(FILE *fp, const char *color, const char *fmt, ...);
int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf); int color_fwrite_lines(FILE *fp, const char *color, size_t count, const char *buf);
int value_color_snprintf(char *bf, size_t size, const char *fmt, double value); int value_color_snprintf(char *bf, size_t size, const char *fmt, double value);
int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...); int percent_color_snprintf(char *bf, size_t size, const char *fmt, ...);
......
...@@ -545,14 +545,15 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) ...@@ -545,14 +545,15 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
static void static void
perf_evsel__config_callgraph(struct perf_evsel *evsel, perf_evsel__config_callgraph(struct perf_evsel *evsel,
struct record_opts *opts) struct record_opts *opts,
struct callchain_param *param)
{ {
bool function = perf_evsel__is_function_event(evsel); bool function = perf_evsel__is_function_event(evsel);
struct perf_event_attr *attr = &evsel->attr; struct perf_event_attr *attr = &evsel->attr;
perf_evsel__set_sample_bit(evsel, CALLCHAIN); perf_evsel__set_sample_bit(evsel, CALLCHAIN);
if (callchain_param.record_mode == CALLCHAIN_LBR) { if (param->record_mode == CALLCHAIN_LBR) {
if (!opts->branch_stack) { if (!opts->branch_stack) {
if (attr->exclude_user) { if (attr->exclude_user) {
pr_warning("LBR callstack option is only available " pr_warning("LBR callstack option is only available "
...@@ -568,12 +569,12 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel, ...@@ -568,12 +569,12 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel,
"Falling back to framepointers.\n"); "Falling back to framepointers.\n");
} }
if (callchain_param.record_mode == CALLCHAIN_DWARF) { if (param->record_mode == CALLCHAIN_DWARF) {
if (!function) { if (!function) {
perf_evsel__set_sample_bit(evsel, REGS_USER); perf_evsel__set_sample_bit(evsel, REGS_USER);
perf_evsel__set_sample_bit(evsel, STACK_USER); perf_evsel__set_sample_bit(evsel, STACK_USER);
attr->sample_regs_user = PERF_REGS_MASK; attr->sample_regs_user = PERF_REGS_MASK;
attr->sample_stack_user = callchain_param.dump_size; attr->sample_stack_user = param->dump_size;
attr->exclude_callchain_user = 1; attr->exclude_callchain_user = 1;
} else { } else {
pr_info("Cannot use DWARF unwind for function trace event," pr_info("Cannot use DWARF unwind for function trace event,"
...@@ -587,15 +588,23 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel, ...@@ -587,15 +588,23 @@ perf_evsel__config_callgraph(struct perf_evsel *evsel,
} }
} }
static void apply_config_terms(struct perf_event_attr *attr __maybe_unused, static void apply_config_terms(struct perf_evsel *evsel)
struct list_head *config_terms)
{ {
struct perf_evsel_config_term *term; struct perf_evsel_config_term *term;
struct list_head *config_terms = &evsel->config_terms;
struct perf_event_attr *attr = &evsel->attr;
list_for_each_entry(term, config_terms, list) { list_for_each_entry(term, config_terms, list) {
switch (term->type) { switch (term->type) {
case PERF_EVSEL__CONFIG_TERM_PERIOD: case PERF_EVSEL__CONFIG_TERM_PERIOD:
attr->sample_period = term->val.period; attr->sample_period = term->val.period;
break;
case PERF_EVSEL__CONFIG_TERM_TIME:
if (term->val.time)
perf_evsel__set_sample_bit(evsel, TIME);
else
perf_evsel__reset_sample_bit(evsel, TIME);
break;
default: default:
break; break;
} }
...@@ -706,7 +715,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) ...@@ -706,7 +715,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
evsel->attr.exclude_callchain_user = 1; evsel->attr.exclude_callchain_user = 1;
if (callchain_param.enabled && !evsel->no_aux_samples) if (callchain_param.enabled && !evsel->no_aux_samples)
perf_evsel__config_callgraph(evsel, opts); perf_evsel__config_callgraph(evsel, opts, &callchain_param);
if (opts->sample_intr_regs) { if (opts->sample_intr_regs) {
attr->sample_regs_intr = PERF_REGS_MASK; attr->sample_regs_intr = PERF_REGS_MASK;
...@@ -798,7 +807,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) ...@@ -798,7 +807,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
* Apply event specific term settings, * Apply event specific term settings,
* it overloads any global configuration. * it overloads any global configuration.
*/ */
apply_config_terms(attr, &evsel->config_terms); apply_config_terms(evsel);
} }
static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
......
...@@ -39,6 +39,7 @@ struct cgroup_sel; ...@@ -39,6 +39,7 @@ struct cgroup_sel;
*/ */
enum { enum {
PERF_EVSEL__CONFIG_TERM_PERIOD, PERF_EVSEL__CONFIG_TERM_PERIOD,
PERF_EVSEL__CONFIG_TERM_TIME,
PERF_EVSEL__CONFIG_TERM_MAX, PERF_EVSEL__CONFIG_TERM_MAX,
}; };
...@@ -47,6 +48,7 @@ struct perf_evsel_config_term { ...@@ -47,6 +48,7 @@ struct perf_evsel_config_term {
int type; int type;
union { union {
u64 period; u64 period;
bool time;
} val; } val;
}; };
......
...@@ -603,6 +603,14 @@ do { \ ...@@ -603,6 +603,14 @@ do { \
* attr->branch_sample_type = term->val.num; * attr->branch_sample_type = term->val.num;
*/ */
break; break;
case PARSE_EVENTS__TERM_TYPE_TIME:
CHECK_TYPE_VAL(NUM);
if (term->val.num > 1) {
err->str = strdup("expected 0 or 1");
err->idx = term->err_val;
return -EINVAL;
}
break;
case PARSE_EVENTS__TERM_TYPE_NAME: case PARSE_EVENTS__TERM_TYPE_NAME:
CHECK_TYPE_VAL(STR); CHECK_TYPE_VAL(STR);
break; break;
...@@ -650,6 +658,10 @@ do { \ ...@@ -650,6 +658,10 @@ do { \
switch (term->type_term) { switch (term->type_term) {
case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD: case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
ADD_CONFIG_TERM(PERIOD, period, term->val.num); ADD_CONFIG_TERM(PERIOD, period, term->val.num);
break;
case PARSE_EVENTS__TERM_TYPE_TIME:
ADD_CONFIG_TERM(TIME, time, term->val.num);
break;
default: default:
break; break;
} }
......
...@@ -63,6 +63,7 @@ enum { ...@@ -63,6 +63,7 @@ enum {
PARSE_EVENTS__TERM_TYPE_NAME, PARSE_EVENTS__TERM_TYPE_NAME,
PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD,
PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE,
PARSE_EVENTS__TERM_TYPE_TIME,
}; };
struct parse_events_term { struct parse_events_term {
......
...@@ -183,6 +183,7 @@ config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); } ...@@ -183,6 +183,7 @@ config2 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); } name { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); } period { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); } branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
, { return ','; } , { return ','; }
"/" { BEGIN(INITIAL); return '/'; } "/" { BEGIN(INITIAL); return '/'; }
{name_minus} { return str(yyscanner, PE_NAME); } {name_minus} { return str(yyscanner, PE_NAME); }
......
...@@ -607,7 +607,7 @@ static char *formats_error_string(struct list_head *formats) ...@@ -607,7 +607,7 @@ static char *formats_error_string(struct list_head *formats)
{ {
struct perf_pmu_format *format; struct perf_pmu_format *format;
char *err, *str; char *err, *str;
static const char *static_terms = "config,config1,config2,name,period,branch_type\n"; static const char *static_terms = "config,config1,config2,name,period,branch_type,time\n";
unsigned i = 0; unsigned i = 0;
if (!asprintf(&str, "valid terms:")) if (!asprintf(&str, "valid terms:"))
......
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